Skip to main content

Overview

Policies are rule-based security controls that evaluate every transaction before execution. They can allow, deny, or require manual approval for transactions based on configurable criteria.

Policy Evaluation Flow

Every spend-capable transaction passes through policy evaluation:

Creating Policies

npm run cli -- policy create \
  --wallet-id <walletId> \
  --name "Trading Limits" \
  --rules '[
    {
      "type": "spending_limit",
      "maxLamportsPerTx": 5000000,
      "maxLamportsPerDay": 50000000,
      "requireApprovalAboveLamports": 10000000
    },
    {
      "type": "protocol_allowlist",
      "protocols": ["system-program", "jupiter", "marinade"]
    }
  ]' \
  --active true

Policy Rule Types

Spending Limit

Control transaction amounts and require approval above thresholds:
{
  "type": "spending_limit",
  "maxLamportsPerTx": 1000000,
  "maxLamportsPerDay": 10000000,
  "requireApprovalAboveLamports": 500000
}
FieldDescription
maxLamportsPerTxMaximum lamports per transaction (deny above)
maxLamportsPerDayMaximum lamports per 24-hour period (deny above)
requireApprovalAboveLamportsTrigger approval gate for amounts above this
All fields are optional. Omit a field to skip that check.

Protocol Allowlist

Restrict which protocols can be used:
{
  "type": "protocol_allowlist",
  "protocols": ["system-program", "jupiter", "spl-token"]
}
Denies any transaction using protocols not in the list.

Address Allowlist

Only allow transactions to specific addresses:
{
  "type": "address_allowlist",
  "addresses": [
    "8xKzZ...",
    "9yNmP..."
  ]
}

Address Blocklist

Block transactions to specific addresses:
{
  "type": "address_blocklist",
  "addresses": [
    "BadAddr1...",
    "BadAddr2..."
  ]
}

Program Allowlist

Restrict which Solana programs can be invoked:
{
  "type": "program_allowlist",
  "programIds": [
    "11111111111111111111111111111111",
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
  ]
}

Token Allowlist

Only allow specific SPL token mints:
{
  "type": "token_allowlist",
  "mints": [
    "So11111111111111111111111111111111111111112",
    "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
  ]
}

Rate Limit

Limit transaction frequency:
{
  "type": "rate_limit",
  "maxTx": 10,
  "windowSeconds": 3600
}
Allows maximum of 10 transactions per hour.

Time Window

Only allow transactions during specific hours:
{
  "type": "time_window",
  "startHourUtc": 9,
  "endHourUtc": 17
}
Allows transactions only between 9 AM and 5 PM UTC.

Max Slippage

Limit slippage tolerance for swaps:
{
  "type": "max_slippage",
  "maxBps": 100
}
Denies swaps with slippage above 1% (100 basis points).

Protocol Risk

Advanced controls for specific protocols:
{
  "type": "protocol_risk",
  "protocol": "jupiter",
  "maxSlippageBps": 50,
  "maxPoolConcentrationBps": 5000,
  "allowedPools": ["pool1...", "pool2..."],
  "allowedPrograms": ["prog1...", "prog2..."],
  "oracleDeviationBps": 200
}

Portfolio Risk

Portfolio-level risk controls:
{
  "type": "portfolio_risk",
  "maxDrawdownLamports": 100000000,
  "maxDailyLossLamports": 50000000,
  "maxExposureBpsPerToken": 2000,
  "maxExposureBpsPerProtocol": 3000
}
FieldDescription
maxDrawdownLamportsMaximum portfolio drawdown allowed
maxDailyLossLamportsMaximum daily loss allowed
maxExposureBpsPerTokenMax 20% exposure per token (2000 bps)
maxExposureBpsPerProtocolMax 30% exposure per protocol (3000 bps)

Policy Evaluation

Test how a transaction would be evaluated without executing it:
npm run cli -- policy evaluate \
  --wallet-id <walletId> \
  --type transfer_sol \
  --protocol system-program \
  --destination <pubkey> \
  --amount-lamports 1000000
Response:
{
  "decision": "allow",
  "reasons": [
    "Spending limit check passed",
    "Protocol allowlist check passed"
  ],
  "riskTier": "low"
}
Possible decisions:
  • allow - Transaction proceeds automatically
  • deny - Transaction blocked
  • require_approval - Transaction pauses at approval gate

Approval Gate Workflow

When a policy requires approval:
1

Transaction Pauses

Transaction status becomes approval_gate and waits for operator action.
2

List Pending Approvals

npm run cli -- tx pending --wallet-id <walletId>
Or via API:
curl -H "x-api-key: dev-api-key" \
  http://localhost:3000/api/v1/wallets/<walletId>/pending-approvals
3

Review Transaction Details

npm run cli -- tx get <txId>
Check the intent, amount, destination, and policy reasons.
4

Approve or Reject

npm run cli -- tx approve <txId>
5

Transaction Continues

After approval, transaction proceeds to signing and submission.

Policy Versioning

Policies support versioning for safe updates:

List Policy Versions

npm run cli -- policy versions <policyId>

Get Specific Version

npm run cli -- policy version <policyId> --number 2

Migrate Policy

npm run cli -- policy migrate <policyId> --target-version 3 --mode safe
Migration modes:
  • safe - Only migrate if compatible
  • force - Migrate regardless of compatibility warnings

Check Compatibility

Validate rules before creating or updating:
npm run cli -- policy compatibility-check \
  --rules '[{"type":"spending_limit","maxLamportsPerTx":1000000}]'

Managing Policies

List Wallet Policies

npm run cli -- policy list --wallet-id <walletId>

Update Policy

const updated = await client.policy.update(policyId, {
  active: false, // Disable policy
  rules: [ /* updated rules */ ]
});
Updating a policy creates a new version. Old transactions may reference previous versions.

Real-World Examples

Conservative Trading Bot

{
  "name": "Conservative Trader",
  "rules": [
    {
      "type": "spending_limit",
      "maxLamportsPerTx": 10000000,
      "maxLamportsPerDay": 100000000
    },
    {
      "type": "protocol_allowlist",
      "protocols": ["jupiter"]
    },
    {
      "type": "max_slippage",
      "maxBps": 50
    },
    {
      "type": "rate_limit",
      "maxTx": 20,
      "windowSeconds": 3600
    }
  ]
}

High-Security Treasury

{
  "name": "Treasury Security",
  "rules": [
    {
      "type": "spending_limit",
      "requireApprovalAboveLamports": 5000000
    },
    {
      "type": "address_allowlist",
      "addresses": ["TrustedAddr1...", "TrustedAddr2..."]
    },
    {
      "type": "time_window",
      "startHourUtc": 9,
      "endHourUtc": 17
    },
    {
      "type": "rate_limit",
      "maxTx": 5,
      "windowSeconds": 86400
    }
  ]
}

DeFi Yield Farmer

{
  "name": "Yield Strategy",
  "rules": [
    {
      "type": "protocol_allowlist",
      "protocols": ["marinade", "solend", "jupiter"]
    },
    {
      "type": "max_slippage",
      "maxBps": 100
    },
    {
      "type": "portfolio_risk",
      "maxExposureBpsPerProtocol": 3000,
      "maxDailyLossLamports": 50000000
    }
  ]
}

Policy Best Practices

Security Recommendations:
  • Always set maxLamportsPerTx and maxLamportsPerDay for production wallets
  • Use requireApprovalAboveLamports for high-value thresholds
  • Combine multiple rule types for defense-in-depth
  • Test policies with policy evaluate before activating
  • Enable time_window rules for business hours-only operation
  • Use rate_limit to prevent runaway execution

Next Steps

Managing Agents

Create autonomous agents with policy-gated capabilities

Protocol Interactions

Execute DeFi operations with policy protection

Build docs developers (and LLMs) love