Transfer USDC scenario
A worked, self-contained example of moving USDC out of your Solana intermediary's USDC account with a steps-only execution — the intermediary already holds the USDC, and you simply send some of it to another account.
The transfer itself is a single SPL Token Transfer instruction. This document also includes the small amount of surrounding context you need (the intermediary, the token accounts, and the sign/submit flow) so it stands on its own.
What runs on-chain
One SPL Token Transfer (opcode 03):
program: the SPL Token program
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DAarg: a single
u64amountin the token's base unitsaccounts, in this exact order:
source— the intermediary's USDC token account (funds leave here)destination— the recipient's USDC token account (funds arrive here)authority— the intermediary, which authorizes the transfer ({INTERMEDIARY})
USDC has 6 decimals, so amounts are value × 10^6 base units: 25 USDC = 25000000, 1.5 USDC = 1500000.
The two token accounts
source — your intermediary's USDC ATA. Derive it from your resolved Solana intermediary and the USDC mint:
Fetch your Solana intermediary:
GET /api/v1/executions/{wallet}/intermediary→ readresult.solana.Derive its associated token account — a program-derived address of
[ intermediary, TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA, EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v ]under the associated-token-account programATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL, whereEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vis the USDC mint.Use that base58 address as
source.
destination — the recipient's USDC token account. This is the recipient's associated token account for the USDC mint (derived the same way, with the recipient's wallet as the owner). If it might not exist yet, prepend an associated-token-account CreateIdempotent for it and name {INTERMEDIARY} as the funder — the service reassigns the funder to the transaction fee payer at signing time, and bills the one-time rent into the fee only if the account was actually missing.
authority is the account that owns source and authorizes the debit — your intermediary. Send it as the {INTERMEDIARY} placeholder. The service substitutes your resolved Solana address before signing. It is the only account you may mark as a signer.
The request
type: "solana"selects the Solana step shape.destinationAssetis the destination token id for USDC on Solana.The
metadataobject is optional display text and can be omitted.Add
"dry": trueto preview the network fee without committing.
TransferChecked variant (optional, safer)
If you prefer the checked variant — which additionally verifies the mint and its decimals on-chain — use opcode 0c, add a u8 decimals arg after amount, and insert the mint as the second account:
Rules that apply here
Only
{INTERMEDIARY}may be a signer. Do not mark any other account"isSigner": true.Do not add a fee, compute-budget, or nonce instruction. The service injects those itself. On a real create the returned
stepsmirror the transaction the service signs, so they include the fee transfer the service appends (plus any associated-token-account create it prepends), and your{INTERMEDIARY}placeholder appears resolved to a concrete address. Only adry: truepreview echoes your submitted steps back unchanged.The fee is charged in USDC via a gasless relayer (Kora). SPL destinations settle through Kora, which pays the SOL gas and collects the network fee as an SPL transfer in the destination token — debited from the same intermediary USDC balance, so the amount you send plus the fee must fit. The destination mint must be on the deployment's
kora_fee_token_mintsallow-list (USDC is), or create returns400.A steps-only SPL action must touch its destination token. This transfer does —
sourceis the intermediary's ATA for the destination mint — so the requirement is satisfied.Amounts are base units, strictly encoded. A value that overflows
u64or a negative value is rejected, not wrapped.
Sign and submit
The create response returns, under result.details, a payload to sign and a signingStandard — your origin wallet's standard (for example erc191 for an EVM origin, raw_ed25519 for a Solana origin). Sign result.details.payload with your origin wallet exactly as you would for any destination — you never handle the inner Solana message — then submit:
The submit body is { signature, executionId } for an EVM or Tron origin. An ed25519 origin (Solana, NEAR, or Stellar) must also include publicKey. A TON origin includes both publicKey and a tonConnect envelope, so its body is { signature, executionId, publicKey, tonConnect }. On success the execution proceeds and the USDC moves from the intermediary's account to the recipient.
Last updated
