SettleMint
Events

token.transfer.final

Reference for the DALP token.transfer.final webhook event that reports an indexed token transfer, final unless a chain reorg retracts it.

token.transfer.final tells a webhook consumer that DALP indexed a token transfer. The event is emitted at index time, so the source block can still sit inside the configured reorg window. The transfer is final unless a chain reorg invalidates the source log; in that case DALP emits a token.transfer.retracted event that supersedes this one.

Use this event to update downstream ledgers, reconciliation queues, and notification systems, and make those writes reversible: a consumer must handle token.transfer.retracted by reversing whatever this event caused, or must itself wait for the reorg depth before acting.

The event is part of the token transfer lifecycle. Pending observations can arrive before block inclusion; final events confirm the indexed on-chain log, subject to retraction. Consumers should treat the event payload as the stable transfer record and use the delivery envelope for idempotent processing.

Delivery contract

FieldValue
Event typetoken.transfer.final
Version1
Lifecycle statefinal
Counter-signed receiptsRecommended for endpoints that consume this event
SDK typeWebhook.TokenTransferFinalV1

This row gives advice only. DALP waits for a counter-signed receipt only if the webhook endpoint's counterSignedReceipts value is true when DALP queues the delivery. When the value is false, a normal 2xx response completes the delivery.

Related references:

  • idxr_token: the indexed token that emitted the transfer.

When to consume this event

Consume token.transfer.final when your integration needs an indexed transfer outcome rather than an early observation. Typical consumers include accounting exports, settlement reconciliation, investor notifications, and compliance monitoring systems.

The event fires at index time, inside the configured reorg window. A chain reorg can still invalidate the source log, and DALP then emits token.transfer.retracted superseding this event. Keep every downstream write this event triggers reversible, and reverse it when the retraction arrives, or delay acting until your own finality condition is met.

Do not use this event as a replacement for webhook verification. Verify the signature, timestamp, and event identifier before you process the payload.

Store evt_id, request.idempotency_key when present, and the transfer identifiers. These values keep a retry or replay from creating a duplicate downstream action.

See webhook idempotency and on-chain outcome for retry, replay, and lifecycle handling across pending, final, retracted, and recalled events.

Payload fields

FieldTypeMeaning
tokenAddressEVM addressToken contract that emitted the transfer.
chainIdIntegerEVM chain identifier for the indexed transfer.
fromEVM addressSender address recorded on the transfer log.
toEVM addressRecipient address recorded on the transfer log.
amountStringRaw token amount from the transfer event. Interpret decimals from the token metadata used by your integration.
transactionHash32-byte EVM hashTransaction that contained the transfer log.
blockNumberIntegerBlock that contained the finalized transfer log.
logIndexIntegerLog index of the transfer within the transaction receipt.

Payload schema

{
  "type": "object",
  "properties": {
    "tokenAddress": {
      "type": "string"
    },
    "chainId": {
      "type": "integer",
      "exclusiveMinimum": 0
    },
    "from": {
      "type": "string"
    },
    "to": {
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "transactionHash": {
      "type": "string"
    },
    "blockNumber": {
      "type": "integer",
      "minimum": 0
    },
    "logIndex": {
      "type": "integer",
      "minimum": 0
    }
  },
  "required": [
    "tokenAddress",
    "chainId",
    "from",
    "to",
    "amount",
    "transactionHash",
    "blockNumber",
    "logIndex"
  ],
  "additionalProperties": false
}

TypeScript SDK example

import { verifyWebhook } from "@settlemint/dalp-sdk/verify-webhook";
import type { Webhook } from "@settlemint/dalp-sdk";

const result = await verifyWebhook({
  rawBody,
  headers,
  secret: process.env.DALP_WEBHOOK_SECRET!,
});

if (!result.ok) {
  throw new Error(`Webhook verification failed: ${result.code}`);
}

if (result.event.type === "token.transfer.final") {
  const event: Webhook.Event<"token.transfer.final"> = result.event;
  const { transactionHash, logIndex, amount } = event.payload;

  await recordFinalTransfer({
    eventId: event.evt_id,
    idempotencyKey: event.request?.idempotency_key,
    transactionHash,
    logIndex,
    amount,
  });
}

curl example

curl -X POST https://consumer.example.com/dalp/webhooks \
  -H "content-type: application/json" \
  -H "webhook-id: evt_8f2baf5888a82c89394b3b3f421e576e" \
  -H "webhook-timestamp: 1778112000" \
  -H "webhook-signature: v1,docs-example-signature" \
  --data '{"evt_id":"evt_8f2baf5888a82c89394b3b3f421e576e","lifecycle_state":"final","payload":{"tokenAddress":"0x5555555555555555555555555555555555555555","chainId":537001,"from":"0x6666666666666666666666666666666666666666","to":"0x7777777777777777777777777777777777777777","amount":"250000000000000000000","transactionHash":"0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","blockNumber":18445240,"logIndex":7},"related":{"idxr_token":"idxr_token_example"},"type":"token.transfer.final","version":1,"request":{"idempotency_key":"idem_01JZP7R5W8M9N0P1Q2R3S4T5"}}'

Version history

  • Version 1: Initial registry entry for token.transfer.final.

Deprecation

This event type is not deprecated.

Manifest

The machine-readable AsyncAPI entry is published in the DALP events manifest.

On this page