Function: getMessagesInRange()
getMessagesInRange(
source:Chain,opts: {address?:string;endBefore?:string;endBlock?:number|bigint|"finalized"|"latest";page?:number|bigint;since?: {blockTimestamp?:number|bigint; };startBlock?:number|bigint;startTime?:number|bigint;topics?: (string|string[] |null)[];typeAndVersions?: readonly (string|RegExp)[];watch?:boolean|AbortSignal; }):AsyncIterableIterator<CCIPRequest<CCIPVersion>>
Defined in: requests.ts:541
Discover and decode CCIP messages within a block/slot/checkpoint range.
This is the range-scanning equivalent of getMessagesInTx. It composes Chain.getLogs and ChainStatic.decodeMessage to yield CCIP requests in discovery order without requiring transaction hashes upfront.
Results are yielded in native log order: (blockNumber, logIndex) ascending for EVM, slot order for Solana. Non-CCIP logs in the range are silently skipped.
Parameters
| Parameter | Type | Description |
|---|---|---|
source | Chain | Source chain to scan logs from |
opts | { address?: string; endBefore?: string; endBlock?: number | bigint | "finalized" | "latest"; page?: number | bigint; since?: { blockTimestamp?: number | bigint; }; startBlock?: number | bigint; startTime?: number | bigint; topics?: (string | string[] | null)[]; typeAndVersions?: readonly (string | RegExp)[]; watch?: boolean | AbortSignal; } | LogFilter options. Key fields: - startBlock / endBlock — block/slot range (endBlock supports 'finalized' and 'latest') - address — onRamp/router address (optional on EVM, required on Solana) - topics — defaults to both CCIP message event names - page — batch size for log pagination |
opts.address? | string | Contract address to filter logs by. |
opts.endBefore? | string | Cursor hint for the exclusive upper end of iteration on chains that support it. |
opts.endBlock? | number | bigint | "finalized" | "latest" | Ending block number (inclusive). |
opts.page? | number | bigint | Page size for pagination. |
opts.since? | { blockTimestamp?: number | bigint; } | Resume hint: the last log emitted by a previous getLogs call on the same address/filter. Any subset of fields may be provided; each chain uses what it can. Two layers of behavior: 1. Start floors (ALL chains — see withSinceStart): blockNumber and blockTimestamp stand in for startBlock/startTime — each effective floor is the LARGER of the explicitly requested bound and the hint's — so a since carrying either satisfies the start requirement on its own. Blocks/versions are always fetched and emitted complete. 2. Block completeness: all chains implementations must guarantee all logs in some block are yielded in the same call before it returns. 3. Exclusive resume (chains with a native per-log cursor): the hinted log itself is NOT re-emitted, and other logs in the same block/tx may also not be; some chains may attempt to yield logs in the same block or transaction, but from 2., the contract guarantees only that logs from the next block or tx on are emitted, so for an hermetic poller, it's safer to only ever pass the last finalized log in the previous call as since hint. The hint only ever RAISES the start floors — it never scans below startBlock/startTime — and a stale, foreign or malformed hint may be ignored (the usual walk runs). |
opts.since.blockTimestamp? | number | bigint | - |
opts.startBlock? | number | bigint | Starting block number (inclusive). Required unless startTime is provided; explicit 0 is allowed. |
opts.startTime? | number | bigint | Starting Unix timestamp (inclusive). |
opts.topics? | (string | string[] | null)[] | Topics to filter logs by. |
opts.typeAndVersions? | readonly (string | RegExp)[] | Restrict logs to contracts whose Chain.typeAndVersion matches any of these. Useful when filtering by topic alone (no address) would otherwise match logs from many unrelated contract types — e.g. ConfigSet is emitted by OnRamp, OffRamp, CommitStore, FeeQuoter, TokenPool, and PriceRegistry alike. Pass e.g. ['OnRamp'] to keep only on-ramps. See passesTypeAndVersion for the exact matching rule. undefined/empty means no restriction (default), and costs nothing — typeAndVersion is never called. |
opts.watch? | boolean | AbortSignal | watch mode: polls for new logs after fetching since start (required), until endBlock finality tag (e.g. endBlock=finalized polls only finalized logs); can be an AbortSignal to cancel loop |
Returns
AsyncIterableIterator<CCIPRequest<CCIPVersion>>
Async iterator of CCIPRequest objects in native log order
Throws
CCIPChainFamilyUnsupportedError if a pre-v1.6 message is found on a non-EVM chain
Throws
CCIPLogsAddressRequiredError on Solana if address is not provided
Examples
EVM — scan a block range for all CCIP messages
const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
for await (const request of getMessagesInRange(chain, {
startBlock: 1000000,
endBlock: 1001000,
address: '0xOnRampAddress...', // optional on EVM, but recommended for public RPCs
})) {
console.log(`seqNr=${request.message.sequenceNumber} dest=${request.lane.destChainSelector}`)
}
Solana — scan a slot range (address required)
const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
for await (const request of getMessagesInRange(chain, {
startBlock: 450000000,
endBlock: 450100000,
address: 'Ccip842gzYHh...', // router program address (required on Solana)
})) {
console.log(`seqNr=${request.message.sequenceNumber}`)
}
See
- getMessagesInTx - Per-transaction message discovery
- getMessagesInBatch - Batch discovery by sequence number range