> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# On-chain events

> Track transaction activity across EVM, SVM, and Bitcoin networks

The `wallet.activity` event tracks all confirmed transaction activity for user WaaS (embedded) wallets. This enables you to monitor blockchain transactions across chains in real-time without polling or indexing.

## Supported networks

### EVM networks

| Network | Mainnet | Testnet | Internal transfers |
| - | - | - | - |
| Ethereum | ✓ | Sepolia | ✓ |
| Polygon | ✓ | Amoy | ✓ |
| Optimism | ✓ | Sepolia | ✓ |
| Base | ✓ | Sepolia | ✓ |
| Arbitrum | ✓ | Sepolia | ✓ |
| BNB Chain | ✓ | Testnet | ✓ |
| Avalanche | ✓ | Fuji | ✓ |
| Robinhood Chain | ✓ | Testnet | ✓ |
| Arc | ✓ | Testnet | ✗ |

> [!NOTE]
>
> Internal transfers are transactions where the wallet address is involved in an internal (nested) call rather than as the direct `to` or `from` on the top-level transaction, for example interactions routed through smart contracts, bridges, or account abstraction entry points. On networks that do not support internal transfer tracking, `wallet.activity` events fire only when the wallet address appears directly in the top-level transaction.

### SVM networks

| Network | Mainnet | Testnet |
| :- | :- | :- |
| Solana | ✓ | Devnet |

### Bitcoin

| Network | Mainnet | Testnet |
| :- | :- | :- |
| Bitcoin | ✓ | ✗ |

> [!NOTE]
>
> A Bitcoin transaction has no single sender or recipient: it spends inputs and creates outputs. Dynamic emits one `assetTransfers` entry per output, including change returning to the sender, and sets `fromAddress` to the input address that contributes the most value. Amounts (`amount`, `amountRaw`) are satoshis, not BTC. `labels` is `sent` when the monitored address funds the transaction and `received` when it appears only in an output.

## How it works

When a confirmed transaction involves a user's WaaS (embedded) wallet, Dynamic sends a `wallet.activity` webhook event to your configured endpoint. This includes both incoming and outgoing transactions.

#### Example payload

```json theme={"system"}
{
  "eventId": "2a92c161-3167-44ad-8fce-4c6cdaed8129",
  "messageId": "5a2a5360-bb7e-4ea6-9bd3-0146bf2f734f",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "externalUserId": "usr_abc123",
  "eventName": "wallet.activity",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "live",
  "timestamp": "2025-06-09T14:30:59.210Z",
  "data": {
    "transactionHash": "0xc19598158b1064e1cf684b4607abe57ed18be754172d6d454930ed82be9f0174",
    "blockNumber": 21000000,
    "transactionTimestamp": "2025-06-09T14:30:55.000Z",
    "blockHash": "0x9b2c1f0e6a4d3b8c7e5f2a1d0c9b8a7f6e5d4c3b2a1908f7e6d5c4b3a2918f0e3",
    "blockExplorerUrls": [
      "https://etherscan.io/tx/0xc19598158b1064e1cf684b4607abe57ed18be754172d6d454930ed82be9f0174"
    ],
    "fromAddress": "0x2687c802ac5eb5da413a89dcfd6cd644e6aba280",
    "toAddress": "0xc0d70ec4bf711836207ae61358d5e822111cfdf8",
    "labels": ["external", "received"],
    "assetTransfers": [
      {
        "tokenAddress": "native",
        "fromAddress": "0x2687c802ac5eb5da413a89dcfd6cd644e6aba280",
        "toAddress": "0xc0d70ec4bf711836207ae61358d5e822111cfdf8",
        "amount": 0.05,
        "metadata": {
          "name": "Ether",
          "symbol": "ETH",
          "decimals": 18
        }
      }
    ],
    "chainName": "ETH",
    "networkId": 1,
    "registeredAddress": "0xc0d70ec4bf711836207ae61358d5e822111cfdf8",
    "relatedAddresses": [
      {
        "userId": "7f1c2d3e-4b5a-4c6d-8e9f-0a1b2c3d4e5f",
        "addresses": ["0x2687c802ac5eb5da413a89dcfd6cd644e6aba280"]
      }
    ]
  }
}
```

#### Transactions that involve other wallets within your environment

When one transaction involves more than one registered wallet in your environment, Dynamic sends a separate `wallet.activity` event for each wallet. Each event shares the same `networkId` and `transactionHash`, and `registeredAddress` identifies the wallet that triggered that delivery. Use all three fields together to tell deliveries apart and deduplicate them, because the same hash and address can appear on more than one network.

`relatedAddresses` lists the other registered wallets in the same environment that appear in the transaction, grouped by `userId`. External wallets registered without a user are grouped together in an entry that has no `userId`. It only includes addresses from the current transaction, and it is empty when no other registered wallet is involved. These addresses are context only, because each of them triggers its own event.

#### Example Bitcoin payload

```json theme={"system"}
{
  "eventId": "b86cba8c-d751-477e-8f49-0f9fc8bf23f4",
  "messageId": "1e9c5354-c914-4268-9084-632d95480fdc",
  "webhookId": "cbfeb4ca-691b-482f-a613-13f4dc4a2257",
  "userId": "99ef6cc2-3473-4b51-8f85-f07b110bb18a",
  "eventName": "wallet.activity",
  "environmentId": "93801ce2-ca24-44d5-84a7-8299479a4a09",
  "environmentName": "live",
  "timestamp": "2026-08-29T11:26:59.786Z",
  "data": {
    "transactionHash": "b44a600b2aca56bb0c446c390d86f7e9a4a0e1f6a4bbcce73baa564c00fc7d63",
    "blockNumber": 964560,
    "transactionTimestamp": "2026-08-29T11:26:20.000Z",
    "blockHash": "000000000000000000017ee0055e2d8cb5176f9a04ad5264cdb7313c0f587154",
    "blockExplorerUrls": [
      "https://mempool.space/tx/b44a600b2aca56bb0c446c390d86f7e9a4a0e1f6a4bbcce73baa564c00fc7d63"
    ],
    "fromAddress": "bc1qsmrap4n4m4ce9pm55cnfh04xvskzny9ld83qm0",
    "toAddress": "bc1qf6kumfzd3mdg4c2jyn8gpxvq0g3j77z04f6ytc",
    "labels": ["received"],
    "assetTransfers": [
      {
        "tokenAddress": "native",
        "fromAddress": "bc1qsmrap4n4m4ce9pm55cnfh04xvskzny9ld83qm0",
        "toAddress": "bc1qf6kumfzd3mdg4c2jyn8gpxvq0g3j77z04f6ytc",
        "amount": 1000,
        "amountRaw": "1000",
        "metadata": {
          "name": "Bitcoin",
          "symbol": "BTC",
          "decimals": 8,
          "imageUri": ""
        }
      },
      {
        "tokenAddress": "native",
        "fromAddress": "bc1qsmrap4n4m4ce9pm55cnfh04xvskzny9ld83qm0",
        "toAddress": "bc1qjgfajukj8zdes0lvltf2dt2c83prhywvzdm0dn",
        "amount": 3764,
        "amountRaw": "3764",
        "metadata": {
          "name": "Bitcoin",
          "symbol": "BTC",
          "decimals": 8,
          "imageUri": ""
        }
      }
    ],
    "chainName": "BTC",
    "networkId": 1,
    "fee": 209,
    "feePayer": "bc1qsmrap4n4m4ce9pm55cnfh04xvskzny9ld83qm0",
    "transactionError": null,
    "source": "quicknode",
    "type": "ADDRESS_ACTIVITY",
    "events": {
      "raw": {
        "blockHash": "000000000000000000017ee0055e2d8cb5176f9a04ad5264cdb7313c0f587154",
        "blockHeight": 964560,
        "blockTime": 1788002780,
        "confirmations": 1,
        "fees": "209",
        "txid": "b44a600b2aca56bb0c446c390d86f7e9a4a0e1f6a4bbcce73baa564c00fc7d63",
        "value": "4764",
        "valueIn": "4973",
        "vin": [
          {
            "addresses": ["bc1qsmrap4n4m4ce9pm55cnfh04xvskzny9ld83qm0"],
            "isAddress": true,
            "n": 0,
            "value": "3973"
          },
          {
            "addresses": ["bc1qxwdnjtlplwj7ue5wcp77cl4c0wmdpgfgsxszel"],
            "isAddress": true,
            "n": 1,
            "value": "1000"
          }
        ],
        "vout": [
          {
            "addresses": ["bc1qf6kumfzd3mdg4c2jyn8gpxvq0g3j77z04f6ytc"],
            "isAddress": true,
            "n": 0,
            "value": "1000"
          },
          {
            "addresses": ["bc1qjgfajukj8zdes0lvltf2dt2c83prhywvzdm0dn"],
            "isAddress": true,
            "n": 1,
            "value": "3764"
          }
        ]
      }
    }
  }
}
```

The second transfer is the change output, which can go to an address other than `fromAddress`. Every output is reported, so sum only the transfers whose `toAddress` is the wallet you monitor. `events.raw` carries the provider transaction, including the inputs, so you can reconstruct the full input set that `fromAddress` alone does not convey.

## Registration event

When a new embedded wallet is created and the environment has on-chain activity tracking enabled, Dynamic registers the wallet address with on-chain monitoring providers. A `wallet.activity.registered` event is sent once this registration succeeds.

This event fires only once per wallet, not on duplicates, replays, or already-registered addresses. Use it to confirm that a wallet is actively monitored before expecting `wallet.activity` transaction events.

#### Example payload

```json theme={"system"}
{
  "eventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f0e1d2c3-b4a5-6789-0abc-def123456789",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "eventName": "wallet.activity.registered",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "sandbox",
  "timestamp": "2025-06-09T14:30:59.210Z",
  "data": {
    "walletAddress": "0x3FcE1F4F28DbA209344072867134A3a7F547C7f1",
    "walletId": "484e49ba-3026-4e2c-9bf0-ed98ae224833",
    "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c"
  }
}
```

## Use cases

* Notify users when they receive funds
* Track transaction history for compliance or analytics
* Trigger downstream workflows based on on-chain activity
* Build real-time activity feeds in your application

## Getting started

To receive on-chain events:

1. [Set up a webhook endpoint](https://docs.dynamic.xyz/docs/platform/console/webhooks/setup.md)
2. Subscribe to the `wallet.activity` and/or `wallet.activity.registered` event types
3. Process incoming events in your webhook handler

See the [embedded wallet webhooks](https://docs.dynamic.xyz/docs/embedded-wallets/webhooks.md#on-chain-activity-events) event reference for the full event payload structures.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.