SettleMint
API referenceEvents

token.transfer.final

Reference for token.transfer.final version 2, delivered after the configured chain reorg depth.

token.transfer.final version 2 reports a transfer only after its source block has passed the configured reorg depth. Subscribe to token.transfer.provisional for notice at inclusion and token.transfer.retracted for a reorg correction of that provisional observation.

Delivery contract

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

The receipt recommendation does not change delivery behavior. 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.

Version 2 is queued at inclusion and delivered after the source block passes the configured reorg depth. A chain reorg inside that window retracts only a delivered token.transfer.provisional event. DALP cancels an undelivered final row from the orphaned block; it does not send a reorg retraction of a version 2 final event.

Verify the signature, timestamp, and event identifier before processing. Default thin deliveries omit from and to; configure fat payloads only when your endpoint is authorized to receive those addresses.

Store evt_id, source_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 indexed transfer log.
logIndexIntegerIndex of the transfer log within its block.

Payload schema

The schema and examples describe the full payload. Thin delivery omits personal data fields. Use the payload-shape guidance to choose the endpoint configuration.

{
  "type": "object",
  "properties": {
    "tokenAddress": {
      "type": "string",
      "minLength": 42,
      "maxLength": 42,
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "A valid Ethereum address (42 characters, starting with 0x)",
      "examples": ["0x71C7656EC7ab88b098defB751B7401B5f6d8976F"]
    },
    "chainId": {
      "type": "integer",
      "exclusiveMinimum": 0
    },
    "from": {
      "type": "string",
      "minLength": 42,
      "maxLength": 42,
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "A valid Ethereum address (42 characters, starting with 0x)",
      "examples": ["0x71C7656EC7ab88b098defB751B7401B5f6d8976F"]
    },
    "to": {
      "type": "string",
      "minLength": 42,
      "maxLength": 42,
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "A valid Ethereum address (42 characters, starting with 0x)",
      "examples": ["0x71C7656EC7ab88b098defB751B7401B5f6d8976F"]
    },
    "amount": {
      "type": "string"
    },
    "transactionHash": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{64}$"
    },
    "blockNumber": {
      "type": "integer",
      "minimum": 0
    },
    "logIndex": {
      "type": "integer",
      "minimum": 0
    }
  },
  "required": ["tokenAddress", "chainId", "from", "to", "amount", "transactionHash", "blockNumber", "logIndex"],
  "additionalProperties": true
}

TypeScript SDK example

Use the request's raw body and headers with your endpoint's webhook secret. This handler illustrates verification and event selection. Before writing downstream state, deduplicate deliveries by evt_id and recognize replayed outcomes by their domain identifiers.

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,
  });
}

HTTP delivery example

This illustrative request shows the delivery shape. Its timestamp and signature are placeholders; a verifier rejects them. Use a signed platform delivery to verify your endpoint.

curl -X POST https://consumer.example.com/dalp/webhooks \
  -H "content-type: application/json" \
  -H "webhook-id: evt_a4eac9d5432394cd91b380838ddbd4a5" \
  -H "webhook-timestamp: 1778112000" \
  -H "webhook-signature: v1,docs-example-signature" \
  --data '{"evt_id":"evt_a4eac9d5432394cd91b380838ddbd4a5","source_id":"example:token.transfer.final@2:0","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":2,"request":{"idempotency_key":"idem_01JZP7R5W8M9N0P1Q2R3S4T5"}}'

Version and manifest

This page documents version 2 of token.transfer.final. This event type is not deprecated. The DALP events manifest contains the machine-readable AsyncAPI entry.

Manifest 2026-09-26 starts version 2 on deployment. Stored version 1 deliveries remain decodable and keep their original event IDs. Version 1 was emitted at inclusion. A reorg still retracts a delivered version 1 final event and cancels an undelivered one; version 2 is delivered after the configured reorg depth and is never retracted. Existing subscriptions to token.transfer.final continue to match the event name. Consumers should branch on version when interpreting historical deliveries. DALP does not backfill version 2 for an already delivered version 1 source.

On this page