diff --git a/src/build.ts b/src/build.ts index 1bd06617..332de177 100644 --- a/src/build.ts +++ b/src/build.ts @@ -57,21 +57,33 @@ function logDiags(diagnostics: Diagnostics[], logger: ILoggingStore) { }); } -export async function extractCandidFromWasm( - wasm: Uint8Array -): Promise { - const mod = await WebAssembly.compile(wasm); - let section = WebAssembly.Module.customSections( - mod, - "icp:public candid:args" - ); +function get_wasm_metadata( + wasm: WebAssembly.Module, + name: string +): string | undefined { + let section = WebAssembly.Module.customSections(wasm, `icp:public ${name}`); if (section.length === 0) { - section = WebAssembly.Module.customSections(mod, "icp:private candid:args"); + section = WebAssembly.Module.customSections(wasm, `icp:private ${name}`); } if (section.length === 0) { - throw new Error("Cannot find candid:args metadata in Wasm module"); + return undefined; + } + const decoder = new TextDecoder(); + const bytes = new Uint8Array(section[0]); + const str = decoder.decode(bytes); + return str; +} + +export async function extractCandidFromWasm( + wasm: Uint8Array +): Promise<[string, undefined | string]> { + const mod = await WebAssembly.compile(wasm); + const serv = get_wasm_metadata(mod, "candid:service"); + if (!serv) { + throw new Error("Cannot find candid:service metadata in Wasm module"); } - return section; + const init = get_wasm_metadata(mod, "candid:args"); + return [serv, init]; } export async function compileCandid( diff --git a/src/components/CanisterModal.tsx b/src/components/CanisterModal.tsx index aa8bce21..bdd6bce9 100644 --- a/src/components/CanisterModal.tsx +++ b/src/components/CanisterModal.tsx @@ -101,6 +101,7 @@ export function CanisterModal({ isOpen, close, deploySetter }) { async function deployWasm() { if (!candid || !wasm) return; + setError(""); const candidJS = await didToJs(candid); const init = candidJS.init({ IDL }); await close(); @@ -157,8 +158,17 @@ export function CanisterModal({ isOpen, close, deploySetter }) { const wasm = new Uint8Array(reader.result); setWasm(wasm); try { - const init = await extractCandidFromWasm(wasm); - console.log(init); + const [serv, init] = await extractCandidFromWasm(wasm); + if (init) { + const candid = (await didjs.merge_init_args(serv, init))[0]; + if (!candid) { + setError("Cannot merge candid:args with candid:service from Wasm"); + return; + } + setCandid(candid); + } else { + setCandid(serv); + } } catch (e) { setError(e.toString()); } @@ -238,12 +248,14 @@ export function CanisterModal({ isOpen, close, deploySetter }) { accept=".wasm" onChange={handleWasmUpload} /> - + {error && ( + + )} {error && {error}} diff --git a/src/didjs.did.js b/src/didjs.did.js index d4ead032..36d430ce 100644 --- a/src/didjs.did.js +++ b/src/didjs.did.js @@ -7,6 +7,11 @@ export const idlFactory = ({ IDL }) => { [IDL.Variant({ Ok: IDL.Null, Err: IDL.Text })], ["query"] ), + merge_init_args: IDL.Func( + [IDL.Text, IDL.Text], + [IDL.Opt(IDL.Text)], + ["query"] + ), }); }; export const init = ({ IDL }) => {