How to Track a Crypto Wallet with Webhooks for Every Transfer

Three ways to monitor a wallet address on Bitcoin, Ethereum, Solana, Tron, BNB Chain and Polygon, and how to receive every transfer as a webhook.

· 6 min read

Sooner or later every crypto product needs to know when money moves on an address: a treasury wallet, a customer's deposit address, a partner who promised to pay. A blockchain does not call you when that happens. You have to watch it. This guide compares the ways to do that and shows the shortest one: a tracker that turns every transfer into a webhook.

Three ways to watch a wallet address

  • Run your own node. You read every block and filter the transfers that touch your addresses. It gives full control and costs the most: a node per blockchain, disks that fill up, upgrades, and different code for Bitcoin, Ethereum, Solana and Tron.
  • Poll a block explorer or an RPC provider. You ask for the address's transactions every few seconds. It is quick to start, but you pay per request, hit rate limits as the number of addresses grows, and still have to handle confirmations and missed polls yourself.
  • Use a wallet tracker API. You register the address once and get an HTTP request for every confirmed transfer. There is nothing to run and the work does not grow with the number of blocks.

The rest of this guide uses the third way with the LirChain Wallet Tracker, which covers Bitcoin, Ethereum, Solana, Tron, BNB Chain and Polygon with one request and one webhook format.

Step 1: add the address

Create a free account, open the Wallet Tracker project in the dashboard and copy its API key. Then send the network and the address. external_id is your own label for the address, for example a user id. It comes back in every webhook.

curl https://api.lirchain.com/merchant/wallet-tracker/create \
  -H "x-api-key: YOUR_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "network": "ethereum",
    "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "external_id": "treasury"
  }'

The address is checked against the rules of its network, so a typo is refused with a 400 instead of silently tracking nothing. The network field takes bitcoin, ethereum, solana, tron, bsc or polygon.

Step 2: receive the webhook

Open the project in the dashboard, paste the HTTPS address of your endpoint into its webhook field and save. From then on every confirmed transfer to or from the address is posted to it as JSON:

Webhook for a transfer
{
  "type": "wallet-tracker",
  "event": {
    "id": "95e04e32-5c98-4f68-8c62-f487bda0ed5c",
    "tracker_id": "67153a22-af19-4352-ab8e-041006c76c7b",
    "external_id": "treasury",
    "project_id": "ea54aa6c-21d7-46a4-b1fe-c0703f74a2af",
    "created_ms": 1791504120904
  },
  "transfer": {
    "network": "ethereum",
    "block_number": 26151012,
    "tx_hash": "0x4e3a…9f21",
    "log_index": "28",
    "from_address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
    "to_address": "0x52ae0f1c8d4b7a90e3b6c2d15f8a47e09b3c91f3",
    "asset": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    "amount": "102870865",
    "symbol": "USDC",
    "amount_units": "102.870865"
  }
}

A minimal handler in Node.js looks like this. It remembers which webhooks it already handled, decides whether the money came in or went out, and answers quickly.

Webhook handler (Node.js, Express)
import express from "express";

const app = express();
app.use(express.json());

// Use a table in your database instead of memory in production
const handled = new Set();

// The addresses you track. Ethereum, BNB Chain and Polygon addresses come in lowercase.
const my_addresses = new Set(["0xdac17f958d2ee523a2206206994597c13d831ec7"]);

app.post("/webhooks/lirchain", (req, res) => {
    const id = req.get("x-webhook-id");

    if (handled.has(id)) {
        return res.sendStatus(200);
    }
    handled.add(id);

    const { type, event, transfer } = req.body;

    if (type === "wallet-tracker") {
        // The tracked address is either the receiver or the sender of the transfer
        const direction = my_addresses.has(transfer.to_address) ? "received" : "sent";

        console.log(event.external_id, transfer.symbol, transfer.amount_units, direction);
    }

    res.sendStatus(200);
});

app.listen(3000);

Answer with a 2xx status within 10 seconds. If your server does not, the same webhook is sent again every minute, up to 20 times, each time with the same x-webhook-id header, so keep the ids you handled and skip repeats.

Step 3: tell incoming from outgoing

Compare the address you track with the two sides of the transfer. It received money when it equals to_address and sent money when it equals from_address. symbol and amount_units give the readable amount (USDC, 102.870865), while asset and amount are the chain's own values: the token's contract address and the amount in its smallest unit.

Bitcoin and Solana transactions can have many senders and receivers at once. There an event is what the transaction changed for your address: the amount it gained or lost, with the other side left empty.

What to know before you rely on it

  • A transfer is reported once it is safely confirmed: 12 blocks on Ethereum, BNB Chain and Polygon, 20 on Tron, 3 on Bitcoin, and finalized transactions on Solana. A transaction that failed is never reported.
  • A tracker reports transfers from the moment you add it.
  • Each network's own coin and the USDT and USDC stablecoins are reported. A token that only calls itself USDT is not: the tracker matches the real contract.
  • Webhooks are not signed. Treat one as a signal and, before you move money because of it, read the event back from the API with your key.
  • The Free plan tracks 50 wallets and reports 250 events per 30 days, and events carry no fee on any plan.

Questions and answers

Can I track a wallet that is not mine?
Yes. A tracker only needs the public address, never a private key, so any wallet on a supported blockchain can be tracked.
How fast does the webhook arrive?
As soon as the transfer is safely confirmed, which on most networks is within a minute or two. Bitcoin takes three blocks, usually around half an hour.
What if my server is down when a transfer happens?
The webhook is retried every minute, up to 20 times. Every event is also kept and can be listed through the API, so nothing is lost while your server is away.

Try it on the Free plan

Every product is included, and no card is needed to sign up.

Create a free account

Keep reading