Finding out a canister's subnet

Given a canister id (principal), how can I find programatically the id of the subnet that hosts the canister? dfx canister info or dfx canister status do not display it. Is it possible to query any of the system canisters to find out? For example, running it through the routing table?

1 Like

I don’t know how to do it programmatically but you can find out by searching for the canister ID at dashboard.internetcomputer.org

Yes. But the dashboard isn’t curl-friendly…

@Dylan are you able to share anything about how the dashboard does this?

I never tried, but the delegation field from ic_agent::Certifcate contains the subnet_id. We may need to add some getter function in ic-agent to expose this.

In typescript and using an older agent library here, but something like this:

import { AnonymousIdentity, Certificate, HttpAgent, } from "@dfinity/agent";
import { Principal } from '@dfinity/principal';

import * as globals from "../globals"

export interface CanisterInfo {
    subnet: string
}
 
declare const Buffer

export async function getCanisterInfo(canisterId: Principal): Promise<CanisterInfo> {
    let canisterInfo: CanisterInfo = {subnet: ""};

    // create anonymous agent
    const agentOptions = { identity: new AnonymousIdentity(), host: globals.HOST };
    const agent = new HttpAgent(agentOptions);

    // get canister info
    try {
        const certificateBlob = await agent.readState(canisterId, { paths: [] })
        const cert = new Certificate(certificateBlob, agent);

        const success = await cert.verify();

        if (success) {
            try {
                // subnet ids are stored in a cert's delegation field
                if (cert['cert'].delegation) {
                    canisterInfo.subnet = Principal.fromUint8Array(cert['cert'].delegation.subnet_id).toText();
                }
                else {
                    // certs for canisters in the root subnet do not include this delegation field
                    // for now we'll assume it's the NNS system subnet
                    canisterInfo.subnet = "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe";
                }
            } catch {
                // ...
            }
        } else {
            // ...
        }
    } catch (error) {
        // ...
    }

    console.log("Subnet", canisterInfo.subnet)

    return canisterInfo;
}
4 Likes

Found the dashboard raw api URL:

https://ic-api.internetcomputer.org/api/v3/canisters/<canister-id>

Example:
https://ic-api.internetcomputer.org/api/v3/canisters/74iy7-xqaaa-aaaaf-qagra-cai

3 Likes