History
Every lien ever recorded for one borrower, swept from the registry's own events.
The only question a caller can ask without having first been handed a lien id: how much a borrower has already pledged, and until when. It does not answer whether one specific receivable is pledged — that needs a lien id from the Lien reference.
Reference
liensOf
function liensOf(
client: CaplaneClient,
borrower: `0x${string}`,
options?: { fromBlock?: bigint },
): Promise<RecordedLien[]>
Sweeps LienRecorded events for one borrower, paginated by MAX_SPAN blocks per request and
retried with withRetry. Runs against a single endpoint (client.read), not the quorum every
other read in this package uses — the two default Arc Testnet endpoints do not share a log-range
limit, so comparing them would need on the order of a hundred paginated requests per endpoint
against a rate limiter. A caller who minds an endpoint quietly omitting an event should pass their
own node as client.read.
import { createCaplaneClient, liensOf } from 'caplane-sdk'
const client = createCaplaneClient()
const found = await liensOf(client, borrower)
Used in production by the MCP server's liens_of_borrower tool (services/mcp/src/tools.ts). The
public registry lookup's borrower search (web/app/[mode]/registry/history.ts) reimplements the
same sweep by hand against raw eth_getLogs, for the same bundle-size reason isEncumbered does —
it mirrors this function's pagination and retry shape rather than importing it.
DEPLOYED_AT
const DEPLOYED_AT: bigint // 61_681_981n
The block the registry was deployed at, and the default fromBlock for liensOf,
submissionsOf, and outcomeOf. A head-relative default would read as an empty history for
anything older than MAX_SPAN blocks — a lender misreading that as nothing pledged.
MAX_SPAN
const MAX_SPAN: bigint // 10_000n
The widest block range a single eth_getLogs call is allowed — the default Arc Testnet endpoint
refuses a wider one with -32614 eth_getLogs is limited to a 10,000 range. Every sweep in this
package pages by this span.
withRetry
function withRetry<T>(ask: () => Promise<T>, baseDelayMs?: number): Promise<T>
Retries a rejected page instead of losing the sweep — the initial call plus up to five retries,
doubling from baseDelayMs (default 2_000). Covers the endpoint shedding load under a legal
query (-32012 requested range too large) and plain rate limiting (-32005 rate limit exceeded);
a rejection that never clears is still raised after the sixth call (the initial attempt and all
five retries). Every paginated read in this
package (liensOf, submissionsOf, outcomeOf) calls this internally — reach for it directly
only when sweeping getLogs yourself against the same endpoints.
RecordedLien
type RecordedLien = {
lienId: `0x${string}`
borrower: `0x${string}`
expiresAt: bigint
blockNumber: bigint
}
One element of what liensOf resolves to — the fields available from a LienRecorded event
alone, without a follow-up call to lienOf.