Privy’s policy engine allows your application to restrict the actions that can be taken with server wallets.

Policies enable you to configure:

  • Transfer limits
  • Allow lists and deny lists of transfer recipients
  • Allow lists and deny lists of smart contracts and programs
  • Constraints around calldata that can be passed to smart contracts

This ensures that server wallets can only ever be used to take actions your application intends to take.

Concepts

Policies are defined by three core primitives: policies, rules, and conditions. At a high-level:

  • Policies are a list of rules that define the total set of actions that are allowed or denied for a server wallet.
  • Rules are a set of conditions, such that if a request satisfies all of the conditions in a rule, the policy engine executes the action (ALLOW or DENY) prescribed by the rule.
  • Conditions are boolean statements that the policy engine can evaluate RPC requests against.

You can create and manage policies through the Privy Dashboard, nodeJS SDK, or via the REST API.

Policies

A policy is composed from a list of rules for each RPC method that a wallet can execute that define what actions are allowed or denied for the wallet. DENY actions take precedence over ALLOW actions. If no rules resolve, the policy will default to DENY.

Policy objects have the following properties:

version
'1.0'

Version of the policy. Currently, 1.0 is the only version.

name
string

Name to assign to policy.

chain_type
'ethereum' | 'solana'

Chain type for wallets that the policy will be applied to.

rules
Rule[]

A list of Rule objects describing what rules to apply to each RPC method (e.g. 'eth_sendTransaction') that the wallet can take.

Policy evaluation

When your application makes an RPC request on a wallet that has a policy, the policy engine evaluates the rules that are associated with the requested RPC method.

For instance, if your application makes an 'eth_signTransaction' request, the policy engine will only evalaute rules associated with the 'eth_signTransaction' method in the policy.

The rules are evaluated as follows:

  1. If any rule evaluates to a DENY action, the policy engine will DENY the request.
  2. If any rule evaluates to an ALLOW action, and no rules evaluate to DENY, then the policy engine will ALLOW the request.

If the request does not satisfy any of the rules for the policy, the policy engine defaults to DENY the request.

If your application makes a request to a server wallet with RPC method X, and the policy’s rules contains no entry with a method corresponding to X, the engine will deny the request by default. If you’d like the policy engine to instead allow requests for RPC method X by default, we recommend setting up an “Allow all” MethodRule for that RPC method like so.

Rules

The nested Rule object within the policy’s rules array. A rule is composed of an set of boolean conditions and an action (ALLOW or DENY) that is taken if an RPC request satisfies all of the conditions in the rule. Rule objects have the following fields:

name
string

Name to assign to the rule.

method
'personal_sign' | 'eth_signTypedData_v4' | 'eth_signTransaction' | 'eth_sendTransaction' | 'signMessage' | 'signTransaction' | 'signAndSendTransaction' | '*'

RPC method to apply the conditions to. Must correspond to the chain_type of the parent policy.

conditions
Condition[]

A set of boolean conditions that define the action the rule allows or denies.

action
'ALLOW' | 'DENY'

Whether the rule should allow or deny a wallet request if it satisfies all of the rule’s conditions.

Each rule corresponds to an individual action that should be allowed or denied by a server wallet. For example, you might configure rules for a policy to:

  • ALLOW transfers of the native token to a set of allowlisted recipient addresses
  • DENY interactions with specific Ethereum smart contracts or Solana programs

Conditions

A condition is a boolean statement about a wallet request. When evaluating a wallet request against a rule, the policy engine checks whether the wallet request satisfies each of the boolean conditions in the rule. If all of the conditions are satisfied, the engine executes the action associated with the rule.

Conditions allow you to define specific action types that should be allowed or denied for a server wallet.

field_source
'ethereum_transaction' | 'ethereum_calldata' | 'ethereum_typed_data_domain' | 'ethereum_typed_data_message' | 'solana_transaction' | 'solana_instruction' | 'interpreted_transaction'

Data source from which to derive the field for the condition.

field
string

The attribute to evaluate for a wallet request. As an example, the field for the recipient of an EVM transaction is 'to'.

abi
JSON

Contract ABI to decode Ethereum calldata against. Should only be set for 'ethereum_calldata' policies. Must strictly be formatted as JSON.

operator
'eq' | 'neq' | 'lt' | 'lte' | 'gt' | 'gte' | 'in'

Boolean operator used to compare a field with a value

value
string | number | string[]

Static value to compare a field to.

Conditions for certain sources may have additional parameters. For instance, ethereum_calldata conditions also require an abi parameter used to decode the calldata, and ethereum_typed_data_message conditions require a typed_data parameter to define the schema for the typed data message.

Field

Fields are attributes of a wallet request that can be parsed or interpreted from the wallet request. Examples of fields include the to parameter of an EVM transaction, the fee_payer parameter of a Solana transaction, or an spl_transfer_recipient field that is populated when the policy engine interprets a transaction.

Fields are derived from field sources, which surface data from the wallet request. Possible field sources are listed below.

Field sourceDescriptionExample fields
'ethereum_transaction'The verbatim Ethereum transaction object in an eth_signTransaction or eth_sendTransaction request.to, chain_id, value.
'ethereum_calldata'The decoded calldata in a smart contract interaction as the smart contract method’s parameters. Note that that 'ethereum_calldata' conditions must contain an abi parameter with the JSON ABI of the smart contractfunction_name, _to, _value (for a ERC20 interaction)
'ethereum_typed_data_domain'Attributes from the signing domain that will verify the signature.chain_id, verifying_contract
'ethereum_typed_data_message'types and primary_type attributes of the TypedData JSON object defined in EIP-712.dot-separated path to value in message object, i.e. to.wallet
'solana_transaction'The verbatim Solana transaction from a signTransaction or signAndSendTransaction request.fee_payer, latest_valid_block_height
'solana_instruction'The verbatim instruction in a Solana transaction from a signTransaction or signAndSendTransaction request.program_id, keys, data
'interpreted_transaction'Attributes that the policy engine interprets from an wallet request, but are not defined within the request object itself.spl_transfer_recipient, spl_transfer_value

Operator

Operators are boolean operators used to compare fields and values. Operators include eq, neq, lt, lte, gt, gte, in.

Values

A condition compares a field using its boolean operator to a static value. As an example, if a condition determines whether an Ethereum transaction has specific recipient address X, the value for the condition is X.