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

# Solana IDL examples

The `solana_instruction_data` field source decodes instructions for any [Anchor](https://www.anchor-lang.com/) program. Each condition includes the program's [IDL](https://www.anchor-lang.com/docs/basics/idl), the JSON interface that describes its instructions. Policies can then allow or deny instructions based on their decoded arguments and named accounts.

<Warning>
  An IDL condition matches any instruction whose data begins with a discriminator from the IDL,
  regardless of which program it calls. Anchor derives discriminators from instruction names, so
  unrelated programs with a `deposit` instruction share the same discriminator. Always pair IDL
  conditions with a `solana_program_instruction` `programId` condition in the same rule. Privy
  ignores the IDL's `address` field.
</Warning>

## IDL requirements

* Privy only accepts IDLs in the modern Anchor format, introduced in Anchor 0.30. [Learn how to convert a legacy IDL](https://www.anchor-lang.com/docs/updates/release-notes/0-30-1#convert-legacy-idls)
* Each IDL can be up to 32 KB, and all IDLs in a policy up to 128 KB combined. Each condition carries its own copy of its IDL. Published IDLs are often larger, so trim them to the instructions the policy uses. Keep each of those instructions complete, with its accounts in their original order, along with every type it uses.
* Template variables are not yet supported in `solana_instruction_data` conditions.

## Fields

| Field | Description |
| - | - |
| `instruction_name` | The name of the IDL instruction whose discriminator begins the instruction data. Supports `eq` and `in`. |
| `discriminator` | The matched instruction's discriminator as `0x`-prefixed hex. Supports `eq` and `in`. |
| `<instruction>.args.<arg>` | A decoded instruction argument, such as `deposit.args.lamports`. |
| `<instruction>.args.<arg>.<field>` | A field inside a struct argument, such as `deposit_for_burn.args.params.amount`. Paths can continue through nested structs, `Option` values, and type aliases. An empty `Option` doesn't match. |
| `<instruction>.accounts.<account>` | The address at the named account's position in the instruction. Accounts inside an IDL account group use a dotted path, such as `deposit.accounts.group.vault`. |

Fields must resolve to one of the types below. Other types, such as enums, vectors, and floats, can appear in an instruction but cannot be compared.

| IDL type | Value format | Operators |
| - | - | - |
| `u8` to `u256`, `i8` to `i256` | Decimal string, such as `'1000000000'`. Compared without rounding. | `eq`, `in`, `gt`, `gte`, `lt`, `lte` |
| `bool` | `'true'` or `'false'` | `eq`, `in` |
| `string` | Any string. Compared case-sensitively. | `eq`, `in` |
| `pubkey` and named accounts | Base58 address | `eq`, `in` |
| `bytes` and `[u8; N]` | `0x`-prefixed hex. Compared case-insensitively. `[u8; N]` values must be exactly `N` bytes. | `eq`, `in` |

## Allow Marinade deposits up to a maximum value

This policy allows a wallet to stake up to 1 SOL with [Marinade](https://marinade.finance/). It also requires the minted mSOL to go to the wallet's own mSOL token account. The `programId` condition limits the rule to the Marinade program.

```ts {skip-check} theme={"system"}
// A trimmed Marinade IDL with only the `deposit` instruction.
const marinadeIdl = {
  instructions: [
    {
      name: 'deposit',
      discriminator: [242, 35, 198, 137, 82, 225, 242, 182],
      accounts: [
        {name: 'state'},
        {name: 'msol_mint'},
        {name: 'liq_pool_sol_leg_pda'},
        {name: 'liq_pool_msol_leg'},
        {name: 'liq_pool_msol_leg_authority'},
        {name: 'reserve_pda'},
        {name: 'transfer_from'},
        {name: 'mint_to'},
        {name: 'msol_mint_authority'},
        {name: 'system_program'},
        {name: 'token_program'}
      ],
      args: [{name: 'lamports', type: 'u64'}]
    }
  ]
};

const policy = {
  version: '1.0',
  name: 'Marinade deposits',
  chain_type: 'solana',
  rules: [
    {
      name: 'Allow Marinade deposits of up to 1 SOL',
      method: 'signAndSendTransaction',
      conditions: [
        {
          field_source: 'solana_program_instruction',
          field: 'programId',
          operator: 'eq',
          value: 'MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD' // Marinade program
        },
        {
          field_source: 'solana_instruction_data',
          idl: marinadeIdl,
          field: 'deposit.args.lamports',
          operator: 'lte',
          value: '1000000000' // 1 SOL
        },
        {
          field_source: 'solana_instruction_data',
          idl: marinadeIdl,
          field: 'deposit.accounts.mint_to',
          operator: 'eq',
          value: '<wallet-msol-token-account>' // The wallet's mSOL token account
        }
      ],
      action: 'ALLOW'
    }
  ]
};
```

## Restrict USDC bridging to a specific recipient and chain

IDL fields can reference fields inside struct arguments. This policy allows Circle [CCTP](https://developers.circle.com/cctp) burns of up to 1,000 USDC, only to a specific recipient on Base.

```ts {skip-check} theme={"system"}
// A trimmed CCTP V1 TokenMessengerMinter IDL with only the `deposit_for_burn` instruction.
const cctpIdl = {
  instructions: [
    {
      name: 'deposit_for_burn',
      discriminator: [215, 60, 61, 46, 114, 55, 128, 176],
      accounts: [
        {name: 'owner'},
        {name: 'event_rent_payer'},
        {name: 'sender_authority_pda'},
        {name: 'burn_token_account'},
        {name: 'message_transmitter'},
        {name: 'token_messenger'},
        {name: 'remote_token_messenger'},
        {name: 'token_minter'},
        {name: 'local_token'},
        {name: 'burn_token_mint'},
        {name: 'message_sent_event_data'},
        {name: 'message_transmitter_program'},
        {name: 'token_messenger_minter_program'},
        {name: 'token_program'},
        {name: 'system_program'},
        {name: 'event_authority'},
        {name: 'program'}
      ],
      args: [{name: 'params', type: {defined: {name: 'DepositForBurnParams'}}}]
    }
  ],
  types: [
    {
      name: 'DepositForBurnParams',
      type: {
        kind: 'struct',
        fields: [
          {name: 'amount', type: 'u64'},
          {name: 'destination_domain', type: 'u32'},
          {name: 'mint_recipient', type: 'pubkey'}
        ]
      }
    }
  ]
};

const policy = {
  version: '1.0',
  name: 'CCTP bridging',
  chain_type: 'solana',
  rules: [
    {
      name: 'Allow USDC burns to one recipient on Base',
      method: 'signAndSendTransaction',
      conditions: [
        {
          field_source: 'solana_program_instruction',
          field: 'programId',
          operator: 'eq',
          value: 'CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3' // CCTP TokenMessengerMinter program
        },
        {
          field_source: 'solana_instruction_data',
          idl: cctpIdl,
          field: 'deposit_for_burn.args.params.amount',
          operator: 'lte',
          value: '1000000000' // 1,000 USDC (6 decimals)
        },
        {
          field_source: 'solana_instruction_data',
          idl: cctpIdl,
          field: 'deposit_for_burn.args.params.destination_domain',
          operator: 'eq',
          value: '6' // Base
        },
        {
          field_source: 'solana_instruction_data',
          idl: cctpIdl,
          field: 'deposit_for_burn.args.params.mint_recipient',
          operator: 'eq',
          value: '<recipient-address-base58>'
        }
      ],
      action: 'ALLOW'
    }
  ]
};
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.