mirage-solana-wallet
Installation
SKILL.md
Mirage Solana Agent Wallet
Use this skill whenever the task is a Solana wallet operation the agent should execute on the user's behalf: wallet creation, address resolution, balance checks, funding, arbitrary Anchor program calls, swaps, SPL transfers (public or private), or raw transaction/message signing. Everything runs through mirage and the bundled mirage ows CLI using an OWS-backed wallet (default: agent-treasury).
Safety
- Treat every wallet, funding, transfer, program-invocation, and signing flow as a sensitive action.
- Before opening a funding link, broadcasting a transfer, invoking a program instruction, or signing a raw transaction, restate the exact wallet, network (cluster/rpc), program/recipient, mint, amount, instruction(s), and any user-provided args or accounts in one short confirmation.
- If the user asks for a swap quote or price, do not run
mirage swapyet. First call the quote endpoint, present the expected input/output and price impact, then ask for explicit confirmation before broadcasting a swap. - Prefer devnet for first-time runs against an unfamiliar program.
- Prefer
OWS_PASSPHRASEover passing--passphraseon the command line. - Do not convert UI amounts to base units for
mirage transferormirage swap; those CLI commands already accept UI amounts like0.1. Convert UI amounts only when directly calling the quote API.
Workflow
- Create or resolve the wallet to operate.
- Create a named wallet with
mirage ows wallet create --name <wallet>. - List wallets with
mirage ows wallet list. mirage address,mirage balance,mirage fund,mirage transfer,mirage swap, andmirage invokeauto-create the defaultagent-treasurywallet if it is missing.- Resolve a wallet's Solana address with
mirage address --wallet <name>; check balance withmirage balance --wallet <name>.
- Create a named wallet with
- If the user wants to receive or top up, use
mirage fund(add--wallet <name>when it is notagent-treasury). This opens the Mirage hosted funding flow with the wallet address asrcv. - If the user wants to invoke an arbitrary Anchor program (build + sign + send any instruction):
- Always attempt the program ID on its own first:
mirage invoke <program-id>(add--cluster devnetor--rpc-url <url>for non-mainnet). Most Anchor programs publish their IDL on-chain, so this is the default path. - If Mirage errors with
No Anchor IDL is published on-chain for <program-id>. Provide one with --idl <path>., ask the user for a local IDL JSON file (e.g.target/idl/<name>.jsonin their repo, or downloaded from the program's GitHub) and retry with--idl <path>. - In a non-interactive environment (scripts, CI, or any agent harness without a TTY), drive the command entirely through flags instead of the interactive picker:
- Inspect first:
mirage invoke <program-id> --cluster <cluster> --show-idlemits a JSON catalog listing every instruction, each arg with its type, and whether every account is auto-resolvable (signer, IDL-declared address, well-known sysvar/program, or PDA with fully declared seeds). Use this to know which instruction(s) to run and which--account/--argvalues you still need from the user. - Run:
mirage invoke <program-id> --cluster <cluster> --ix <name> [--ix <name> ...] --arg <ix>.<name>=<value> ... --account <ix>.<name>=<pubkey> ... --yes. Repeat--ix,--arg, and--accountas needed. Add--dry-runto preview the resolved plan without signing when you want to confirm with the user first.
- Inspect first:
- In interactive use, Mirage fetches the IDL, lets the user pick one or more instructions, auto-derives the signer, well-known sysvars/programs, and IDL-declared PDAs, and only prompts for args or accounts it cannot resolve, then confirms a final summary before signing.
- Add
--wallet <name>when the fee payer is notagent-treasury. Add--yesonly when the user has confirmed the full plan.
- Always attempt the program ID on its own first:
- If the user wants an SPL transfer (public or private):
mirage transfer --to <recipient> --amount <ui-amount>— defaults to mainnet USDC, private visibility,agent-treasurysender.- Add
--wallet <name>when the sender is notagent-treasury. - Add
--mint <mint>for a non-default mint. - Add
--visibility publicto opt out of private routing;--visibility privateis the default. - Use
--clusteror--rpc-urlonly when the user asks or the environment requires it.
- If the user wants a swap:
- For quote-only requests, call
GET https://payments.magicblock.app/v1/swap/quotedirectly instead of runningmirage swap. - Convert the requested UI amount to base units for the input mint for
ExactInquotes, or output mint forExactOutquotes. Use known decimals when certain (USDC and USDT are 6 decimals); otherwise fetch mint decimals over Solana RPC before calling the quote endpoint. - Example USDC to USDT quote:
curl -s "https://payments.magicblock.app/v1/swap/quote?inputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&outputMint=Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB&amount=500000&swapMode=ExactIn". - Present
inAmount,outAmount,otherAmountThreshold,slippageBps,priceImpactPct, and the route labels if available. Then ask whether to execute the swap. - Execute only after confirmation with
mirage swap --input-mint <mint> --output-mint <mint> --amount <ui-amount>plus any confirmed flags such as--slippage-bps,--wallet,--visibility, or private delivery fields.
- For quote-only requests, call
- If the user wants to sign an arbitrary Solana transaction or message (outside the transfer/invoke/swap flows):
mirage ows sign tx --wallet <name> --chain solana --tx <unsigned-tx-hex>for raw transactions.mirage ows sign message --wallet <name> --chain solana --message "<message>"for message-signing only (not for transactions).
- Report the outcome:
- Include the transaction signature and sender address.
- For
mirage invoke, include the cluster-appropriate explorer URL printed by the CLI. - Verify status on Solana RPC or check
mirage balancewhen it is useful.
Common Commands
# Wallet management
mirage ows wallet create --name agent-treasury-1
mirage ows wallet list
mirage address --wallet recipient-wallet
mirage balance --wallet agent-treasury
# Funding
mirage fund
mirage fund --wallet agent-treasury
# Invoke any Anchor program by IDL
mirage invoke <program-id> --cluster devnet # interactive; on-chain IDL
mirage invoke <program-id> --idl ./target/idl/<name>.json # local IDL fallback
# Non-interactive invoke (agents / scripts / CI)
mirage invoke <program-id> --cluster devnet --show-idl # JSON catalog of instructions + accounts
mirage invoke <program-id> --cluster devnet \
--ix increment \
--arg increment.amount=1 \
--account increment.counter=<pubkey> \
--dry-run # preview the plan, no signing
mirage invoke <program-id> --cluster devnet --ix increment --yes # run with auto-resolution
# SPL transfers
mirage transfer --to <recipient> --amount 0.1
mirage transfer --wallet sender-wallet --to <recipient> --amount 2.5
mirage transfer --wallet sender-wallet --to <recipient> --amount 2.5 --visibility public
mirage transfer --wallet sender-wallet --to <recipient> --mint <mint> --amount 1
# Swaps
curl -s "https://payments.magicblock.app/v1/swap/quote?inputMint=<mint>&outputMint=<mint>&amount=<base-units>&swapMode=ExactIn"
mirage swap --input-mint <mint> --output-mint <mint> --amount 0.5 --slippage-bps 50
# Arbitrary signing
mirage ows sign tx --wallet agent-treasury --chain solana --tx <unsigned-tx-hex>
mirage ows sign message --wallet agent-treasury --chain solana --message "hello"
Notes
mirage fundis a receive/top-up flow, not a send flow.mirage transferdefaults to mainnet USDC and private visibility; set--visibility publicto opt out of private routing.mirage swapsigns and sends; use the quote endpoint directly for quote-only requests before asking the user to confirm execution.- Do not pass
--yestomirage swap; it is not supported. After user confirmation, runmirage swapwithout--yes. - If the user only supplies a recipient wallet name, resolve it with
mirage addressbefore sending. - Create a brand-new named wallet explicitly with
mirage ows wallet create --name <wallet>before using it in other commands. mirage invokedefaults to the on-chain Anchor IDL PDA. Try the baremirage invoke <program-id>form first; only ask the user for a local IDL when Mirage reports that no on-chain IDL is published.mirage invokeauto-derives signers, well-known sysvars/programs, and PDAs whose seeds are declared in the IDL; anything else is prompted for (interactively) or requires--account/--argflags (non-interactively).- Use
mirage ows sign txfor raw Solana transactions that do not fitmirage transferormirage invoke. - On older Mirage installs,
BlockhashNotFoundon private transfers can indicate an outdated global CLI. Re-run with the current build if needed.
Related skills