Create / register
createAgent(umi, input, config?)— one-shot mint: calls Metaplex’smintAndSubmitAgent. Creates a Core asset and registers its Agent Identity in a single transaction. By default the agent’s on-chain metadata advertises aservices.receiptsURL ofhttps://api.leash.market/v1/receipts/{agent}so explorers and indexers can find the feed automatically — passreceiptsUrl: falseto omit,receiptsUrl: 'https://...'to override, or setLEASH_NO_RECEIPTS_URL=1/LEASH_RECEIPTS_URL=...to control it from the environment. See the Create an agent guide and Receipts by default.prepareAgentMint(umi, input, config?)/sendPreparedAgentMint(umi, prepared)— two-step variant for priority fees, hardware wallets, custom retries. Honours the samereceiptsUrlrules.registerAgentIdentity(umi, { asset, collection, agentRegistrationUri })— BYO flow: attaches an Agent Identity plugin to a Core asset you already minted.
Read
getAgentIdentityStatus(umi, asset)— returns{ registered, treasury, account? }. UsessafeFetchAgentIdentityV1FromSeedsso unregistered assets returnregistered: falseinstead of throwing.getAgentTreasury(context, asset)— derives the Asset Signer PDA (the agent’s built-in wallet).loadAgentRegistration(uri)/loadRegistrationDocument(uri)— fetch + Zod-validateRegistrationV1.
Spend allowance (treasury → executive)
The agent treasury (an Asset Signer PDA) physically owns the funds. To let an executive wallet move them via x402, approve a capped SPL delegation on the agent’s ATA for each stable mint you want to spend (USDC, USDT, USDG). Implemented as anSPL.Approve wrapped in mpl-core::Execute so the
PDA can authorise it via CPI; the resulting delegation is wire-compatible
with every existing x402 facilitator (the on-chain transfer is plain
TransferChecked). Allowances are per-mint — re-run setSpendDelegation
once per stable you intend to settle in.
setSpendDelegation(umi, { agentAsset, mint, executive, amount, payer?, authority?, tokenProgram? })— defensively inspects the agent’s ATA and approvesexecutivefor up toamountatomic units. If the ATA already exists with the correct mint + owner the create step is skipped (singleExecute(Approve)tx); if the ATA is absent it’s created viaCreateIdempotent; if it exists with a mismatched owner you get a precise error rather than the generic"Provided owner is not allowed". Returns{ signature, treasury, sourceTokenAccount, delegatedAmount, delegate }.revokeSpendDelegation(umi, { agentAsset, mint, payer?, authority?, tokenProgram? })— dropsdelegateanddelegated_amountto zero.getSpendDelegation(umi, { agentAsset, mint, tokenProgram? })— reads on-chain state without sending a tx. Returns{ treasury, sourceTokenAccount, sourceExists, balance, delegate, delegatedAmount }.
provisionTreasuryAtas
-
provisionTreasuryAtas(umi, { agentAsset, network?, mints?, payer? })— idempotently creates the agent treasury’s Associated Token Accounts for a curated set of stablecoins. Defaults toKNOWN_STABLES[network]: USDC on devnet; USDC + USDT on mainnet. Pass a custommintsarray to override. Returns{ treasury, atas: [{ mint, symbol, address, tokenProgram, created, signature? }] }—created: falsemeans the ATA was already valid (no tx broadcast). Re-run safely as many times as you like. Why pre-create? Two reasons: (1) wallets and faucets refuse to send to an address that doesn’t have an ATA, so provisioning ahead of time means “send USDC to this treasury” Just Works, and (2)setSpendDelegationthen becomes a singleExecute(Approve)instead of also having to create the ATA inline — fewer surfaces for"Provided owner is not allowed"to misfire on. -
Constants:
SPL_TOKEN_PROGRAM_ID,TOKEN_2022_PROGRAM_ID,KNOWN_STABLES.
Execute (delegation)
Mirrors the Metaplex Run an Agent guide step-for-step. The web playground signs all three calls with the connected Privy embedded wallet — there is no server-side signer in the user flow.registerExecutive(umi, { payer?, authority? })— one-timeregisterExecutiveV1. Defaultspayer = umi.payer(matches the docs snippet). Overrideauthoritywhen a different signer thanumi.identityshould own the executive profile (multisig, hardware wallet).hasExecutiveProfile(umi, authority)— does anExecutiveProfileV1exist for that wallet?delegateExecution(umi, { agentAsset, executiveAuthority, payer?, authority? })—delegateExecutionV1. Theauthority(defaultumi.identity) must be the asset owner — the program rejects the tx otherwise.verifyDelegation(umi, { agentAsset, executiveAuthority })→{ delegateRecord, exists }. Derives theExecutionDelegateRecordV1PDA and runs the docs’umi.rpc.getAccount(...).existscheck.isExecutionDelegated(umi, { agentAsset, executiveAuthority })— boolean shortcut aroundverifyDelegation.
Withdraw
Owner-driven drain of treasury funds — both SPL stables and native SOL (Genesis creator fees). Both paths share onempl-core::Execute wrap so the Asset Signer PDA can authorise the
inner instruction via CPI; only the inner instruction differs (SPL
TransferChecked vs SystemProgram.Transfer). Same wire-shape works
for classic SPL Token, Token-2022, and the System program. Full guide:
Withdraw treasury funds.
SPL stables
withdrawTreasury(umi, { agentAsset, mint, destination, amount, payer?, authority?, tokenProgram? })— movesamountatomic units todestination. Bundles aCreateIdempotentATA in front when the destination has no ATA yet.withdrawTreasuryAll(umi, { agentAsset, mint, destination, ... })— reads the on-chain balance and drains it. Returnsnull(no tx broadcast) when the treasury is empty.getTreasuryBalance(umi, { agentAsset, mint, tokenProgram? })— read-only “what’s the max I can pull” helper.
withdrawTreasurySol(umi, { agentAsset, destination, lamports, payer?, authority? })— moves exactlylamportstodestinationvia a hand-rolledSystemProgram.Transferwrapped inmpl-core::Execute. No ATA needed.withdrawTreasurySolAll(umi, { agentAsset, destination, reserveLamports?, ... })— reads the PDA’s lamport balance, subtracts a configurable reserve (default5_000lamports), and transfers the rest. Returnsnullwhen the spendable amount is zero.getTreasurySolBalance(umi, { agentAsset, reserveLamports? })→{ treasury, lamports, sol, spendableLamports, spendableSol }for UI gating.SYSTEM_PROGRAM_ID,DEFAULT_SOL_RESERVE_LAMPORTS— re-exported constants for advanced consumers.
Agent token (Metaplex Genesis)
Wraps the Genesis SDK so an agent can launch its canonical token in one call. Creator fees route to the agent’s Asset Signer PDA (the treasury), and the launch transactions are wrapped inmpl-core::Execute so the agent
itself executes them on-chain. Full guide: Launch an agent token.
launchAgentToken(umi, { agentAsset, network?, setToken?, token, launch?, wallet?, ... })— one-shotcreateAndRegisterLaunch. Returns{ mintAddress, genesisAccount, signatures, launch, token, agentAsset, network, agentTokenSet }with base58-encoded signatures.setToken: trueis permanent — once an agent’s token is bound it cannot be changed, replaced, or unset.GENESIS_TOKEN_IMAGE_URL_PREFIX/isGenesisTokenImageUrl(url)— Metaplex Genesistoken.imageURL rule helpers (see Metaplex docs).prepareAgentTokenLaunch(umi, input)/sendPreparedAgentTokenLaunch(umi, prepared, opts?)— two-step variant for hardware wallets, custom retries, or inspecting the unsigned bundle before sending.setAgentToken(umi, { agentAsset, genesisAccount, collection?, payer?, authority? })— wrapssetAgentTokenV1inmpl-core::Execute. Use this when you launched a Genesis token outside Leash and want to bind it to your agent later (the docs’ “Set Agent Token” snippet).getAgentToken(umi, agentAsset)→{ agentAsset, treasury, hasToken, mint, source }wheresourceis'v1' | 'v2' | 'none'.hasAgentToken(umi, agentAsset)— boolean shortcut.
TokenMetadata,
BondingCurveLaunchInput, GenesisApiConfig, SvmNetwork.
Registration resolution
resolveByoUri(uri)— fetches + validatesRegistrationV1from a public URL.parseLeashBlock(input)— Zod parse helper forLeashBlockV1.
Operator keypair
Pure Ed25519 helpers for the agent’s own off-chain signing identity — independent of the owner / executive on-chain wallets. Bytes are Solana-compatible (secret(32) || public(32), same shape as solana-keygen), so the same secret can be loaded by any tool in the ecosystem. No Solana RPC dependency — runs in Node, the browser, and edge runtimes. See Identities for when to use this vs. an owner / executive wallet.
generateOperatorKeypair()→{ publicKey, secretKey, pubkey }— fresh keypair from the platform’s CSPRNG.operatorFromSeed(seed)— deterministic derivation from a 32-byte seed (tests, KMS, mnemonic-derived flows).signWithOperator(secretKey, message)— Ed25519 signature over an arbitrary payload (typically a 32-byte digest).exportOperatorJson(kp)/importOperatorJson(raw)— round-trip the secret as asolana-keygen-style JSON byte array.operatorPublicId(kp)→{ pubkey, fingerprint }— public-only summary safe for logs and UI.pubkeyToBytes(pubkey)— base58 → 32-byteUint8Array(throws on invalid input).operatorRegistration(pubkey)→AgentRegistrationentry (leash:operator/solana:<pubkey>) ready to drop intocreateAgent({ registrations: [...] }).readOperatorRegistration(reg)— inverse: extracts the operator pubkey from an on-chain registration entry, ornullif it isn’t one.
Prepare/Send split
Every mutating helper in this package ships in two flavours:- One-shot (
createAgent,setSpendDelegation,withdrawTreasury, …) — builds, signs withumi.identity, and submits. Returns the signature plus echo fields. Use this when the SDK runs in the same process as the signer. prepare*— builds an unsignedTransactionBuilder(or returnsnullwhen there’s nothing to do) plus the same echo fields. Pair withawait prepared.builder.sendAndConfirm(umi)to sign and submit later. Use this when the signer lives elsewhere (hardware wallet, browser extension, remote RPC, the upcoming Leash HTTP API), when you need to add priority fees / custom retries, or when you want to inspect the tx before broadcasting.
prepareAgentMint + sendPreparedAgentMint and prepareAgentTokenLaunch + sendPreparedAgentTokenLaunch pairs are slightly different — they go through the Metaplex hosted Agent / Genesis APIs rather than building a Umi TransactionBuilder locally — so they keep their own send helpers. Everything else returns a builder you can finish off with .sendAndConfirm(umi) directly.
| One-shot | Prepare sibling | Notes |
|---|---|---|
createAgent | prepareAgentMint + sendPreparedAgentMint | Goes through Metaplex’s hosted mint API, not a local builder. |
registerAgentIdentity | prepareRegisterAgentIdentity | BYO Core asset. |
setSpendDelegation | prepareSetSpendDelegation | Returns willCreateAta so callers can size fees correctly. |
revokeSpendDelegation | prepareRevokeSpendDelegation | Pure builder — no RPC pre-flight. |
provisionTreasuryAtas | prepareProvisionTreasuryAtas | Returns null when every requested ATA already exists. |
registerExecutive | prepareRegisterExecutive | One-time per executive wallet. |
delegateExecution | prepareDelegateExecution | Owner-signed grant. |
withdrawTreasury | prepareWithdrawTreasury | Bundles a CreateIdempotent for the destination ATA when needed. |
withdrawTreasuryAll | prepareWithdrawTreasuryAll | Returns null when the treasury ATA balance is zero. |
withdrawTreasurySol | prepareWithdrawTreasurySol | Pure builder — lamports is taken at face value. |
withdrawTreasurySolAll | prepareWithdrawTreasurySolAll | Returns null when the spendable lamport amount (after reserveLamports) is zero. |
setAgentToken | prepareSetAgentToken | Bind a Genesis token to an existing agent. |
launchAgentToken | prepareAgentTokenLaunch + sendPreparedAgentTokenLaunch | Genesis multi-tx bundle. |
{ unsignedTransaction, echo } from the corresponding prepare* function so the caller stays in control of signing and broadcasting.
