Pockets & intents
A session can spend from its pocket within the on-chain policy. Apps request outcomes; the chain checks the signed intent, spending limits and atomic delivery.
Try it in the app
The devnet dashboard can create your pocket, renew its trading session, claim 25 tUSDC, review a quote and swap between tUSDC and tSOL. These are test tokens with no monetary value. No SDK setup is required. Keep at least 0.01 devnet SOL in your wallet for registration eligibility; service wallets sponsor setup and trading fees.
New app pockets have a $50 daily cap in oracle-valued test units, a 1% oracle slippage limit and two pinned feeds. The service supports $0.10–$10 per swap with a 0.20% spread. Review the exact amount and short quote expiry before confirming. Reloading loses the in-memory trading key; sign in and choose Enable trading to renew the session. Existing home addresses and policies are preserved. Send everything home uses an owner proof.
Funding
Each pocket lives at PDA(["pocket", app_id]). Users fund it two ways: a Blink (a Solana Actions deposit their own wallet simulates and signs), or a plain address for exchange withdrawals. fundingOptions re-derives the pocket PDA and refuses a substituted address. The reference Actions service also checks that the destination is an initialized pocket before constructing a transaction. Deposits remain public; funding from a main wallet creates an on-chain link to it.
verifyFunding compares GET metadata with the expected address. It does not inspect the transaction later returned by POST. Use a trusted Actions endpoint and check the actual destination, amounts and instructions before signing. The SDK's Solana Pay URL is a transaction-request URL, not a direct-transfer QR containing only the pocket address.Token accounts: a deposit creates the pocket's account for that mint. The account for a swap's output mint is the app's to create before the first fill (the reference solver does not pay that rent, since it would flow to the user's home on sweep).
Intents, not transactions
const receipt = await gl.submitIntent(pocket, session.signer, {
nonce: 1n, // a counter you persist per pocket
inMint: USDC, inMax: 25_000_000n, // spend at most 25 USDC
outMint: SOL, outMin: 160_000_000n, // receive at least 0.16 SOL
deadlineSlot: current + 150n, // or the offer dies
});The session key signs SHA-256 of the intent's canonical bytes. A solver — anyone running the open reference implementation — builds one transaction: signature check, fill_begin, its own routing, fill_end. If the pocket's balance of the out-mint hasn't risen by at least outMin by fill_end — measured on the very account fill_begin snapshotted — the entire transaction reverts, the solver's fee included. Nonces are a sliding window of 2,048 values per pocket: use a counter you persist, and the window follows it for the pocket's whole life; anything it leaves behind can never be replayed.
The policy — limits with teeth
| Rule | Conservative default | Enforced |
|---|---|---|
| Daily cap | $200 | on-chain, per pocket |
| Max slippage vs oracle | 1% | on-chain, every fill |
| Passkey above | $50 | bigger spends need a passkey session (user-verified assertion) |
| No-oracle mints (NFTs) | $20 cap | passkey-signed only |
| Oracle feeds | pinned per mint by you | apps and solvers can't substitute feeds |
Every intent commits to the policy's hash — if anyone tampers with the policy, every fill fails closed while sweep keeps working. The dashboard reads these values from the pocket account itself.
The exits
- Sweep home —
sweep_homemoves balances from the supplied token-account pairs and surplus SOL to the home address, retaining the pocket's rent reserve. Include every token account you want swept. An owner proof works after a session is lost or revoked; relayer availability and transaction fees still matter. With mint information supplied, the reference relayer creates missing home token accounts. - Revoke — ends a session immediately, and no earlier
open_sessioncan be replayed to bring it back. - Change home or policy — owner proof plus a 24-hour timelock. A configured watcher can notify on proposals and, with a funded fee payer, execute due changes. Notifications and cranking depend on that service being available. There is no ordinary session-authorized "send to address X" instruction in v1.
Before building an owner proof or sweep/revoke signature, read the pocket's current owner_action_nonce. Pass it to sweepDigest(pocket, nonce), revokeDigest(pocket, nonce), or changeDigest/cancelDigest after the change bytes. These digests append the nonce as u64 little-endian. Successful sweep, revoke, propose, cancel and execute operations advance it; rebuild a stale authorization from fresh state. This is separate from the intent nonce window.
When rotating a session, its expiry must exceed the pocket's stored max_session_expiry_slot and stay within the current policy's allowed horizon. Simply reusing the same expiry cannot reopen a revoked session.