Skip to main content

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.

Apps can use Privy policies to restrict which transfer actions a wallet or signer can take. For transfers, Privy evaluates policies against the original request body sent to the transfer endpoint before it prepares the underlying transactions. That means transfer rules should match request-body fields like source.asset, source.amount, source.chain, and destination.address.

Supported methods

Transfer policies support a single rule method:
  • transfer
If a wallet policy only allows eth_sendTransaction, transfer requests will still be denied. Wallets that call the transfer endpoint need an explicit transfer rule.

Supported conditions

Transfer rules support action_request_body conditions for the fields below:
Field sourceFieldSupported operatorsNotes
action_request_bodysource.asseteq, in, in_condition_setMatches a named asset such as “USDC” or “ETH”.
action_request_bodysource.asset_addresseq, in, in_condition_setMatches a custom token contract address.
action_request_bodysource.amounteq, gt, gte, lt, lteValue must be a positive decimal string, such as “10.5”.
action_request_bodysource.chaineq, in, in_condition_setMatches the source chain, such as “base” or “solana”.
action_request_bodydestination.addresseq, in, in_condition_setMatches the recipient wallet address.
action_request_bodydestination.asseteq, in, in_condition_setMatches the destination asset for cross-asset transfers.
action_request_bodydestination.chaineq, in, in_condition_setMatches the destination chain for cross-chain transfers.
Transfer rules also support shared system conditions, such as current_unix_timestamp, for time-based controls.
Transfer policies support both chain_type: "ethereum" and chain_type: "solana". For transfer methods, the policy engine only accepts action_request_body and system conditions.

Choose source.asset or source.asset_address

Use source.asset if your app sends named assets like "USDC" or "ETH". Use source.asset_address if your app sends custom token contract addresses.
A single rule cannot condition on both source.asset and source.asset_address. A transfer request includes one or the other, never both.
This also affects runtime matching:
  • A rule using source.asset will not match a request that sends source.asset_address.
  • A rule using source.asset_address will not match a request that sends source.asset.
Keep your policy format aligned with the request format your application actually sends.

Example

The example below allows:
  • transfers of USDC up to 1000 units to an approved destination address
  • transfers on the Base chain only
After creating the policy, apply it to the wallet with policy_ids. For signer-specific transfer permissions, attach the policy as an override policy on a signer instead.
const policy = await privy.policies().create({
  name: 'Approved transfer policy',
  version: '1.0',
  chain_type: 'ethereum',
  rules: [
    {
      name: 'Allow USDC transfers up to 1000 to approved address on Base',
      method: 'transfer',
      action: 'ALLOW',
      conditions: [
        {
          field_source: 'action_request_body',
          field: 'source.asset',
          operator: 'eq',
          value: 'USDC',
        },
        {
          field_source: 'action_request_body',
          field: 'source.amount',
          operator: 'lte',
          value: '1000.0',
        },
        {
          field_source: 'action_request_body',
          field: 'source.chain',
          operator: 'eq',
          value: 'base',
        },
        {
          field_source: 'action_request_body',
          field: 'destination.address',
          operator: 'eq',
          value: '<approved-address>',
        },
      ],
    },
  ],
});

await privy.wallets().update('<wallet-id>', {
  policy_ids: [policy.id],
});
If the wallet has an owner_id, the wallet update must be authorized by that owner.

Common patterns

  • Restrict transfers to an allowlist of destination addresses with destination.address: in or destination.address: in_condition_set.
  • Limit which assets can be transferred with source.asset or source.asset_address.
  • Enforce maximum transfer size with source.amount.
  • Lock transfers to a specific chain with source.chain.
  • Add time-based controls with system.current_unix_timestamp.
  • Combine chain and destination controls for cross-chain transfer restrictions.

Next steps

Create a policy

Learn more about creating and managing policy objects.

Conditional policies per signer

Apply different transfer permissions to different signers on the same wallet.