> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chance.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Solana

> Verify a serialized Solana transaction before it is signed.

`venue`: `solana`. Over HTTP, `sol`, `svm`, `spl` and `spltoken` also resolve to it.

## What to send

A base64-serialized transaction, legacy or v0, as `{transaction: "<base64>"}`, `{tx: "<base64>"}` or `{method: "signAndSendTransaction", params: {transaction: "<base64>"}}`. The string must be strict base64. It is detected without `venue` when the bytes deserialize as a transaction with at least one instruction.

For a v0 transaction that uses address lookup tables, accounts loaded from a table cannot be resolved offline. They show as lookup-table accounts, and a note says so.

## How it is decoded

Each instruction is decoded and listed in order.

| Program | Instructions decoded | Instruction action |
| - | - | - |
| System Program | `Transfer` | `sol-transfer` |
| System Program | `CreateAccount` (rent funding a new account), `Assign` (flagged: the account gets a new owner program) | none |
| SPL Token and Token-2022 | `Transfer`, `TransferChecked`, `MintTo`, `Burn` | `spl-transfer` |
| SPL Token and Token-2022 | `Approve`, `ApproveChecked`, `SetAuthority`, `CloseAccount` | `spl-permission` |
| ComputeBudget, Memo, Associated Token Account | All (they move no funds) | none |
| Other programs, and other System or token instructions | Not decoded | `program-call` |

SPL amounts are the u64 in the instruction. `TransferChecked` and `ApproveChecked` also carry decimals and the mint.

`actionType` is the single instruction action present, `mixed` if there is more than one, and `program-call` if there is none.

`actionFamily` covers the whole transaction:

* `permission` if any instruction is `Approve`, `ApproveChecked`, `SetAuthority`, `CloseAccount` or `Assign`.
* Otherwise `unknown` if any instruction could not be decoded.
* Otherwise `transfer` if any instruction moves funds (`CreateAccount` counts).
* Otherwise `unknown`, with a note that the transaction is only fees and memos.

## Notes the classifier adds

* A plain SPL `Transfer` names token accounts, not wallets, and not the mint. The owner of the destination and the token are unverified from the instruction.
* Token-2022 mints can carry transfer fees, transfer hooks and other extensions that the instruction does not show.
* `Approve` lets a delegate move tokens later without asking again. `SetAuthority` changes who controls a token account. `CloseAccount` sends the account's rent to a destination, which is a known draining pattern.
* `MintTo` creates supply, and `Burn` destroys tokens.
* Unknown programs and undecodable instructions tell the judge to lean ESCALATE unless your rules cover them.

## No live lookup

The adapter reads only the bytes. In an escrow wallet, the transaction is also simulated before the verdict, but a Solana simulation reports only whether the transaction succeeds, not what it moves. None of the wallet limits (per-action USD limit, 24-hour cap, token allowlist, recipient allowlist) can be checked against a raw Solana transaction, so a wallet with any of them set blocks it. Transfers made with `escrow_transfer` state what they move and are checked normally. See [Wallet limits](/wallet-limits#when-effects-cannot-be-measured).

## Example

```ts theme={null}
// 0.25 SOL from 9WzD…AWWM to 4Nd1…DB4T, with a priority-fee instruction
const action = {
  transaction:
    "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIEfowIh2C/3h3dzzLBfyCbgkLuUqrxMfrNiNDqLG0LBvIyHPpa3RheiJOl/YgBPsTX4SLe1GNUyt/1DZVjledbYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwZGb+UhFzL/7K26csOb57yM5bvF9xJrLEObOkAAAADEmud2A3ggVPF6nezqQ7RE66DtsSxvHTHG4OSoS/BS6wIDAAkD6AMAAAAAAAACAgABDAIAAACAsuYOAAAAAA==",
};

const res = await fetch("https://harness.chance.cc/api/v1/intent", {
  method: "POST",
  headers: { "x-api-key": process.env.CHANCE_API_KEY!, "Content-Type": "application/json" },
  body: JSON.stringify({
    intent: "Pay contractors in SOL, at most 1 SOL per payment, only to 4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T.",
    venue: "solana",
    action,
  }),
});
const result = await res.json();
if (result.verdict !== "ALLOW") throw new Error(result.reasoning ?? result.error);
// Only now sign and send the transaction.
```

The classifier types this as `sol-transfer` in the `transfer` family. Its summary lists the priority-fee instruction as moving no funds and the transfer as 0.25 SOL (250,000,000 lamports) to `4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T`.

## From an MCP client

Instruct the agent to call `verify_intent` before signing any Solana transaction, with your rules as `intent`, `{ "transaction": "<base64>" }` as `action` and `venue: "solana"`, and to act only on ALLOW.
