Skip to main content
Every gasless write returns a transaction hash and nothing else. waitForTransaction answers the two questions that follow: did it actually succeed, and what did it emit. It is a standalone export, not a method on the SDK instance, so it needs no bearerToken.

Usage

Why a revert does not throw

A reverted transaction comes back as a result (success: false), never as a thrown error. Only “we do not know yet” throws, meaning a timeout or a transport failure.
That split is deliberate, because these are the two ways a hand-rolled polling loop goes wrong in a money flow:
  • A revert read as success double-credits a ledger. So a revert is a normal outcome you must branch on, which makes it a return value.
  • A timeout read as failure strands a transfer that later confirms. So a timeout is the one case where retrying is correct, which makes it an exception.

Parameters

Reading a receipt is idempotent, so nodeUrl is your slot in the ordered RPC chain: a transport failure advances to the next endpoint instead of aborting the wait. It defaults to the endpoint the SDK already uses for CHIPI wallets.

Return value

Returns a Promise<WaitForTransactionResult>: Each event is { from_address, keys, data }, exactly as the node returns it, for you to decode against your own ABI. keys[0] is the selector of the event name, so filter on from_address first, then match the selector.

Calling it from the client

Supported. waitForTransaction reads a receipt over RPC and needs no secret, so importing it into a browser hook is a first-class use, not a workaround.
This is now a guarantee rather than an accident. Until 14.12.1 the constants module read process.env at module scope, so a client import only worked because bundlers inject a process.env shim. Those reads are guarded, and a test fails the build if a bare process.env reappears in a browser-bundled module.
Anything needing a sk_ stays server-only. That split is about the secret, not about the runtime: waitForTransaction has no secret to leak.

Pairing with treasury webhooks

treasury.proposal.executed carries executedTxHash but no receipt, by design. This is the other half: take the hash from the webhook, resolve the receipt here, and read the event you care about.
RECEIVED, PENDING and PRE_CONFIRMED all count as not-yet-final. A hash that has not propagated yet reads as an error on most nodes, which is treated as a normal early poll rather than a failure.