Overview

The solData criterion provides advanced validation of Solana transaction instruction data using Interface Definition Language (IDL) specifications. This criterion allows you to decode and validate instruction parameters against specific rules, ensuring that transactions meet precise requirements before signing. A solData criterion uses IDL specifications to identify which Solana programs to validate against and defines instruction-specific validation rules including instruction names and parameter constraints. The idls field specifies which programs to validate, while the conditions field defines the validation rules. The idls field is a list that can include either: For general policy concepts and setup instructions, see the Policies Overview.

IDL Specifications

Anchor IDL Format

IDL specifications must follow Anchor’s IDL format v0.30+. This standardized format ensures compatibility and proper instruction decoding.

Supported Argument Types

The following primitive argument types are currently supported:
  • Boolean: bool
  • String: string
  • Public Key: pubkey
  • Unsigned Integers: u8, u16, u32, u64, u128, u256
  • Signed Integers: i8, i16, i32, i64, i128, i256
  • Floating Point: f32, f64

Current Limitations

Complex IDL argument types are not currently supported, including:
  • User-defined types
  • Arrays
  • Vectors
  • Optional types
If you need support for any of these features, please reach out to us on our CDP Discord.

IDL Compatibility

To convert older IDL formats to the required v0.30+ format, use the Anchor CLI:
anchor idl convert internal/policy/fixtures/solana_system_program_idl.json -o internal/policy/fixtures/solana_system_program_idl.json

Instruction Discriminators

Instruction discriminators are unique byte sequences that identify specific instructions within a program. Different program types use different discriminator formats and sizes.

Discriminator Formats by Program Type

Program TypeDiscriminator FormatSizeExample
SystemProgram4-byte little-endian u324 bytesTransfer = [2,0,0,0]
SPL Token1-byte enum index1 byteTransfer = 3
Associated TokenBorsh-encoded enum1 byteCreate = 0
Anchor ProgramsSHA256 hash of “global:instruction_name”8 bytestransfer = [163,52,200,...]

Anchor Discriminator Generation

For Anchor programs, the 8-byte discriminator is generated using:
SHA256("global:instruction_name")
This ensures consistent and unique identification of instructions across Anchor-based programs.

IDL Configuration

Known Program Shortcuts

For common Solana programs, you can use predefined program names instead of providing IDL specifications:
  • "SystemProgram" - Native Solana system program
  • "TokenProgram" - SPL Token program
  • "AssociatedTokenProgram" - Associated Token Account program

Custom IDL Objects

For custom programs or when you need specific instruction definitions, provide IDL objects with:
  • address: The program’s public key address
  • instructions: Array of instruction definitions containing:
    • name: Instruction name
    • discriminator: Byte array identifying the instruction
    • args: Array of argument definitions with name and type

Conditions

Conditions in your solData criteria allow you to validate specific instruction parameters against defined constraints.

Condition Evaluation

  • If there are multiple conditions defined in a solData criterion, they are evaluated with OR logic - if any condition matches, the validation passes
  • Parameters within a condition are evaluated with AND logic - all parameters must match for the condition to pass

Condition Structure

Each condition includes:
  • instruction: Name matching an instruction in one of the provided IDLs
  • params (optional): Array of parameter validations, each with:
    • name: Parameter name matching the instruction argument
    • operator: Comparison operator (==, <=, >=, <, >, !=) for single value comparison, or (in, not in) for list comparisons
    • value or values: Expected value or list of values for comparison

Examples

Using Known IDLs

This example uses predefined program names for common Solana programs:
import { CdpClient } from "@coinbase/cdp-sdk";
import {
  LAMPORTS_PER_SOL,
  PublicKey,
  SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  Transaction,
} from "@solana/web3.js";
import "dotenv/config";

const cdp = new CdpClient();

const policy = await cdp.policies.createPolicy({
  policy: {
    scope: "account",
    description: "Create solData account policy",
    rules: [
      {
        action: "accept",
        operation: "signSolTransaction",
        criteria: [
          {
            type: "solData",
            idls: ["SystemProgram", "TokenProgram", "AssociatedTokenProgram"],
            conditions: [
              {
                instruction: "transfer",
                params: [
                  {
                    name: "lamports",
                    operator: "<=",
                    value: "1000000",
                  },
                ],
              },
              {
                instruction: "transfer_checked",
                params: [
                  {
                    name: "amount",
                    operator: "<=",
                    value: "100000",
                  },
                  {
                    name: "decimals",
                    operator: "==",
                    value: "6",
                  },
                ],
              },
              {
                instruction: "create",
              },
            ],
          },
        ],
      },
    ],
  },
});

console.log("Created solData policy: ", policy.id);

// Apply policy to account
const accountWithSolDataPolicy = await cdp.solana.getOrCreateAccount({
  name: "MyAccount",
});

await cdp.solana.updateAccount({
  address: accountWithSolDataPolicy.address,
  update: {
    accountPolicy: policy.id,
  },
});

// Test with valid transaction
const fromPubkey = new PublicKey(accountWithSolDataPolicy.address);
const goodTransferAmount = BigInt(0.001 * LAMPORTS_PER_SOL);
const transaction = new Transaction().add(
  createAnchorSystemTransferInstruction(goodTransferAmount),
  createAnchorSPLTransferCheckedInstruction(100000, 6),
  createAnchorAssociatedTokenAccountCreateInstruction()
);

transaction.recentBlockhash = SYSVAR_RECENT_BLOCKHASHES_PUBKEY.toBase58();
transaction.feePayer = fromPubkey;

const serializedTransaction = transaction.serialize({
  requireAllSignatures: false,
});

const base64Transaction = Buffer.from(serializedTransaction).toString("base64");

try {
  const result = await accountWithSolDataPolicy.signTransaction({
    transaction: base64Transaction,
  });
  console.log("✅ Signed transaction: ", result.signedTransaction);
} catch (error) {
  console.log("❌ Transaction rejected: ", error);
}

Using Custom IDLs

For custom programs, provide IDL specifications:
import { CdpClient } from "@coinbase/cdp-sdk";

const cdp = new CdpClient();

const policy = await cdp.policies.createPolicy({
  policy: {
    scope: "account",
    description: "Custom IDL solData policy",
    rules: [
      {
        action: "accept",
        operation: "signSolTransaction",
        criteria: [
          {
            type: "solData",
            idls: [
              {
                address: "11111111111111111111111111111111",
                instructions: [
                  {
                    name: "transfer",
                    discriminator: [163, 52, 200, 231, 140, 3, 69, 186],
                    args: [
                      {
                        name: "lamports",
                        type: "u64",
                      },
                    ],
                  },
                ],
              },
              {
                address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
                instructions: [
                  {
                    name: "transfer_checked",
                    discriminator: [119, 250, 202, 24, 253, 135, 244, 121],
                    args: [
                      {
                        name: "amount",
                        type: "u64",
                      },
                      {
                        name: "decimals",
                        type: "u8",
                      },
                    ],
                  },
                ],
              },
            ],
            conditions: [
              {
                instruction: "transfer",
                params: [
                  {
                    name: "lamports",
                    operator: "<=",
                    value: "1000000",
                  },
                ],
              },
              {
                instruction: "transfer_checked",
                params: [
                  {
                    name: "amount",
                    operator: "<=",
                    value: "100000",
                  },
                  {
                    name: "decimals",
                    operator: "==",
                    value: "6",
                  },
                ],
              },
            ],
          },
        ],
      },
    ],
  },
});

console.log("Created custom IDL solData policy: ", policy.id);
It is critical that instructions are properly formatted with the correct discriminator and parameter encoding for policy validation to work correctly. The discriminator must match exactly what’s defined in the IDL, and parameters must be encoded according to their specified types.
For TypeScript developers working with custom Anchor programs, consider using the Anchor TypeScript client SDK (@coral-xyz/anchor).The SDK provides utilities for loading program IDLs, generating type-safe instruction builders, and creating properly formatted transactions, which can simplify the process of working with custom programs in your solData policies.

Use Cases

The solData criterion enables sophisticated policy controls for any Solana program, from native system operations to complex DeFi protocols. By providing custom IDL specifications, you can validate instruction parameters for both your own programs and popular ecosystem protocols.

Example Ecosystem Program Integration

DeFi and Trading Protocols:
  • Jupiter - Control swap parameters, slippage limits, and route restrictions for decentralized exchanges
  • Raydium - Set constraints on liquidity provision and farming operations
Staking and Validation:
  • Jito - Govern staking operations, validator selection, and MEV reward distributions
  • Marinade - Control liquid staking deposits, withdrawals, and stake account management
NFT and Digital Assets:
  • Metaplex - Restrict NFT minting parameters, royalty settings, and marketplace interactions
  • Magic Eden - Validate NFT marketplace transactions and bid placements
For your own custom programs, solData policies provide granular control over inputs to your instruction parameters.

Key Considerations

IDL Format Requirements

  • Always use Anchor IDL format v0.30+ for compatibility
  • Verify IDL structure matches the expected format
  • Convert older IDL formats using the Anchor CLI conversion tool
  • Ensure discriminator values exactly match the program’s instruction identifiers