Skip to content

Instantly share code, notes, and snippets.

@rubpy
Created June 20, 2024 20:46
Show Gist options
  • Save rubpy/a54272833f3876f8ce79bde638192fb3 to your computer and use it in GitHub Desktop.
Save rubpy/a54272833f3876f8ce79bde638192fb3 to your computer and use it in GitHub Desktop.
Fetching on-chain Metaplex token metadata (through lightweight getAccountInfo).
import * as web3 from "@solana/web3.js";
import {
MPL_TOKEN_METADATA_PROGRAM_ID,
MetadataAccountData as MplMetadataAccountData,
getMetadataAccountDataSerializer,
} from "@metaplex-foundation/mpl-token-metadata";
//////////////////////////////////////////////////
const METAPLEX_PROGRAM_ID = new web3.PublicKey(MPL_TOKEN_METADATA_PROGRAM_ID);
function findTokenMetadataAccountAddress(tokenMint: web3.PublicKey): web3.PublicKey | null {
try {
const [mplAccount] = web3.PublicKey.findProgramAddressSync(
[Buffer.from("metadata"), METAPLEX_PROGRAM_ID.toBuffer(), tokenMint.toBuffer()],
METAPLEX_PROGRAM_ID,
);
return mplAccount;
} catch (e) {}
return null;
}
async function getTokenMetadata(conn: web3.Connection, tokenMint: web3.PublicKey): Promise<MplMetadataAccountData | null> {
const serializer = getMetadataAccountDataSerializer();
if (!serializer) {
throw new Error("getMetadataAccountDataSerializer failed");
}
const mplTokenAccount = findTokenMetadataAccountAddress(tokenMint);
if (!mplTokenAccount) return null;
const info = await conn.getAccountInfo(mplTokenAccount);
if (!info || !info.data) {
throw new Error("unexpected getAccountInfo response");
}
let metadata: MplMetadataAccountData | null = null;
try {
[metadata] = serializer.deserialize(info.data);
if (typeof metadata !== "object") metadata = null;
} catch (e) {}
return metadata;
}
//////////////////////////////////////////////////
(async (rpcUrl: string) => {
const conn = new web3.Connection(rpcUrl, "confirmed");
const tokenMint = new web3.PublicKey("EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm");
const tokenMetadata = await getTokenMetadata(conn, tokenMint);
if (!tokenMetadata) return;
//////////////////////////////////////////////////
console.log(`Token metadata (${tokenMint.toBase58()}):`);
console.dir(tokenMetadata)
//
// --- OUTPUT ---
//
// Token metadata (EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm):
// {
// key: 4,
// updateAuthority: 'wifq4CRwpXCK8NYtKNsQAYoDethT1aR7R1DaKCLFgAd',
// mint: 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm',
// name: 'dogwifhat',
// symbol: '$WIF',
// uri: 'https://bafkreihwqhounu3cdwgvk2gc2dqcinpntlccbo3xcy4xuerd24yndldl5q.ipfs.nftstorage.link',
// sellerFeeBasisPoints: 0,
// creators: { __option: 'None' },
// primarySaleHappened: false,
// isMutable: false,
// editionNonce: { __option: 'Some', value: 254 },
// tokenStandard: { __option: 'Some', value: 2 },
// collection: { __option: 'None' },
// uses: { __option: 'None' },
// collectionDetails: { __option: 'None' },
// programmableConfig: { __option: 'None' }
// }
//
// --------------
//
})(process.env.SOL_RPC_URL || "https://mainnet.helius-rpc.com/?api-key=00000000-0000-0000-0000-000000000000");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment