Skip to content
Development
Command

/inspect-mint

Decode a token mint's extensions and live authorities, and flag integration risks

BOOST
From plugin
ai-kit
11034 skills15 agents34 commands4 MCP
Install
> /plugin marketplace add solanabr/ai-kit
> /plugin install solana-ai-kit@stbr

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/inspect-mint

Context preview

What this command does when you run it.

Decode a token mint's extensions and live authorities, and flag integration risks

Command definition

inspect-mint.md
description: "Decode a token mint's extensions and live authorities, and flag integration risks"

Inspect the mint in $ARGUMENTS: what it takes to integrate, and who can still change it. Read-only. Extension meanings and per-extension rules: [token-extensions](../skills/token-extensions/SKILL.md); what an integrator has to handle: [Reading an unknown mint](../skills/token-extensions/SKILL.md#reading-an-unknown-mint) and [Token accounts and transfers](../skills/token-extensions/SKILL.md#token-accounts-and-transfers); venue policy and the pre-launch checks: [programs.md, Before launch](../skills/token-extensions/references/programs.md#before-launch).

Inputs

| Input | Notes | |---|---| | `mint` | Required. | | `rpc` or `cluster` | Default mainnet. Prefer the project's provider (`HELIUS_API_KEY` in `.env`: `https://mainnet.helius-rpc.com/?api-key=<key>`); public RPCs rate-limit. | | `for` | `integrate` (default: a program, frontend or venue accepting the mint) or `issue` (an issuer reviewing their own mint before launch). |

1. Decode from raw bytes

Don't read extensions from RPC `jsonParsed` or `spl-token display`. Agave RPC nodes before 4.2 decode with `spl-token-2022-interface` 2.x, and for a mint that carries PermissionedBurn they return no `extensions` field at all, hiding a permanent delegate or hook on the same mint. `spl-token` 5.5.0 and a `--locked` 5.6.1 build use the same decoder. Decode with `@solana-program/token-2022` 0.19 on Kit 8 instead: from the project root if it already depends on both, otherwise from a scratch directory.

mkdir -p "$HOME/.cache/solana-ai-kit/inspect-mint" && cd "$HOME/.cache/solana-ai-kit/inspect-mint" && npm init -y >/dev/null && npm i -q '@solana/kit@^8.3' '@solana-program/token-2022@^0.19'

The scratch directory lives under `$HOME/.cache`, not `$TMPDIR`, because the run needs mainnet RPC and Node's `fetch` ignores the sandbox's proxy — so under Claude Code the run goes outside the sandbox, where `$TMPDIR` names a different directory than it did during the install, and the script would not be found. `$HOME` is the same on both sides, and `~/.cache` is in the kit's sandbox `allowWrite`.

`@solana-program/token-2022` 0.19 peers `@solana/kit` `^8.3`. A workspace pinned to an older kit major keeps its pin — run from the scratch directory instead of moving it.

Write this block to `inspect-mint.mjs` in the directory you installed into — the kit ships no such file, so it has to be written before the run line below resolves (adjust that path if you installed at the project root).

// node inspect-mint.mjs <mint> [rpc-url]: decode a mint from raw bytes (RPC jsonParsed can drop extensions)
import { address, createSolanaRpc, fetchEncodedAccount, unwrapOption } from '@solana/kit';
import { decodeMint, findExtraAccountMetaListPda, TOKEN_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';

const [mintArg, url = 'https://api.mainnet-beta.solana.com'] = process.argv.slice(2);
const rpc = createSolanaRpc(url);
const mint = address(mintArg);
const account = await fetchEncodedAccount(rpc, mint);
if (!account.exists) throw new Error('account not found on this cluster');
const is2022 = account.programAddress === TOKEN_2022_PROGRAM_ADDRESS;
if (!is2022 && account.programAddress !== TOKEN_PROGRAM_ADDRESS) throw new Error(`owned by ${account.programAddress}, not a token program`);
const len = account.data.length; // 82 = classic mint; extended mints carry account type 1 at byte 165 and are never 355 (multisig) bytes
if (len !== 82 && (len <= 165 || len === 355 || account.data[165] !== 1)) throw new Error('not a mint (token account or multisig)');
const { data } = decodeMint(account);
const extensions = unwrapOption(data.extensions) ?? [];
const hook = extensions.find((e) => e.__kind === 'TransferHook');
let hookMetaList = null;
if (hook && hook.programId !== '11111111111111111111111111111111') {
  const [pda] = await findExtraAccountMetaListPda({ mint }, { programAddress: hook.programId });
  hookMetaList = { address: pda, exists: (await fetchEncodedAccount(rpc, pda)).exists };
}
const { epoch } = await rpc.getEpochInfo().send();
const plain = (_, v) => typeof v === 'bigint' ? v.toString() : v instanceof Map ? Object.fromEntries(v)
  : v?.__option ? (v.__option === 'Some' ? v.value : null) : v;
console.log(JSON.stringify({ mint, program: is2022 ? 'Token-2022' : 'SPL Token', epoch, ...data, extensions, hookMetaList }, plain, 2));
node "$HOME/.cache/solana-ai-kit/inspect-mint/inspect-mint.mjs" <MINT> <RPC_URL>

Kit's `__kind` names differ from the Rust ones — `ScaledUiAmountConfig`, `PausableConfig`, `ConfidentialTransferFee` ([Reading an unknown mint](../skills/token-extensions/SKILL.md#reading-an-unknown-mint)). Report the extension under the name the user will meet in their own tool.

2. Follow up

  • **Hook program set** (not `1111...`): `solana program show <hook> -u <rpc>` for its upgrade authority (none means immutable). `hookMetaList.exists: false` means clients resolve no extra accounts, so the hook must work without them or every transfer fails. What a transfer then has to carry: [transfer-hooks](../skills/token-extensions/references/transfer-hooks.md).
  • **Transfer fee:** the active fee is `newerTransferFee` once `epoch >= newerTransferFee.epoch`, else `olderTransferFee`. A newer fee with a future epoch is a scheduled change. The recipient gets `amount - fee`, so an integrator credits the balance delta ([fees](../skills/token-extensions/references/fees.md)).
  • **ScaledUiAmount** with a future `newMultiplierEffectiveTimestamp`, or InterestBearing: the displayed amount will move; say by how much ([display-amounts](../skills/token-extensions/references/display-amounts.md)).
  • **MetadataPointer** to another address: the metadata lives there (possibly another program); fetch it only if the report needs name or symbol ([metadata-groups](../skills/token-extensions/references/metadata-groups.
Read more
Ships withai-kit

Claude Code, set up to ship on Solana. Not programs alone — the whole lifecycle: validating the idea, building the program and the app around it, shipping it, and the launch and growth work that follows.

Get the whole plugin

Other commands on ai-kit.