Skip to content

Commit 0e23227

Browse files
authored
feat(ui): use candid:service metadata to lookup did (#736)
Update after: This is to be updated after #735 is merged There's a been a "temporary hack" since 2022 - I spot checked canisters and they seem to have the standard "candid:service" metadata, eg: ``` # bitcoin minter icp canister metadata -n ic mqygn-kiaaa-aaaar-qaadq-cai "candid:service" ```
1 parent ac2ef66 commit 0e23227

1 file changed

Lines changed: 14 additions & 27 deletions

File tree

tools/ui/src/candid.ts

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,9 @@ export async function fetchActor(canisterId: Principal): Promise<ActorSubclass>
7878
}
7979
}
8080
if (!js) {
81+
// Read the interface from the canister's `candid:service` metadata — the
82+
// standard, certified way for a canister to expose its Candid interface.
8183
js = await getDidJsFromMetadata(canisterId);
82-
if (!js) {
83-
try {
84-
js = await getDidJsFromTmpHack(canisterId);
85-
} catch(err) {
86-
if (/no query method/.test(err as any)) {
87-
console.warn(err);
88-
js = undefined;
89-
} else {
90-
throw(err);
91-
}
92-
}
93-
}
9484
}
9585
if (!js) {
9686
throw new Error('Cannot fetch candid file');
@@ -201,14 +191,20 @@ async function getDidJsFromPostMessage(canisterId: Principal): Promise<undefined
201191
return new Promise((resolve,reject)=>{})
202192
}
203193

194+
204195
async function getDidJsFromMetadata(canisterId: Principal): Promise<undefined | string> {
205-
const status = await CanisterStatus.request({ agent, canisterId, paths: ['candid'] });
206-
const did = status.get('candid') as string | null;
207-
if (did) {
208-
return didToJs(did);
209-
} else {
210-
return undefined;
196+
// The 'candid' path resolves to the `candid:service` metadata section and is
197+
// read (and certified) via the canister's read_state endpoint.
198+
try {
199+
const status = await CanisterStatus.request({ agent, canisterId, paths: ['candid'] });
200+
const did = status.get('candid') as string | null;
201+
if (did) {
202+
return didToJs(did);
203+
}
204+
} catch (err) {
205+
console.warn('Failed to read candid:service metadata:', err);
211206
}
207+
return undefined;
212208
}
213209

214210
export async function getProfiling(canisterId: Principal): Promise<Array<[number, bigint]>|undefined> {
@@ -293,15 +289,6 @@ async function renderFlameGraph(profiler: any) {
293289
}
294290
}
295291

296-
async function getDidJsFromTmpHack(canisterId: Principal): Promise<undefined | string> {
297-
const common_interface: IDL.InterfaceFactory = ({ IDL }) => IDL.Service({
298-
__get_candid_interface_tmp_hack: IDL.Func([], [IDL.Text], ['query']),
299-
});
300-
const actor: ActorSubclass = Actor.createActor(common_interface, { agent, canisterId });
301-
const candid_source = await actor.__get_candid_interface_tmp_hack() as string;
302-
return didToJs(candid_source);
303-
}
304-
305292
async function didToJs(candid_source: string): Promise<undefined | string> {
306293
// call didjs canister
307294
const didjs_id = getCanisterId();

0 commit comments

Comments
 (0)