I’m looking at the ext standard for erc721 tokens and the TokenIdentifier type, which is needed to query for metadata for tokens. The only thing I see regarding the tokens is:
// \x0Atid" + canisterId + 32 bit index
type TokenIdentifier = Text;
I’m confused on how to formulate the token identifier to query the canister.
Let’s say I want to create a TokenIdentifier for token index 2.
Is it not just something like “rrkah-fqaaa-aaaaa-aaaaq-cai-2”
I’m currently trying to solve this as well using this code: GitHub - Toniq-Labs/ext-js: JS agent for EXT but I’m a noob in JS. Didn’t even know what NPM is a couple of hours ago
If anyone here knows how to compute the TokenIdentifier according to this function, please reach out to us:
const tokenIdentifier = (principal, index) => {
const padding = Buffer("\x0Atid");
const array = new Uint8Array([
...padding,
...Principal.fromText(principal).toUint8Array(),
...to32bits(index),
]);
return Principal.fromUint8Array(array).toText();
};
const decodeTokenId = (tid) => {
var p = [...Principal.fromText(tid).toUint8Array()];
var padding = p.splice(0, 4);
if (toHexString(padding) !== toHexString(Buffer("\x0Atid"))) {
return {
index : 0,
canister : tid,
token : tokenIdentifier(tid, 0)
};
} else {
return {
index : from32bits(p.splice(-4)),
canister : Principal.fromUint8Array(p).toText(),
token : tid
};
}
};
Alright I’ve got it. So for anybody wondering: The TokenIdentifier is a representation of the canister’s ID, the index of the token within the canister, and a domain seperator so it needs to be computed from the token index and the canister ID of the smart contract that minted the token. You can do this using this JS code:
import { Principal } from '@dfinity/principal';
const to32bits = num => {
let b = new ArrayBuffer(4);
new DataView(b).setUint32(0, num);
return Array.from(new Uint8Array(b));
}
const computeTokenIdentifier = (principal, index) => {
const padding = Buffer("\x0Atid");
const array = new Uint8Array([
...padding,
...Principal.fromText(principal).toUint8Array(),
...to32bits(index)
])
console.log(array);
}
// Insert the canister ID and the token index as arguments
// This will print the result to console
// Result should look something like this: cso6j-aaaaa-uwiaa-aaaaa-amcay-maqca-aaaad-c
computeTokenIdentifier('CANISTER-ID', 0);
Sorry for my late response. So, yeah I was looking for a way to compute the TokenIdentifier when working with the Candid UI or dfx. That’s why I just log the array.
After replace return Principal.fromUint8Array(array).toText(); it works for me. I might just submit a PR on EXT. It would be great just have encode function in utility.
Thanks for pointing this out. This was fixed a while ago, but not released yet for some reason. @lwshang just did a new release of ic-types that now allows Principals ending in 4.