# Manage transactions

To create a transaction, navigate into your desired wallet and click ‘Send transaction’.

## Standard transaction types

Wallet-as-a-Service currently supports the following transaction type across *all blockchains*:

### Payment

This is a standard transfer of funds from your wallet to a counterparty.

If you select this transaction type, you will need to:

1. Select the blockchain address you would like to send the payment to
If an external address you want is not displayed, you need to add it to the address book.
2. Select which asset you would like to send
All assets in the wallet will be displayed as options. If you wish to transact with an asset not already in your wallet, click ‘switch to non-standard asset’ and you will be prompted to enter your desired asset’s symbol and contract.
3. Enter the transaction amount
4. Type in the total amount you wish to send, inclusive of blockchain fees
5. Click ‘Confirm transaction details’
6. You will be prompted to check the transaction details again to confirm they are correct. You can also view the transaction amount in USD. The submission window remains open for five seconds during which you can cancel. The submission is then submitted to the blockchain.
7. If you have approvals or MPC signing set up, the transaction will be sent for approval or signing


## Advanced transaction types

There are additional transaction types available to users transacting on the *XRP blockchain only*:

### OfferCreate

This transaction type places an offer or instruction on the XRP Ledger blockchain to exchange digital currencies at a certain price. It is similar to a traditional limit order.

If you select this transaction type, you will need to:

1. Enter sale details
  * Amount of the asset being sold
  * Symbol of the asset being sold
  * Issuer wallet address of the asset being sold
2. Enter purchase details
  * Amount of the asset being purchased
  * Symbol of the asset being purchased
  * Issuer wallet address of the asset being purchased
3. Select a flag to dictate how the offer will behave
  * **Fill or Kill**: The offer is cancelled if it cannot be fully filled at the time of execution
  * **Immediate or Cancel**: The offer trades as much as it can by consuming existing offers, or executes "successfully" even if no offers match
  * **Passive**: The Offer will not consume Offers that exactly match it. Instead, it becomes an Offer object and waits in the ledger until other Offers or cross-currency payments fully consume it
  * **Sell**: Exchanges the entire sale amount, even if it means obtaining more than the purchase amount in exchange
4. Optional: complete advanced settings
  * **Sequence number**: a unique, increasing number associated with your account that ensures each offer from that account is executed only once and in the correct order. These are automatically generated, however users may wish to provide their own
  * **OfferSequence number**: a unique number used to cancel a previous sequence
  * **Expiration**: the time (in seconds) the offer will be active on the decentralized exchange. After the offer expires, it cannot be filled by other users
5. Click ‘Create’


More information
Click [here](https://xrpl.org/docs/references/protocol/transactions/types/offercreate#offercreate-flags) for more information on restrictions/error cases that apply when completing an OfferCreate transaction.

**Example**: an error message will be displayed if the user selects both the ImmediateOrCancel and FillOrKill flags.

### OfferCancel

This transaction type will remove an offer from the XRP Ledger.

If you select this transaction type, you will need to:

1. Enter the sequence number of the previous OfferCreate transaction you wish to cancel
2. Optional: complete advanced settings
  * **Sequence number**: the sequence number of the account sending the transaction
  * **Last ledger sequence**: the highest ledger index this transaction can appear in
3. Click ‘Confirm’


### TrustLine

This transaction type will create or modify a trust line, or relationship of trust, between two accounts.

For example, if A wants to trade a custom token issued by B, A needs to first create a trust line with B’s account, specifying how much of B’s token A is willing to hold. This allows A to receive and send B’s tokens securely.

If you select this transaction type, you will need to:

1. Enter the maximum amount of an asset that may be held on the trust line
2. Enter the symbol of the asset that will be held on the trust line
3. Enter the wallet address that your activated XRP account will trust
4. Select a flag to dictate how the trust line will behave
  * Authorize the other party to hold currency issued by this account
  * Enable the No Ripple flag: blocks the automatic routing of payments through that specific trust line to other accounts
  * Disable the No Ripple flag
  * Freeze the trust line
  * Unfreeze the trust line
Click [here](https://xrpl.org/docs/references/protocol/transactions/types/trustset) for more information on the TrustLine flags available.
5. Click ‘Create’


## View a transaction

Transactions can be viewed from the Transactions tab within each wallet.

Click on a transaction to display the transaction details and current status.

API documentation
See our [Wallet-as-a-Service API reference](/pt-br/products/wallet/api-docs/palisade-api/palisade-api) for information on how to make transactions via the API.

### Reading contract-token transfer fields

Native asset transfers (ETH, BTC, TRX, XRP, SOL) move value directly from the origin wallet to the recipient wallet. The top-level `destinationAddress` names the recipient, and the top-level `qty` is the amount the recipient receives.

Contract-token transfers (ERC-20, TRC-20, BEP-20, ERC-721, and the other token-standard transfers in [Supported token standards](/pt-br/products/wallet/user-interface/blockchains-and-tokens#supported-token-standards)) work differently. The blockchain runs a call against the token contract, and the contract's internal ledger credits the recipient wallet.

**Outgoing transfers: top-level `destination` names the execution target.** For an **outgoing** transfer — one your organization sends — the top-level `destination` (and its deprecated equivalent `destinationAddress`) is the blockchain execution target: the address Wallet-as-a-Service submits to the blockchain after it compiles the transaction. For an outgoing contract-token transfer, compilation also sets the top-level `qty` to `"0"` and the top-level `asset` to the blockchain's native asset.

| Outgoing transfer type | Top-level `destination.address` | Top-level `qty` | Top-level `asset` |
|  --- | --- | --- | --- |
| Native asset (for example, ETH, TRX, SOL, BTC, XRP) | The recipient wallet address | The amount the recipient receives | The transferred asset |
| Contract token (for example, ERC-20, TRC-20, BEP-20) | The token contract address | Typically `"0"` — no native asset moves to the contract | The blockchain's native asset (for example, TRX for a TRC-20 transfer) |


For outgoing contract-token transfers, the recipient wallet address and token quantity don't appear at the top level of the transaction. To find them, read the `TRANSFER` entries in the asset-change arrays shown below.

**Incoming transfers keep the recipient at the top level.** This normalization applies only to outgoing transfers. When Wallet-as-a-Service records an incoming contract-token transfer detected through blockchain monitoring, the top-level `destination` holds your recipient wallet address, the top-level `qty` holds the transferred token quantity, and the top-level `asset` holds the token.

Field naming
Use the structured `destination` object instead of the deprecated `destinationAddress`. `destination.address` holds the same address, and `destination` also carries wallet, vault, and counterparty context when Wallet-as-a-Service can resolve them. For new integrations, read `destination.address`.

**Recipient lookup in asset changes.** Every transaction exposes two arrays of `AssetChange` entries that describe how balances move:

- **`proposedAssetChanges`** — Asset changes that Wallet-as-a-Service predicts **before confirmation**. Wallet-as-a-Service populates this array as soon as it compiles the transaction, so you can read it while the transaction is still pending. These values are indicative and can change if the on-chain execution differs from the prediction.
- **`confirmedAssetChanges`** — Asset changes that Wallet-as-a-Service records **after confirmation**, once the transaction reaches [`CONFIRMED`](/pt-br/products/wallet/user-interface/transactions/overview#the-complete-stage-breakdown). These values reflect what happened on chain.


Each entry contains these fields:

- `purpose` — either `TRANSFER` (asset movement) or `FEE` (network fees).
- `asset` — the asset that moves.
- `qty` — the amount that moves.
- `source` — the wallet the asset moves from. On `FEE` entries, `source` identifies the fee payer, which can differ from the transfer source when a dedicated fee wallet pays the network fee.
- `destination` — the wallet the asset moves to. Populated on `TRANSFER` entries; not populated on `FEE` entries.


Both `source` and `destination` hold the on-chain address, the wallet ID and vault ID when the wallet belongs to your organization, and any subaccount address the chain requires.

To resolve the recipient of a contract-token transfer:

1. Iterate the entries in `proposedAssetChanges` (before confirmation) or `confirmedAssetChanges` (after confirmation).
2. Skip entries with `purpose: FEE`.
3. For each `TRANSFER` entry, read `destination.address` for the recipient wallet and `qty` for the token quantity sent to that wallet.


The same lookup works for native transfers: the `TRANSFER` entry mirrors the top-level fields, so a single code path handles both transfer types.

**Example: TRC-20 / ERC-20 transfer.** The following response shows an outgoing USDT transfer on Tron (TRC-20). USDT on Ethereum, USDC on any EVM chain, and any other ERC-20, TRC-20, or BEP-20 transfer follow the same shape — only the contract, wallet, and asset symbol change.

```json
{
  "id": "019c94f1-cc8c-79b4-9c0f-bc7edaabc267",
  "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
  "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456",
  "status": "CONFIRMED",
  "action": "PALISADE_TRANSFER",
  "blockchain": "TRON",
  "asset": { "symbol": "TRX", "standard": "NATIVE" },
  "originAddress": "TSourceWallet0000000000000000000000",
  "origin": {
    "address": "TSourceWallet0000000000000000000000",
    "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
  },
  "destinationAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "destination": {
    "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "type": "EXTERNAL"
  },
  "qty": "0",
  "proposedAssetChanges": [
    {
      "purpose": "TRANSFER",
      "asset": {
        "symbol": "USDT",
        "standard": "ERC20",
        "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
      },
      "qty": "125.500000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
        "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456"
      },
      "destination": {
        "address": "TRecipientWallet00000000000000000000"
      }
    },
    {
      "purpose": "FEE",
      "asset": { "symbol": "TRX", "standard": "NATIVE" },
      "qty": "13.451000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
      }
    }
  ],
  "confirmedAssetChanges": [
    {
      "purpose": "TRANSFER",
      "asset": {
        "symbol": "USDT",
        "standard": "ERC20",
        "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
      },
      "qty": "125.500000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
        "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456"
      },
      "destination": {
        "address": "TRecipientWallet00000000000000000000"
      }
    },
    {
      "purpose": "FEE",
      "asset": { "symbol": "TRX", "standard": "NATIVE" },
      "qty": "13.451000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
      }
    }
  ]
}
```

Read this response as follows:

- `destinationAddress` and `destination.address` both hold `TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t` — the on-chain USDT contract that Tron runs the transfer against, not the recipient.
- Top-level `qty` is `"0"` because no native TRX moves to the contract. The TRX in the `FEE` entry is the network fee.
- Top-level `asset` is TRX, the blockchain's native asset — compilation normalizes it along with `destination` and `qty`. USDT appears only in the `TRANSFER` asset-change entries.
- The recipient wallet `TRecipientWallet00000000000000000000` and the token quantity `125.500000` appear in the `TRANSFER` entry of `confirmedAssetChanges` (or `proposedAssetChanges` while the transaction is still pending).


The same pattern applies to ERC-20 transfers on Ethereum, Arbitrum, Base, Polygon, Avalanche, and BNB Smart Chain: `destination.address` names the ERC-20 contract (for example, the USDC contract `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` on Ethereum), and the `TRANSFER` asset-change entry holds the recipient wallet.

## Filter transactions by origin or destination

To list transactions by where they come from or go to, add `filter.origin.*` or `filter.destination.*` query parameters to `GET /v2/transactions` or `GET /v2/vaults/{vaultId}/wallets/{walletId}/transactions`. Each filter matches the origin or destination of a transaction by any of these identifiers:

- The blockchain address
- The wallet ID or address book entry ID
- The counterparty ID


| Operator | Behavior |
|  --- | --- |
| `eq`, `in` | Matches when any identifier equals a value you supply. |
| `notEq`, `notIn` | Matches only when no identifier equals a value you supply. |
| `contains`, `startsWith`, `endsWith` | Matches the address only. Pattern matching is case-insensitive. |
| `isNull` | Checks whether the origin or destination is empty. |


**Example:** List a wallet's transactions sent to a specific counterparty.

```bash
curl -X GET "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/transactions?filter.destination.eq=$COUNTERPARTY_ID" \
  -H "Authorization: Bearer $TOKEN"
```

**Example:** List transactions received from either of two addresses.

```bash
curl -X GET "https://api.sandbox.palisade.co/v2/transactions?filter.origin.in=0x55502b9d5a68b0F8a48384352295BeD968aD8AA4&filter.origin.in=0x8dCd82eC41C41627D987830128198aff4A392D89" \
  -H "Authorization: Bearer $TOKEN"
```

A transaction must match every filter you set.

Deprecated address-only filters
Wallet-as-a-Service deprecates `filter.originAddress.*` and `filter.destinationAddress.*`. These filters match the blockchain address only. Their exact and list operators (`eq`, `notEq`, `in`, `notIn`) are case-sensitive, and their pattern operators are case-insensitive. For new integrations, use `filter.origin.*` and `filter.destination.*`.

## Freeze and unfreeze transactions

Transaction freeze controls allow you to temporarily hold incoming transactions for compliance review before funds become available in your wallet.

**Freeze a transaction**

To freeze an incoming transaction:

1. Navigate to the Transactions tab within your wallet
2. Click on the transaction you want to freeze to view its details
3. Click the "Freeze transaction" button
4. Enter a reason for freezing the transaction
5. Click "Freeze" to confirm


The transaction amount will be moved from the "Available" balance to the "Frozen" balance until unfrozen.

**Unfreeze a transaction**

To release frozen funds:

1. Navigate to the frozen transaction details
2. Click the "Unfreeze" button in the frozen transaction notice
3. Enter a reason for unfreezing the transaction
4. Click "Unfreeze" to confirm


The funds will be immediately moved from the "Frozen" balance to the "Available" balance.

**Freeze and unfreeze through the API**

To freeze or unfreeze a transaction through the API, call `PUT /v2/vaults/{vaultId}/wallets/{walletId}/transactions/{transactionId}/freeze` or `.../unfreeze` and include the required `reason` query parameter.

To make a request retryable, pass an optional `mutationId`. Reuse the same value each time you retry that request:

```bash
curl -X PUT "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/transactions/$TRANSACTION_ID/freeze?reason=AML%20review&mutationId=ce4918bf-a199-4ce2-85a3-d0d296855384" \
  -H "Authorization: Bearer $TOKEN"
```

The transaction's `freezeInfo` object, and each entry in `freezeInfo.history`, carries these fields:

| Field | Description |
|  --- | --- |
| `authority` | The authority that applied the freeze state: `FREEZE_AUTHORITY_AUTOMATIC_POLICY`, `FREEZE_AUTHORITY_CUSTOMER_MANUAL`, or `FREEZE_AUTHORITY_MANAGEMENT_COMPLIANCE`. |
| `mutationId` | The stable identifier of the freeze mutation. |
| `freezeRevision` | The revision number of the transaction's freeze state. The number increases with each change. |


API documentation
See the [Wallet-as-a-Service API reference](/pt-br/products/wallet/api-docs/palisade-api/palisade-api) for information on how to freeze and unfreeze transactions via the API.