> ## 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.

# XRPL examples

> Example XRPL policies for restricting payment destinations, capping amounts, and limiting transaction types

XRPL policies evaluate decoded transaction fields signed via `xrpl_signTransaction`.

* Your app uses `xrpl_signTransaction` for RPC transaction signing. Rules for this method can use the `xrpl_transaction` field source below.
* Your app uses `raw_sign` for raw hash signing. Rules that apply to `raw_sign` requests can only use `system` conditions, since there's no decoded transaction to evaluate.
* XRPL policies also apply to the `exportPrivateKey` and `exportSeedPhrase` methods. No other method is supported — `*` is not a valid method for the `xrpl` chain type.

The policy engine inspects fields on these transaction types: `Payment`, `OfferCreate`, `OfferCancel`, and `TrustSet`. All conditions use the `xrpl_transaction` field source.

Other transaction types can still be signed — field conditions are not available for them, so constrain them with a `TransactionType` condition and rely on the engine's default deny. For wallets that should sign only a known set of transaction types, write `ALLOW` rules scoped to those types and let everything else fall through to the default deny, rather than adding an unconditional `ALLOW`.

## Restrict to Payment transactions only

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Allow only Payments",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Restrict to Payment type",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Allowlist Payment destinations

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Allowlist destinations",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow payments to specific addresses",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Destination",
                    "operator": "in",
                    "value": [
                        "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
                        "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe"
                    ]
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Cap XRP payment amount

XRP amounts are expressed in drops (1 XRP = 1,000,000 drops). Cap native XRP transfers with the `Payment.Amount.drops` field.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Cap XRP payments",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow XRP payments under 1000 XRP",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Amount.drops",
                    "operator": "lt",
                    "value": "1000000000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Restrict IOU payments by currency and issuer

For issued currency (IOU) payments, constrain the token, issuer, and amount. Use `Payment.Amount.value`, `Payment.Amount.currency`, and `Payment.Amount.issuer`.

> [!NOTE]
>
> `Payment.Amount.drops` and `Payment.Amount.value` are mutually exclusive — a condition using
> `.drops` matches only native XRP payments, while `.value` matches only IOU payments.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Allow specific IOU payments",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow USD payments from trusted issuer under 10000",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Amount.currency",
                    "operator": "eq",
                    "value": "USD"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Amount.issuer",
                    "operator": "eq",
                    "value": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Amount.value",
                    "operator": "lt",
                    "value": "10000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Cap OfferCreate amounts

Your app can constrain DEX offers with the `OfferCreate.TakerPays` and `OfferCreate.TakerGets` fields.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Cap DEX offers",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow offers paying under 500 XRP",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "OfferCreate"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "OfferCreate.TakerPays.drops",
                    "operator": "lt",
                    "value": "500000000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Restrict TrustSet limits

Your app can control which trust lines a wallet establishes and set a maximum amount.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Restrict trust lines",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow trust lines to specific issuer with limited amount",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "TrustSet"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "TrustSet.LimitAmount.issuer",
                    "operator": "eq",
                    "value": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "TrustSet.LimitAmount.value",
                    "operator": "lte",
                    "value": "1000000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Denylist destinations with condition sets

Reference a dynamic address list with `in_condition_set`. Manage the list via the [condition sets API](https://docs.privy.io/controls/policies/condition-sets.md).

> [!NOTE]
>
> The policy engine denies a request by default when no rule matches, so a `DENY` rule needs a
> companion `ALLOW` rule or every request is denied. Scope that `ALLOW` to the transaction type the
> wallet should sign, as the `Payment` condition below does. `DENY` takes precedence for sanctioned
> addresses, legitimate payments fall through to the `ALLOW`, and every other transaction type is
> denied by default.

> [!WARNING]
>
> A `Payment.Destination` denylist only screens `Payment` transactions. It does not stop value
> reaching the same address through a `CheckCreate`, `EscrowCreate`, or `PaymentChannelCreate`, and
> it does not cover account-control transactions such as `SetRegularKey`, `SignerListSet`,
> `AccountDelete`, or `DelegateSet`. The engine evaluates only the top-level transaction, so a
> `Batch` that wraps a `Payment` is not inspected either. Never pair a denylist with an
> unconditional `ALLOW`, which would permit all of these. For agent-controlled wallets, prefer a
> default-deny allowlist that permits only the specific transaction types the wallet needs.

> [!WARNING]
>
> Store classic `r`-addresses in condition sets, not X-addresses — an X-address item, tagged or
> untagged, never matches, so a sanctions-list `DENY` rule silently fails to catch that address.
> Condition sets also can't match on destination tags; use a separate `Payment.DestinationTag`
> condition for that.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Denylist Payment destinations",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Deny payments to sanctioned addresses",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Destination",
                    "operator": "in_condition_set",
                    "value": "your-condition-set-id"
                }
            ],
            "action": "DENY"
        },
        {
            "name": "Allow other Payments",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

To let the wallet sign other transaction types as well, add a separate scoped `ALLOW` rule for each
type the wallet legitimately needs, rather than widening this rule to an unconditional `ALLOW`.

## Only allow signing after a certain date

Your app can gate signing on the current timestamp with system conditions.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Time-gated XRPL signing",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow signing after launch date",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "system",
                    "field": "current_unix_timestamp",
                    "operator": "gt",
                    "value": "1757304000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Combine transaction and system conditions

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Time-gated payments to allowlist",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Allow payments to approved addresses after launch",
            "method": "xrpl_signTransaction",
            "conditions": [
                {
                    "field_source": "xrpl_transaction",
                    "field": "TransactionType",
                    "operator": "eq",
                    "value": "Payment"
                },
                {
                    "field_source": "xrpl_transaction",
                    "field": "Payment.Destination",
                    "operator": "in",
                    "value": [
                        "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
                        "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe"
                    ]
                },
                {
                    "field_source": "system",
                    "field": "current_unix_timestamp",
                    "operator": "gt",
                    "value": "1757304000"
                }
            ],
            "action": "ALLOW"
        }
    ]
}
```

## Deny all signing requests

`*` is not a supported method for the `xrpl` chain type. To deny every `xrpl_signTransaction`
request, use an empty-conditions `DENY` rule for that method instead.

```ts {skip-check} theme={"system"}
{
    "version": "1.0",
    "name": "Deny all XRPL signing",
    "chain_type": "xrpl",
    "rules": [
        {
            "name": "Deny all signing requests",
            "method": "xrpl_signTransaction",
            "conditions": [],
            "action": "DENY"
        }
    ]
}
```

## Supported policy fields

> [!NOTE]
>
> `address` type fields accept both classic `r`-addresses and untagged X-addresses — Privy
> normalizes X-addresses to classic format before comparing. Tagged X-addresses are rejected when
> the policy is created. To restrict by destination tag, add a separate `Payment.DestinationTag`
> condition alongside `Payment.Destination`.

| Field | Type | Operators |
| :- | :- | :- |
| `TransactionType` | string | `eq`, `in`, `in_condition_set` |
| `Payment.Destination` | address | `eq`, `in`, `in_condition_set` |
| `Payment.DestinationTag` | UInt32 | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.Amount.drops` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.Amount.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.Amount.currency` | string | `eq`, `in`, `in_condition_set` |
| `Payment.Amount.issuer` | address | `eq`, `in`, `in_condition_set` |
| `Payment.SendMax.drops` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.SendMax.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.SendMax.currency` | string | `eq`, `in`, `in_condition_set` |
| `Payment.SendMax.issuer` | address | `eq`, `in`, `in_condition_set` |
| `Payment.DeliverMin.drops` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.DeliverMin.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `Payment.DeliverMin.currency` | string | `eq`, `in`, `in_condition_set` |
| `Payment.DeliverMin.issuer` | address | `eq`, `in`, `in_condition_set` |
| `OfferCreate.TakerPays.drops` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `OfferCreate.TakerPays.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `OfferCreate.TakerPays.currency` | string | `eq`, `in`, `in_condition_set` |
| `OfferCreate.TakerPays.issuer` | address | `eq`, `in`, `in_condition_set` |
| `OfferCreate.TakerGets.drops` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `OfferCreate.TakerGets.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `OfferCreate.TakerGets.currency` | string | `eq`, `in`, `in_condition_set` |
| `OfferCreate.TakerGets.issuer` | address | `eq`, `in`, `in_condition_set` |
| `OfferCreate.Expiration` | UInt32 | `eq`, `lt`, `lte`, `gt`, `gte` |
| `TrustSet.LimitAmount.value` | decimal | `eq`, `lt`, `lte`, `gt`, `gte` |
| `TrustSet.LimitAmount.currency` | string | `eq`, `in`, `in_condition_set` |
| `TrustSet.LimitAmount.issuer` | address | `eq`, `in`, `in_condition_set` |
| `TrustSet.QualityIn` | UInt32 | `eq`, `lt`, `lte`, `gt`, `gte` |
| `TrustSet.QualityOut` | UInt32 | `eq`, `lt`, `lte`, `gt`, `gte` |
