Skip to main content

Track Universal Read

Overview

Track a Universal Read by its request ID, or by the Push Chain transaction that submitted it. You get the current state of the request and can wait for it to reach a terminal status.

Tracking works with a read-only client that has no signer and no funds. That makes it the right tool after a page refresh, from a backend, or when read() timed out at the client while the request kept running on chain.

Note: trackRead() can be used independently of read(). Save the request ID or transaction hash and resume from any session.

Track Universal Read

pushChainClient.universal.trackRead({ requestId } | { txHash }, {options}): Promise<UniversalReadResponse | UniversalReadResponse[]>

Tracking by transaction hash returns an array because one transaction can carry several reads.

const snapshot = await pushChainClient.universal.trackRead(
{ requestId },
{
progressHook: (progress) => {
console.log(progress.id + ': ' + progress.title);
},
}
);

const done = await snapshot.wait();
console.log(done.status, done.value);

These Arguments are mandatory

ArgumentsTypeDefaultDescription
ref.requestId | ref.txHashstring | bigint-The read's request ID (hex or numeric), or the Push Chain transaction that submitted it. Pass one.
options.resultShape{ kind: 'evmCall', abi, functionName } and othersInferredHow to decode resultData. Balances, storage and Web2 reads are inferred from the on-chain query. A typed contract call resumed in a new session needs it because the ABI is not on chain; without it value stays raw bytes.
options.progressHook(progress: ProgressEvent) => voidundefinedCallback invoked at each lifecycle step while wait() polls. See ProgressHook Type and Response below.
Advanced Arguments
ArgumentsTypeDefaultDescription
options.advanced.pollingIntervalMsnumber2000Milliseconds between polls when calling wait(). Minimum: 500.
options.advanced.timeoutnumberDerived from expiry, at most 180000Maximum milliseconds wait() polls before throwing ReadTimeoutError with code === 'READ_TIMEOUT'. Timing out cancels nothing; the request keeps running and you can track it again.

ProgressHook Type and Response

ProgressHook Type and Response
IDTitleMessageLevelResponse
READ-TX-104-02Request Confirmed, Read DetectedRead <requestId> requested in <txHash>SUCCESS{ txHash, requestId, logIndex }
READ-TX-105-01Awaiting QuorumValidators are observing the destination for <requestId>INFO{ requestId, status: 'PENDING' }
READ-TX-105-02Voting In ProgressValidators are voting on the result of <requestId>INFO{ requestId, status: 'VOTING' }
READ-TX-105-04Approaching Expiry<n> Push blocks until <requestId> expiresWARNING{ requestId, pushBlocksRemaining }
READ-TX-106-02Callback DeliveredReadFulfilled emitted for <requestId>SUCCESS{ requestId }
READ-TX-106-03Callback RevertedCallbackFailed for <requestId>; the read is still FULFILLED but your callback did not runWARNING{ requestId, reason }
READ-TX-106-04Callback Gas SettledBurned <n> UPC, refunding <n> UPCINFO{ requestId, burned, refunded }
READ-TX-106-05Refund Sent<amount> UPC pushed to <refundTo>INFO{ requestId, amount, refundTo }
READ-TX-106-06Refund Rejected<refundTo> rejected the refund; it sits in the admin rescue poolWARNING{ requestId, amount, refundTo }
READ-TX-199-01Read FulfilledRead <requestId> fulfilled and deliveredSUCCESS{ requestId, value, resultData, callbackDelivered }
READ-TX-199-02Read Failed / Expired / AbortedRead <requestId> ended <status>: <error>. A fulfilled read whose callback was not delivered also ends here, with status CALLBACK_FAILED (or SOURCE_ERROR, DECODE_FAILED)ERROR{ requestId, status, errorCode, errorMsg, refunded }
READ-TX-199-03Read TimeoutGave up waiting for <requestId> after <n>s; resume with trackReadERROR{ requestId, lastStatus, elapsedMs }
Returns `UniversalReadResponse` <object>

The returned snapshot is the current state of the request. Call wait() to poll until the read reaches a terminal status, or refresh() to fetch one fresh snapshot.

For the full response shape, see Read Universal State - Returns UniversalReadResponse.

Resume a Typed Contract Call

A typed contract call has no ABI on chain, so pass the ABI and function name through resultShape when you resume it in a new session.

const snapshot = await pushChainClient.universal.trackRead(
{ requestId },
{ resultShape: { kind: 'evmCall', abi: tokenAbi, functionName: 'totalSupply' } },
);

Note: Keep the ABI next to your stored request reference. resultShape supplies runtime decoding only; it cannot infer a TypeScript return type from a hash.

Live Playground

Tracking needs no wallet and no funds. Pick a predefined read, or track a request ID of your own.

Live Playground: Track a Read
VIRTUAL NODE IDE
Copy playground link
Copy code

Next Steps