@escro/sdk 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -4
- package/dist/index.cjs +5754 -461
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1455 -184
- package/dist/index.d.ts +1455 -184
- package/dist/index.js +5680 -462
- package/dist/index.js.map +1 -1
- package/package.json +13 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../../shared/src/types/escrow.ts","../../shared/src/types/bots.ts","../../shared/src/config.ts","../../shared/src/utils/canonicalize.ts","../../shared/src/utils/secret-scan.ts","../../shared/src/utils/index.ts","../../shared/src/auth.ts","../../shared/src/bot-descriptor.ts","../../shared/src/instructions.ts","../src/payments.ts","../src/errors.ts","../src/api.ts","../src/poll.ts","../src/solana.ts","../../shared/src/pda.ts","../../shared/src/accounts.ts","../src/adapter.ts","../src/adapter-contract.ts","../src/adapters/bittensor/index.ts","../src/adapters/gradients/index.ts","../src/adapters/ridges/index.ts","../src/adapters/404gen/index.ts","../src/adapters/lium/index.ts","../src/adapters/akash/index.ts","../src/adapters/render/index.ts","../src/adapters/gensyn/index.ts","../src/adapters/zkml/index.ts"],"sourcesContent":["import { Connection, PublicKey } from \"@solana/web3.js\";\nimport { disputeReasonError, verifyBotDescriptorSignature } from \"@escro/shared\";\nimport type {\n EscrowAccount,\n EscrowErrorCode,\n EscrowState,\n ProtocolStats,\n SolanaCluster,\n} from \"@escro/shared\";\nimport type { ServedWalletReputation } from \"@escro/reputation\";\nimport type {\n CreateEscrowParams,\n CreateEscrowResult,\n EscroOptions,\n ListOptions,\n PaginatedResult,\n PollOptions,\n RaiseDisputeParams,\n ReleasePaymentOutcome,\n SubmitDeliverableParams,\n WorkerCandidate,\n} from \"./types.js\";\nimport { ApiClient } from \"./api.js\";\nimport {\n EscroConfirmError,\n EscroError,\n EscrowNotFoundError,\n EscroRailNotEnabledError,\n} from \"./errors.js\";\nimport { EscrowPaymentRouter } from \"./payments.js\";\nimport type { PayParams, PaymentResult, PaymentRouter } from \"./payments.js\";\nimport { pollUntil } from \"./poll.js\";\nimport { buildReleasePaymentTx, fetchPlatformConfig, signAndSend } from \"./solana.js\";\n\n// How long {@link Escro.confirm} keeps retrying a not-yet-visible transaction.\nconst CONFIRM_WINDOW_MS = 30_000;\nconst CONFIRM_FIRST_DELAY_MS = 500;\nconst CONFIRM_MAX_DELAY_MS = 4_000;\n// Codes worth retrying: the transaction is not visible yet, the RPC failed, a\n// gateway answered without a server code (502/503/504 from the load balancer),\n// or a rate limit (confirm is idempotent).\nconst RETRYABLE_CONFIRM_CODES = [\n \"TX_NOT_FOUND\",\n \"RPC_UNAVAILABLE\",\n \"HTTP_502\",\n \"HTTP_503\",\n \"HTTP_504\",\n \"RATE_LIMITED\",\n \"HTTP_429\",\n] as const;\n\nfunction isRetryableConfirmCode(code: string): boolean {\n return (RETRYABLE_CONFIRM_CODES as readonly string[]).includes(code);\n}\n\n// A release the API's RPC cannot yet see as settled is refused, retryable.\nfunction isRetryableReleaseCode(code: string): boolean {\n return code === (\"ESCROW_NOT_SETTLED\" satisfies EscrowErrorCode) || isRetryableConfirmCode(code);\n}\n\n// The API's evidence rule (zod `.url()`): a string the WHATWG URL parser accepts.\nfunction isUrl(value: string): boolean {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nexport class Escro {\n private readonly connection: Connection;\n private readonly api: ApiClient;\n private readonly options: EscroOptions;\n private readonly cluster: SolanaCluster;\n private readonly router: PaymentRouter = new EscrowPaymentRouter();\n\n constructor(options: EscroOptions) {\n this.options = options;\n this.cluster = options.cluster;\n this.connection = new Connection(options.rpcUrl, \"confirmed\");\n this.api = new ApiClient(options.apiUrl, options.wallet);\n }\n\n // ── Buyer Bot ────────────────────────────────────────────────────────────────\n\n /**\n * Create a new escrow: registers with the API, signs and submits the\n * on-chain `create_escrow` transaction, then confirms it with the API.\n *\n * @returns `{ escrowId, escrowPda, signature }` — use `escrowPda` for all subsequent calls.\n */\n async createEscrow(params: CreateEscrowParams): Promise<CreateEscrowResult> {\n const { escrowId, escrowPda, unsignedTx } = await this.api.createEscrow(params);\n const signature = await this.send(unsignedTx);\n await this.confirm(escrowPda, signature);\n return { escrowId, escrowPda, signature };\n }\n\n /**\n * Release payment to the worker. Buyer must be the wallet in the constructor.\n * Builds and submits the `release_payment` on-chain tx FIRST (the chain is the\n * source of truth), then has the API record it, retrying as\n * {@link Escro.releasePaymentWithOutcome} does. Use that method to see whether the\n * API recorded the release.\n *\n * @returns Solana transaction signature.\n */\n async releasePayment(address: string): Promise<string> {\n const { signature } = await this.releasePaymentWithOutcome(address);\n return signature;\n }\n\n /**\n * {@link Escro.releasePayment}, reporting whether the API recorded the release.\n * `ESCROW_NOT_SETTLED` (the API's RPC does not yet show the escrow closed), the codes\n * {@link Escro.confirm} retries and a network failure are retried for about 30 s. A\n * failed record never throws: the release already landed, so the signature is returned\n * with `confirm.landed: false` and an `EscroConfirmError` (the API's code, or\n * `NETWORK_ERROR` when the last call never reached it). A release that failed at\n * execution on chain throws an {@link EscroError} with code `TX_FAILED`, and the API is\n * never asked to record it.\n *\n * @returns `{ signature, confirm }`.\n */\n async releasePaymentWithOutcome(address: string): Promise<ReleasePaymentOutcome> {\n // Fetch escrow metadata for worker pubkey + mint\n const escrow = await this.api.getEscrow(address);\n if (!escrow.taker) {\n throw new EscrowNotFoundError(`Escrow ${address} has no assigned worker`);\n }\n\n // Fetch platform config for treasury pubkey + usdc mint\n const { treasury, mint } = await fetchPlatformConfig(this.connection, this.cluster);\n\n // Build, sign, and submit the on-chain release_payment FIRST. The DB COMPLETED\n // write must NOT precede settlement — a failed on-chain tx would otherwise leave\n // the escrow COMPLETED in the DB but funded on-chain and dropped from the oracle\n // timeout sweep (H1×M2). The chain is the source of truth.\n const unsignedTx = await buildReleasePaymentTx({\n buyer: this.options.wallet.publicKey,\n escrowPda: new PublicKey(address),\n worker: new PublicKey(escrow.taker),\n mint,\n treasury,\n connection: this.connection,\n cluster: this.cluster,\n });\n const signature = await signAndSend(\n unsignedTx,\n this.options.wallet,\n this.connection,\n this.cluster,\n );\n\n // Record it AFTER the chain settled: /release records COMPLETED only once the API's RPC\n // shows the account closed, and refuses with ESCROW_NOT_SETTLED until then. A failure\n // past the retry window is reported, never thrown: the on-chain signature is authoritative.\n try {\n await this.retryRecord(\n address,\n signature,\n () => this.api.releasePaymentDb(address),\n isRetryableReleaseCode,\n );\n } catch (err) {\n if (!(err instanceof EscroConfirmError)) throw err;\n return { signature, confirm: { landed: false, error: err } };\n }\n\n return { signature, confirm: { landed: true } };\n }\n\n /**\n * Raise a dispute for an escrow. Either the buyer or the assigned worker\n * may call this. Signs and submits the `raise_dispute` on-chain tx, then confirms it with the API.\n *\n * @returns Solana transaction signature.\n */\n async raiseDispute(address: string, params: RaiseDisputeParams): Promise<string> {\n const reasonError = disputeReasonError(params.reason);\n if (reasonError !== null) throw new EscroError(reasonError, \"VALIDATION_ERROR\");\n // Checked before anything lands: confirm validates evidence only after the\n // dispute is on chain, where a rejection would leave it unrecorded.\n if (params.evidence !== undefined && !isUrl(params.evidence)) {\n throw new EscroError(`evidence must be a URL: ${params.evidence}`, \"VALIDATION_ERROR\");\n }\n const { unsignedTx } = await this.api.raiseDispute(address, { reason: params.reason });\n const signature = await this.send(unsignedTx);\n await this.confirm(address, signature, {\n ...(params.evidence !== undefined && { evidence: params.evidence }),\n });\n return signature;\n }\n\n /**\n * Cancel a funded escrow before any worker has claimed it.\n * Buyer must be the wallet in the constructor. Only valid when state is `FUNDED`.\n * Signs and submits the `cancel_escrow` on-chain tx, then confirms it with the API; full USDC refund to buyer.\n *\n * @returns Solana transaction signature.\n */\n async cancelEscrow(address: string): Promise<string> {\n const { unsignedTx } = await this.api.cancelEscrow(address);\n return this.sendAndConfirm(address, unsignedTx);\n }\n\n // ── Payments (dual-path; x402 reserved) ───────────────────────────────────────\n\n /**\n * Reserved synchronous-payment entrypoint (ARCHITECTURE §7a). `pay()` settles\n * over the x402 rail, which is not implemented until Phase 9; today it rejects\n * with {@link EscroRailNotEnabledError}. The signature is FROZEN so enabling\n * x402 later is not a breaking change for kit-generated bots. For asynchronous,\n * verification-needed work use {@link createEscrow}, the core product.\n *\n * Not `async`: it returns a rejected promise (never awaits) so callers can\n * `await`/`.catch()` it uniformly, and it exercises the same {@link PaymentRouter}\n * routing seam Phase 9 will implement.\n */\n pay(params: PayParams): Promise<PaymentResult> {\n // The router only selects rails enabled in this build. A pay() call requests\n // the synchronous rail; x402 is reserved and not enabled, so the router falls\n // back to escrow, and pay() is not the escrow path (createEscrow is), so\n // there is no synchronous backend to service the call.\n const rail = this.router.selectRail({\n to: params.to,\n amountMicroUsdc: params.amountMicroUsdc,\n mode: \"sync\",\n });\n return Promise.reject(new EscroRailNotEnabledError(rail === \"escrow\" ? \"x402\" : rail));\n }\n\n // ── Worker Bot ───────────────────────────────────────────────────────────────\n\n /**\n * Claim an assigned task. Worker must be the wallet in the constructor.\n * Signs and submits the `claim_task` on-chain tx, then confirms it with the API.\n *\n * @returns Solana transaction signature.\n */\n async claimTask(address: string): Promise<string> {\n const { unsignedTx } = await this.api.claimTask(address);\n return this.sendAndConfirm(address, unsignedTx);\n }\n\n /**\n * Submit a deliverable for the buyer to review. Worker must be the wallet.\n * Signs and submits the `submit_deliverable` on-chain tx, then confirms it with the API.\n *\n * @returns Solana transaction signature.\n */\n async submitDeliverable(address: string, params: SubmitDeliverableParams): Promise<string> {\n const { unsignedTx } = await this.api.submitDeliverable(address, params);\n return this.sendAndConfirm(address, unsignedTx);\n }\n\n /**\n * List tasks assigned to the wallet's public key.\n * Optionally filter by state(s) and paginate results.\n *\n * If `options.poll` is true, polls with exponential backoff until at least\n * one task is returned.\n *\n * @param state - Filter by one or more states (first state used as API filter).\n * @param options - Polling, pagination (limit/offset).\n */\n async getMyTasks(\n state?: EscrowState[],\n options?: PollOptions & ListOptions,\n ): Promise<PaginatedResult<EscrowAccount>> {\n const assignedTo = this.options.wallet.publicKey.toBase58();\n const params: Parameters<ApiClient[\"listEscrows\"]>[0] = {\n assignedTo,\n ...(state?.[0] != null && { state: state[0] }),\n ...(options?.limit != null && { limit: options.limit }),\n ...(options?.offset != null && { offset: options.offset }),\n };\n\n if (!options?.poll) {\n return this.api.listEscrows(params);\n }\n\n const fetcher = () =>\n this.api.listEscrows(params).then((result) => (result.items.length > 0 ? result : null));\n\n return pollUntil(\n assignedTo,\n fetcher,\n (r): r is PaginatedResult<EscrowAccount> => r !== null,\n options.timeoutMs,\n );\n }\n\n /**\n * List escrows CREATED by the wallet's public key (the maker / buyer), the\n * mirror of {@link getMyTasks} for the buyer side. Optionally filter by state\n * and paginate.\n *\n * A Buyer Bot uses this to sum its own outstanding (still-locked) escrows for\n * the client-side spend cap: the program is the source of truth, so the total\n * is read from chain state (via the API), never a local tally a crash could lose.\n *\n * @param state - Filter by one or more states (first state used as API filter).\n * @param options - Polling, pagination (limit/offset).\n */\n async getMyEscrows(\n state?: EscrowState[],\n options?: PollOptions & ListOptions,\n ): Promise<PaginatedResult<EscrowAccount>> {\n const maker = this.options.wallet.publicKey.toBase58();\n const params: Parameters<ApiClient[\"listEscrows\"]>[0] = {\n maker,\n ...(state?.[0] != null && { state: state[0] }),\n ...(options?.limit != null && { limit: options.limit }),\n ...(options?.offset != null && { offset: options.offset }),\n };\n\n if (!options?.poll) {\n return this.api.listEscrows(params);\n }\n\n const fetcher = () =>\n this.api.listEscrows(params).then((result) => (result.items.length > 0 ? result : null));\n\n return pollUntil(\n maker,\n fetcher,\n (r): r is PaginatedResult<EscrowAccount> => r !== null,\n options.timeoutMs,\n );\n }\n\n // ── EscroBots discovery ──────────────────────────────────────────────────────\n\n /**\n * Find worker bots in the EscroBots registry, optionally filtered by\n * capability. Queries `GET /v1/bots?role=worker` (the API includes `both`\n * bots) and returns candidates in REGISTRY ORDER: this method does no\n * ranking, scoring, or reordering (ARCHITECTURE §8: no curation; §13: not a\n * marketplace). Escro-shipped code never ranks; the caller's own bot decides.\n *\n * Each candidate keeps the CLAIM (`descriptor`) separate from the AUTHORSHIP\n * check (`signatureValid`, verified locally so a third party need not trust the\n * API). Capabilities remain unverified claims; on-chain history (EscroRep,\n * Phase 7) is their verification, deliberately not merged in here.\n */\n async findWorkers(\n params: { capability?: string } & ListOptions = {},\n ): Promise<WorkerCandidate[]> {\n const { items } = await this.api.listBots({\n role: \"worker\",\n ...(params.capability != null && { capability: params.capability }),\n ...(params.limit != null && { limit: params.limit }),\n ...(params.offset != null && { offset: params.offset }),\n });\n return items.map((descriptor) => ({\n descriptor,\n signatureValid: verifyBotDescriptorSignature(descriptor),\n }));\n }\n\n /**\n * Fetch the EscroRep bulk export: every indexed wallet's RAW reputation\n * components (ARCHITECTURE §9), each wallet exactly once, in one fetch. Returns\n * the raw components verbatim - this method does NO ranking, scoring, or default\n * weighting (Escro-shipped code never ranks; the caller's own bot weights and\n * decides). Selection layers join these components to {@link findWorkers}\n * candidates by wallet. Throws {@link ReputationUnavailableError} when the\n * deployment mounts no reputation source (HTTP 404).\n */\n async listReputations(): Promise<ServedWalletReputation[]> {\n return this.api.listReputations();\n }\n\n // ── Stats ────────────────────────────────────────────────────────────────────\n\n /**\n * Fetch protocol-wide stats from the public `GET /v1/stats` endpoint.\n *\n * @returns protocol-wide {@link ProtocolStats}.\n */\n async getStats(): Promise<ProtocolStats> {\n const data = await this.api.getStats();\n return data as ProtocolStats;\n }\n\n // ── Shared ───────────────────────────────────────────────────────────────────\n\n /**\n * Ask the API to record the create, claim, submit, cancel or dispute that the\n * landed `signature` carries; the API verifies it on chain first. Retries a\n * not-yet-visible transaction, an RPC failure, a gateway error or a rate limit\n * for about 30 s (waiting at least a sent Retry-After), never a rejection. Throws\n * {@link EscroConfirmError}; calling again is safe (a replay of a recorded\n * transition succeeds).\n */\n async confirm(\n address: string,\n signature: string,\n opts: { evidence?: string } = {},\n ): Promise<EscrowAccount> {\n return this.retryRecord(\n address,\n signature,\n () => this.api.confirm(address, signature, opts.evidence),\n isRetryableConfirmCode,\n );\n }\n\n // Calls `record` until the API records the landed `signature`: a code `retryable` accepts or\n // a network failure is retried for about 30 s (waiting at least a sent Retry-After), any\n // other refusal is not. Throws EscroConfirmError.\n private async retryRecord<T>(\n address: string,\n signature: string,\n record: () => Promise<T>,\n retryable: (code: string) => boolean,\n ): Promise<T> {\n const deadline = Date.now() + CONFIRM_WINDOW_MS;\n let delay = CONFIRM_FIRST_DELAY_MS;\n for (;;) {\n let code: string;\n let message: string;\n let retryAfterMs: number | undefined;\n let wait = delay;\n try {\n return await record();\n } catch (err) {\n if (err instanceof EscroError) {\n if (!retryable(err.code)) {\n throw new EscroConfirmError(\n address,\n signature,\n err.code,\n err.message,\n err.retryAfterMs,\n );\n }\n code = err.code;\n message = err.message;\n retryAfterMs = err.retryAfterMs;\n wait = Math.max(delay, err.retryAfterMs ?? 0);\n } else {\n // A network failure: the request may not have reached the API.\n code = \"NETWORK_ERROR\";\n message = err instanceof Error ? err.message : String(err);\n }\n }\n if (Date.now() + wait > deadline) {\n throw new EscroConfirmError(address, signature, code, message, retryAfterMs);\n }\n await sleep(wait);\n delay = Math.min(delay * 2, CONFIRM_MAX_DELAY_MS);\n }\n }\n\n private send(unsignedTx: string): Promise<string> {\n return signAndSend(unsignedTx, this.options.wallet, this.connection, this.cluster);\n }\n\n private async sendAndConfirm(address: string, unsignedTx: string): Promise<string> {\n const signature = await this.send(unsignedTx);\n await this.confirm(address, signature);\n return signature;\n }\n\n /**\n * Fetch an escrow by its PDA address.\n * If `options.poll` is true, polls with exponential backoff until the escrow\n * appears (useful immediately after a create tx before the API DB syncs).\n */\n async getEscrow(address: string, options?: PollOptions): Promise<EscrowAccount> {\n if (!options?.poll) {\n return this.api.getEscrow(address);\n }\n\n return pollUntil(\n address,\n () =>\n this.api.getEscrow(address).catch((e: unknown) => {\n if (e instanceof EscrowNotFoundError) return null;\n throw e instanceof Error ? e : new Error(String(e));\n }),\n (r): r is EscrowAccount => r !== null,\n options.timeoutMs,\n );\n }\n}\n","import type { SolanaCluster } from \"../config.js\";\n\n/**\n * All possible lifecycle states of an AgentEscrow account on-chain.\n *\n * State transitions (happy path):\n * CREATED → FUNDED → IN_PROGRESS → SUBMITTED → COMPLETED\n *\n * Exception paths:\n * Any state (before COMPLETED) → DISPUTED (human arbitration)\n * CREATED | FUNDED → CANCELLED (buyer cancels before agent accepts)\n * SUBMITTED → COMPLETED (24h timeout auto-release to worker)\n * IN_PROGRESS → REFUNDED (deadline expiry auto-refund to buyer)\n */\nexport enum EscrowState {\n /** Escrow PDA created on-chain; awaiting token deposit from the maker. */\n CREATED = \"CREATED\",\n /** Maker deposited tokens into the vault; open for agent acceptance. */\n FUNDED = \"FUNDED\",\n /** An agent accepted the task; work is underway. */\n IN_PROGRESS = \"IN_PROGRESS\",\n /** Agent submitted a deliverable URI; awaiting buyer review or 24h auto-release. */\n SUBMITTED = \"SUBMITTED\",\n /** Funds released to the agent. Terminal state. */\n COMPLETED = \"COMPLETED\",\n /** Buyer cancelled before work started. Terminal state. */\n CANCELLED = \"CANCELLED\",\n /** Maker or agent raised a dispute; requires human arbitration. */\n DISPUTED = \"DISPUTED\",\n /** Funds returned to the maker (deadline expiry or dispute resolution). Terminal state. */\n REFUNDED = \"REFUNDED\",\n}\n\n/** Solana cluster the escrow account lives on. */\nexport type Network = \"mainnet-beta\" | \"devnet\" | \"localnet\";\n\n/**\n * Full on-chain representation of an AgentEscrow PDA, enriched with\n * off-chain metadata resolved by the API server.\n *\n * `amount` and all `*At` timestamps use the on-chain units:\n * - `amount` is in the SPL token's smallest denomination (e.g. μUSDC = 10⁻⁶ USDC).\n * - timestamps are Unix seconds as stored in the Anchor account.\n *\n * When serialising over HTTP, `amount` is represented as a decimal `string`\n * (see {@link GetEscrowResponse}) to avoid JSON `number` precision loss.\n */\nexport interface EscrowAccount {\n /** Base-58 public key of the escrow PDA. */\n address: string;\n /** Base-58 public key of the task creator (the party paying for the work). */\n maker: string;\n /** Base-58 public key of the assigned agent, or `null` if no agent has accepted yet. */\n taker: string | null;\n /** Base-58 public key of the SPL token mint used for payment (e.g. USDC mint). */\n mint: string;\n /**\n * Payment amount held in escrow, in the mint's smallest denomination.\n * Stored as `bigint` to preserve full u64 precision from the on-chain account.\n */\n amount: bigint;\n /** Current lifecycle state of the escrow. */\n state: EscrowState;\n /**\n * SHA-256 hex digest of the canonical UTF-8 JSON serialisation of the {@link TaskSpec}.\n * Recorded on-chain (the account's `spec_hash` holds this hash, bare, or as `ipfs://<hash>` on\n * escrows created before P18.T0c), so the buyer and worker (and an arbitrator) can check that a\n * spec is the one the escrow was created for.\n */\n taskSpecHash: string;\n /**\n * The exact string the escrow's on-chain `spec_hash` holds: the bare 64-hex `taskSpecHash`\n * (escrows created since P18.T0c), `ipfs://<taskSpecHash>` (earlier), `null` before the\n * spec_uri migration ran. A label for the {@link TaskSpec}'s hash, not a fetchable copy (Escro\n * stores no spec body; the buyer shares the spec).\n */\n taskSpecUri: string | null;\n /** Base-58 public key of the oracle authority permitted to sign timeout_release / refund_buyer. */\n oracle: string;\n /**\n * Platform fee in basis points. The API serves the value it recorded at registration\n * (`PLATFORM_FEE_BPS`, the mirror of PlatformConfig `fee_bps`); on chain `create_escrow`\n * stores PlatformConfig's value. Additive: the buyer deposits `amount` plus the fee and\n * the worker receives the full `amount`.\n */\n oracleFeeBps: number;\n /** Unix timestamp (seconds) when the escrow PDA was initialised. */\n createdAt: number;\n /**\n * Unix timestamp (seconds) at which the escrow deadline expires; mirrors the\n * on-chain `deadline` field set at `create_escrow`. A Worker Bot reads this to\n * decide whether it can finish a job before the deadline (never claim what it\n * can't finish); after it passes, an unstarted escrow is refundable to the maker.\n */\n deadline: number;\n /** Unix timestamp (seconds) of the most recent agent submission, or `null`. */\n submittedAt: number | null;\n /**\n * SHA-256 hex digest of the worker's submitted deliverable, mirrored from the\n * on-chain `deliverable_hash` written at `submit_deliverable`; `null` until the\n * escrow reaches SUBMITTED. The on-chain value is authoritative: a Buyer Bot's\n * review re-verifies a deliverable against a hash it independently expects and\n * never treats this mirror as proof of integrity on its own.\n */\n deliverableHash: string | null;\n /**\n * URI of the submitted deliverable artifact (S3 presigned / IPFS / Arweave),\n * mirrored from the off-chain `proof_uri` recorded at `submit_deliverable`;\n * `null` until SUBMITTED. The Buyer Bot fetches the deliverable content here to\n * review it.\n */\n proofUri: string | null;\n /** PDA canonical bump seed, stored on-chain to validate future instructions. */\n bump: number;\n /** Solana cluster this account belongs to. */\n network: Network;\n}\n\n/**\n * First-class settlement cause for an escrow, recorded off-chain (EscroRep\n * fidelity — P7.T2e). One value per fund-moving instruction, keyed 1:1 to the\n * reducer's `EscrowEventKind` (packages/reputation) so the DB-served reputation\n * matches the on-chain reducer. The cause also encodes the dispute OUTCOME:\n * `ARBITRATION_RELEASE` = worker prevailed, `ARBITRATION_REFUND` = buyer\n * prevailed (#23.3). Single-sourced here and mirrored by the `escrows.settlement_cause`\n * CHECK allow-list (a drift test binds the two); never caller-supplied.\n *\n * Declared as a `const` array (not a bare union) so the value list has a single\n * runtime source the migration-drift test and any validator read from.\n */\nexport const SETTLEMENT_CAUSES = [\n /** Buyer-signed release_payment — explicit completion (#23.1). */\n \"EXPLICIT_RELEASE\",\n /** Oracle timeout_release — 24h auto-release completion (#23.1, buyer non-response). */\n \"TIMEOUT_RELEASE\",\n /** admin arbitration_release — worker prevailed in a dispute (#23.3), not a completion. */\n \"ARBITRATION_RELEASE\",\n /** Deadline-expiry refund_buyer (any cranker) — worker non-delivery (#23.2). */\n \"DEADLINE_REFUND\",\n /** admin arbitration_refund — buyer prevailed in a dispute (#23.3). */\n \"ARBITRATION_REFUND\",\n /** cancel_escrow — buyer cancelled a FUNDED escrow before any claim. */\n \"CANCELLED\",\n] as const;\n\n/** A settlement cause recorded on `escrows.settlement_cause` (see {@link SETTLEMENT_CAUSES}). */\nexport type SettlementCause = (typeof SETTLEMENT_CAUSES)[number];\n\n/**\n * Every `event_type` the oracle writes to the `oracle_events` audit table\n * (packages/oracle logEvent). Single-sourced here; the `oracle_events.event_type`\n * CHECK allow-list must ACCEPT every value here (a drift test asserts the CHECK is\n * a superset of this union, in packages/api oracle-events-constraint.test.ts; the\n * CHECK may additionally keep grandfathered legacy values with no live emitter).\n * This exists because a CHECK that lags the emitted set silently drops the write\n * (logEvent must not fail the SQS message, so it cannot surface a rejection as a\n * throw): P7.T2d found the reconciliation types below rejected by the constraint,\n * so every reconciliation audit write was failing. Typing logEvent's `eventType`\n * to {@link OracleEventType} closes the same class at compile time.\n *\n * Declared as a `const` array (not a bare union) so the value list has a single\n * runtime source the migration-drift test reads.\n */\nexport const ORACLE_EVENT_TYPES = [\n /** Oracle-signed timeout_release settled the escrow (24h auto-release completion). */\n \"TIMEOUT_RELEASE\",\n /** Permissionless refund_buyer settled the escrow (deadline-expiry refund). */\n \"AUTO_REFUND\",\n /** A duplicate SQS delivery: the escrow was already settled, nothing signed. */\n \"ALREADY_SETTLED\",\n /** M2b reconciler re-synced a fake DB-DISPUTED row to its on-chain state. */\n \"DISPUTE_RECONCILED\",\n /** Reconciler folded a closed escrow's DB row to its actual on-chain settlement. */\n \"RECONCILED\",\n /** Reconciler could not read the settling instruction, so it wrote nothing terminal. */\n \"RECONCILE_INDETERMINATE\",\n /** Settlement attempted before its on-chain time gate opened (silent backoff, not a failure). */\n \"NOT_YET_ELIGIBLE\",\n /** An unknown/forged message type was dropped (the oracle allowlists only its own types). */\n \"UNKNOWN_MESSAGE_TYPE\",\n] as const;\n\n/** An `event_type` written to `oracle_events` (see {@link ORACLE_EVENT_TYPES}). */\nexport type OracleEventType = (typeof ORACLE_EVENT_TYPES)[number];\n\n/** One set of `GET /v1/stats` figures: the public block, or the operator block. */\nexport interface ProtocolStatsFigures {\n totalEscrows: number;\n totalVolumeUsdc: string;\n /**\n * Settled USDC volume: the sum of `amount_usdc` (the job amount, which the\n * worker keeps in full; the additive platform fee is protocol revenue, not\n * settled work volume) over escrows in the COMPLETED terminal state. COMPLETED\n * is reached only by the three worker-paying instructions (release_payment,\n * timeout_release, arbitration_release); refunded and cancelled escrows never\n * paid a worker and are excluded. This is the honest headline number: it counts\n * settlement, not transaction volume.\n */\n settledVolumeUsdc: string;\n byState: Record<EscrowState, number>;\n activeEscrows: number;\n}\n\n/** Protocol-wide aggregate statistics: public, unauthenticated. */\nexport interface ProtocolStats extends ProtocolStatsFigures {\n /** The Solana cluster this API serves (its `CLUSTER`). */\n cluster: SolanaCluster;\n /** That cluster's one USDC mint (`getUsdcMint`): every figure here is in this token. */\n usdcMint: string;\n /**\n * Escro-operated fleet figures (ARCHITECTURE section 9): the same fields over\n * escrows whose buyer and assigned worker are both in the API's operator\n * allowlist. They are real settlements but not third-party demand, so every\n * public field excludes them; never sum this block with the public fields.\n */\n operator: ProtocolStatsFigures;\n}\n\n/** One worker's settled earnings over an activity window; wallet anonymised. */\nexport interface ActivityEarner {\n /**\n * Anonymised worker wallet: a truncated display form (`first4...last4`), never\n * the full address. Truncation is a display convenience, not a privacy boundary\n * (Solana addresses are public and EscroRep exposes full per-wallet history).\n */\n wallet: string;\n /** Settled USDC (job amount) the worker earned in the window. */\n settledVolumeUsdc: string;\n /** Number of escrows the worker settled (reached COMPLETED) in the window. */\n jobsSettled: number;\n}\n\n/**\n * Activity leaderboard: anonymised top earners over a rolling window. The data\n * source behind escro.ai/activity (weekly earners). Public, unauthenticated.\n */\nexport interface ActivityLeaderboard {\n /** The Solana cluster this API serves (its `CLUSTER`). */\n cluster: SolanaCluster;\n /** That cluster's one USDC mint (`getUsdcMint`): every earning here is in this token. */\n usdcMint: string;\n /** Rolling window length in days (7 = weekly earners). */\n periodDays: number;\n /** Top earners, descending by settled volume. */\n earners: ActivityEarner[];\n}\n","/**\n * EscroBots v0 - the permissionless capability directory (ARCHITECTURE §8).\n *\n * A bot advertises itself by publishing a wallet-signed capability descriptor.\n * The descriptor is a *claim*, not a verified fact - on-chain history is the\n * verification (surfaced in the Phase 7 v1 directory). The registry performs no\n * approval, review, or ranking; fraud against the protocol is the only removal\n * criterion. The descriptor document itself is independently verifiable: anyone\n * holding it can check `signature` against `wallet` without trusting the API.\n */\n\n/**\n * The advertisable roles. Single source for both the `BotRole` type and the API's\n * zod enum (routes/bots.ts uses `z.enum(BOT_ROLES)`), so the accepted values and\n * the type cannot drift: a role added here flows into validation automatically.\n */\nexport const BOT_ROLES = [\"worker\", \"buyer\", \"both\"] as const;\n\n/** Whether the bot hires work, performs work, or both. */\nexport type BotRole = (typeof BOT_ROLES)[number];\n\n/**\n * The descriptor fields the bot's wallet signs. Everything a registry consumer\n * needs to find and reach the bot, minus the signature over these fields.\n */\nexport interface UnsignedBotDescriptor {\n /** Base58 Solana pubkey - the advertising bot and the descriptor's signer. */\n wallet: string;\n /** What the bot does in the escrow relationship. */\n role: BotRole;\n /** Free-form capability tags, e.g. `[\"fine-tune\", \"eval\"]`. Filterable. */\n capabilities: string[];\n /** The underlying service the bot wraps, e.g. `\"bittensor:sn56\"`. */\n serviceRef: string;\n /** Human-readable pricing guidance, e.g. `\"~$5 per fine-tune job\"`. */\n pricingHint: string;\n /** Optional http(s) endpoint a buyer can reach the bot at. */\n endpoint?: string;\n /** Unix milliseconds when the descriptor was signed. Monotonic per wallet. */\n signedAt: number;\n}\n\n/**\n * A signed capability descriptor as stored and served by the registry.\n * `signature` is a base58 detached Ed25519 signature over the canonical form of\n * the {@link UnsignedBotDescriptor} fields (see `canonicalBotDescriptorMessage`).\n */\nexport interface BotDescriptor extends UnsignedBotDescriptor {\n /** Base58 detached Ed25519 signature over the canonical unsigned descriptor. */\n signature: string;\n}\n","// Cluster-aware on-chain configuration. The devnet block is rewritten by\n// `packages/program/scripts/deploy.ts` after each devnet deploy. The mainnet\n// block is replaced ONLY by `scripts/deploy-mainnet.sh` (or by a human editing\n// this file as part of a mainnet bootstrap). Manual edits to the devnet block\n// will be overwritten by the next devnet deploy.\n//\n// Why cluster-aware: the devnet and mainnet programs have different program\n// IDs so that a leaked devnet upgrade authority cannot push a malicious\n// upgrade to mainnet. See docs/PROGRAM_UPGRADE_RUNBOOK.md \"Mainnet deploys\".\n\nexport type SolanaCluster = \"devnet\" | \"mainnet\";\n\n// ── Devnet (auto-generated by deploy.ts) ──────────────────────────────────────\nexport const PROGRAM_ID_DEVNET = \"EjLpJ3obUYk1f2KDensU7UdGBZTxSdxufm7CSnMA3H5C\" as const;\nexport const PLATFORM_CONFIG_PDA_DEVNET = \"5BYnq9YsCTaMxBLJhBn4TPnCQuxiHcG5eZ2ygLJBu9dc\" as const;\nexport const DEVNET_USDC_MINT = \"4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU\" as const;\nexport const DEPLOYED_AT_DEVNET = \"2026-08-15T17:24:37.149Z\" as const;\n\n// ── Mainnet (replaced by scripts/deploy-mainnet.sh — see runbook) ─────────────\nexport const PROGRAM_ID_MAINNET = \"4CwLNRF4mFXutiBGjtMHQBxh8whW8T8EyvJXdRhY1rvr\" as const;\nexport const PLATFORM_CONFIG_PDA_MAINNET = \"7zPti535SmzvkdtmKaGR8w4niHLiEidWCqCaQXLbQvhn\" as const;\nexport const MAINNET_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\" as const;\n// Pinned mainnet PlatformConfig values, compared by the PlatformConfig change\n// alert (infra platform-config-watch). After a deliberate `update_platform` the\n// alarm stays raised until these pins are updated and the stack redeployed.\nexport const MAINNET_TREASURY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\nexport const MAINNET_ORACLE_AUTHORITY = \"G2Cr4PAJ58ZSYX2ceCMt2DtP1KBFXA9oYDtJJKZaKKJT\" as const;\n// Program upgrade authority since T0a (2026-08-18): the 2-of-2 Squads vault. The same\n// address as the treasury, named separately because the roles are distinct.\nexport const MAINNET_UPGRADE_AUTHORITY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\n\n// ── Cluster genesis hashes (no deploy rewrites these) ─────────────────────────\n// An RPC proves its cluster by its genesis hash; the ops CLIs refuse a mismatch.\nexport const DEVNET_GENESIS_HASH = \"EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG\" as const;\nexport const MAINNET_GENESIS_HASH = \"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d\" as const;\n\n// ── Escro REST API base URLs (per cluster) ────────────────────────────────────\n//\n// Stable per-cluster domains: MIRROR of infra/bin/escro.ts `domainName`. The SDK,\n// the generated bot projects, and the Bot Kit CLI all resolve the default API base\n// from here rather than hardcoding a literal (same \"cluster config lives in one\n// place\" rule as the program id / mint). A self-hoster or a localnet run overrides\n// it with an explicit apiUrl; this is only the default.\nexport const API_URLS: Record<SolanaCluster, string> = {\n devnet: \"https://api-devnet.escro.ai\",\n mainnet: \"https://api.escro.ai\",\n};\n\nexport function getApiUrl(cluster: SolanaCluster): string {\n return API_URLS[cluster];\n}\n\n// ── Cluster-agnostic ──────────────────────────────────────────────────────────\n\n/** Platform oracle fee rate in basis points (50 bps = 0.50%). */\nexport const PLATFORM_FEE_BPS = 50 as const;\n\n/**\n * Minimum escrow amount in μUSDC (6 decimals), i.e. the worker's net `amount`.\n * MIRROR of the on-chain constant — MUST equal `MIN_ESCROW_AMOUNT` in\n * packages/program/programs/escro/src/lib.rs, which create_escrow enforces via\n * `require!(params.amount >= MIN_ESCROW_AMOUNT, AmountBelowMinimum)`. A drift is\n * caught in CI by src/onchain-timing.test.ts, which reads lib.rs.\n *\n * Note: the platform fee is ADDITIVE — the buyer deposits `amount + fee` (see\n * create_escrow.rs), and this minimum applies to `amount` (the worker's net),\n * not to the buyer's total deposit.\n */\nexport const MIN_ESCROW_AMOUNT = 5_000_000 as const; // 5_000_000 μUSDC = $5.00\n\n/**\n * The account layout version the program writes and accepts. MIRROR of\n * `CURRENT_ACCOUNT_VERSION` in packages/program/programs/escro/src/lib.rs; a drift is\n * caught in CI by src/onchain-timing.test.ts, which reads lib.rs.\n */\nexport const CURRENT_ACCOUNT_VERSION = 1 as const;\n\n/**\n * The most UTF-8 bytes `raise_dispute` accepts as a reason. MIRROR of `MAX_REASON_LEN` in\n * packages/program/programs/escro/src/instructions/raise_dispute.rs, locked by\n * src/onchain-timing.test.ts. Checked off chain by `disputeReasonError`.\n */\nexport const MAX_DISPUTE_REASON_BYTES = 200 as const;\n\n/**\n * The most UTF-8 bytes `create_escrow`'s `spec_hash` may hold. MIRROR of `#[max_len(64)]` on\n * `spec_hash` in packages/program/programs/escro/src/state/escrow_account.rs, locked by\n * src/onchain-timing.test.ts. The program bounds the field only by the account's allocation; the\n * API's create builder enforces this cap.\n */\nexport const MAX_SPEC_HASH_BYTES = 64 as const;\n\n/**\n * Indeterminate reconciles an escrow may accrue (since its row last changed) before the\n * scanner stops enqueueing it and the oracle alerts once. Each one follows a read that found\n * the account closed, so an excluded escrow has nothing left to sign. The oracle, the scanner\n * and ops' restate filter read this one constant.\n */\nexport const RECONCILE_ATTEMPT_BOUND = 5;\n\n// ── On-chain timing gates + clock-skew margin ─────────────────────────────────\n//\n// MIRROR of the on-chain Rust constants. These MUST equal the program's values:\n// ONCHAIN_REFUND_GRACE_SECONDS == refund_buyer.rs REFUND_GRACE_SECONDS (non-feature)\n// ONCHAIN_TIMEOUT_SECONDS == timeout_release.rs TIMEOUT_SECONDS (non-feature)\n// A drift is caught in CI by src/onchain-timing.test.ts, which reads the .rs files.\nexport const ONCHAIN_REFUND_GRACE_SECONDS = 900 as const; // 15 min\nexport const ONCHAIN_TIMEOUT_SECONDS = 86_400 as const; // 24 h\n\n/**\n * Clock-skew margin. The Solana cluster clock lags wall-clock, so any OFF-CHAIN\n * timing gate that must clear an ON-CHAIN gate has to be strictly later/more\n * lenient by at least this much — otherwise the off-chain side fires at the\n * boundary while the chain still rejects, producing transient reverts. Governing\n * rule for off-chain scheduling: off-chain offset = on-chain offset + skew.\n */\nexport const CLOCK_SKEW_SECONDS = 60 as const;\n\n/** Scanner refund-sweep offset: strictly greater than on-chain refund grace. */\nexport const SCANNER_REFUND_GRACE_SECONDS = (ONCHAIN_REFUND_GRACE_SECONDS +\n CLOCK_SKEW_SECONDS) as 960; // 960\n/** Scanner timeout-release offset: strictly greater than on-chain timeout. */\nexport const SCANNER_TIMEOUT_SECONDS = (ONCHAIN_TIMEOUT_SECONDS + CLOCK_SKEW_SECONDS) as 86_460; // 86_460\n\n/**\n * Sentinel value for the not-yet-deployed mainnet program ID. base58-decodes to\n * the Solana System Program address, which is unusable as an escro program ID —\n * any attempt to deploy to this address fails at the Solana loader level. Code\n * that needs to refuse operation on a not-yet-bootstrapped mainnet compares\n * `PROGRAM_ID_MAINNET` against this constant.\n */\nexport const MAINNET_PROGRAM_ID_PLACEHOLDER = \"11111111111111111111111111111111\" as const;\n\nexport function getProgramId(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PROGRAM_ID_MAINNET : PROGRAM_ID_DEVNET;\n}\n\nexport function getPlatformConfigPda(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PLATFORM_CONFIG_PDA_MAINNET : PLATFORM_CONFIG_PDA_DEVNET;\n}\n\nexport function getUsdcMint(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? MAINNET_USDC_MINT : DEVNET_USDC_MINT;\n}\n\nexport function isPlaceholderProgramId(id: string): boolean {\n return id === MAINNET_PROGRAM_ID_PLACEHOLDER;\n}\n\n/**\n * Throws when running in mainnet context with the placeholder program ID still\n * in place. Callers should invoke this at module init (or first use) so the\n * service refuses to do any on-chain work against an unbootstrapped mainnet.\n */\nexport function assertProgramIdNotPlaceholder(id: string, cluster: SolanaCluster): void {\n if (cluster === \"mainnet\" && isPlaceholderProgramId(id)) {\n throw new Error(\n `PROGRAM_ID_MAINNET is still the System Program placeholder (${MAINNET_PROGRAM_ID_PLACEHOLDER}). ` +\n \"Run scripts/deploy-mainnet.sh to bootstrap mainnet, then update the placeholder in \" +\n \"packages/shared/src/config.ts, packages/program/programs/escro/src/lib.rs, \" +\n \"packages/program/Anchor.toml, and infra/bin/escro.ts.\",\n );\n }\n}\n\nexport function parseClusterEnv(raw: string | undefined): SolanaCluster {\n if (raw === \"mainnet\") return \"mainnet\";\n if (raw === \"devnet\" || raw === undefined || raw === \"\") return \"devnet\";\n throw new Error(`CLUSTER env var must be \"devnet\" or \"mainnet\", got \"${raw}\"`);\n}\n","export function canonicalize(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) {\n return \"[\" + value.map((v) => (v === undefined ? \"null\" : canonicalize(v))).join(\",\") + \"]\";\n }\n if (typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n return \"{\" + keys.map((k) => JSON.stringify(k) + \":\" + canonicalize(obj[k])).join(\",\") + \"}\";\n }\n return JSON.stringify(value);\n}\n","/**\n * Secret detection for task-spec content, which is shared and not secret.\n *\n * A task spec and its metadata go to the worker (and, in a dispute, the arbitrator),\n * and its hash and URI are recorded on-chain, so nothing in them is secret. Escro\n * stores no spec body. The original finding (L3) is that secrets CAN be placed in the\n * free-form metadata map. We actively REJECT obvious secret material rather than\n * merely document the boundary: \"documented as not secret\" is weaker than \"refuses\n * a secret\".\n *\n * Design goal: near-zero false positives. We flag only high-confidence patterns\n * (keypair byte arrays, base58 64-byte secret keys, PEM private-key blocks, AWS\n * access keys, and a small set of unambiguous secret field names). We do NOT do\n * entropy heuristics or fuzzy mnemonic matching, which would risk rejecting\n * legitimate task descriptions.\n */\n\n/**\n * Thrown when caller-supplied content appears to contain a secret. Carries a\n * 400 statusCode + code so the API's global error handler returns a clean\n * client error rather than a 500.\n */\nexport class SecretInMetadataError extends Error {\n readonly code = \"METADATA_CONTAINS_SECRET\";\n readonly statusCode = 400;\n readonly path: string;\n readonly reason: string;\n constructor(path: string, reason: string) {\n super(\n `Refused: a suspected secret was found at ${path} (${reason}). ` +\n \"Task metadata is shared with the worker and its hash is recorded on-chain; it is not secret storage: remove the secret and retry.\",\n );\n this.name = \"SecretInMetadataError\";\n this.path = path;\n this.reason = reason;\n }\n}\n\nconst PEM_PRIVATE_KEY = /-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/;\nconst AWS_ACCESS_KEY_ID = /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/;\n// A 64-byte ed25519 secret key base58-encodes to ~87-88 chars. 32-byte pubkeys\n// (~43-44 chars) are legitimate in metadata, so only the long form is a signal.\n// Anchored to the whole (trimmed) value for precision — base64 of similar length\n// carries chars outside the base58 alphabet and won't match.\nconst BASE58_64_BYTE = /^[1-9A-HJ-NP-Za-km-z]{86,90}$/;\n\n/** Unambiguous secret-bearing field names (normalized: lowercased, separators stripped). */\nconst SECRET_FIELD_NAMES = new Set([\"privatekey\", \"secretkey\", \"mnemonic\", \"seedphrase\"]);\n\nfunction normalizeFieldName(key: string): string {\n return key.toLowerCase().replace(/[\\s_-]/g, \"\");\n}\n\nfunction looksLikeKeypairByteArray(arr: unknown[]): boolean {\n // Solana keypair secret = 64 bytes; raw secret seed = 32 bytes.\n if (arr.length !== 64 && arr.length !== 32) return false;\n return arr.every((n) => typeof n === \"number\" && Number.isInteger(n) && n >= 0 && n <= 255);\n}\n\nfunction scanString(value: string): string | null {\n if (PEM_PRIVATE_KEY.test(value)) return \"PEM private key block\";\n if (AWS_ACCESS_KEY_ID.test(value)) return \"AWS access key id\";\n if (BASE58_64_BYTE.test(value.trim())) return \"base58-encoded 64-byte secret key\";\n return null;\n}\n\n/**\n * Recursively scan an arbitrary JSON-like value for obvious secret material.\n * Returns the first match as `{ path, reason }`, or `null` if none is found.\n */\nexport function scanForSecrets(\n value: unknown,\n path = \"$\",\n): { path: string; reason: string } | null {\n if (typeof value === \"string\") {\n const reason = scanString(value);\n return reason === null ? null : { path, reason };\n }\n if (Array.isArray(value)) {\n if (looksLikeKeypairByteArray(value)) {\n return { path, reason: \"array of bytes resembling an ed25519 keypair\" };\n }\n for (let i = 0; i < value.length; i++) {\n const hit = scanForSecrets(value[i], `${path}[${String(i)}]`);\n if (hit !== null) return hit;\n }\n return null;\n }\n if (value !== null && typeof value === \"object\") {\n for (const [k, v] of Object.entries(value)) {\n if (typeof v === \"string\" && v.length > 0 && SECRET_FIELD_NAMES.has(normalizeFieldName(k))) {\n return { path: `${path}.${k}`, reason: `field name \"${k}\" indicates a secret value` };\n }\n const hit = scanForSecrets(v, `${path}.${k}`);\n if (hit !== null) return hit;\n }\n return null;\n }\n return null;\n}\n\n/** Throws {@link SecretInMetadataError} if `value` contains obvious secret material. */\nexport function assertNoSecrets(value: unknown, context = \"$\"): void {\n const hit = scanForSecrets(value, context);\n if (hit !== null) {\n throw new SecretInMetadataError(hit.path, hit.reason);\n }\n}\n","import { MAX_DISPUTE_REASON_BYTES } from \"../config.js\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function invariant(condition: boolean, message: string): asserts condition {\n if (!condition) {\n throw new Error(`Invariant violation: ${message}`);\n }\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Why `reason` cannot go on chain as a dispute reason, or null when it can. The program\n * counts UTF-8 bytes, so a short reason of multi-byte characters can still be too long.\n */\nexport function disputeReasonError(reason: string): string | null {\n if (reason.length === 0) return \"reason must not be empty\";\n const bytes = new TextEncoder().encode(reason).length;\n if (bytes > MAX_DISPUTE_REASON_BYTES) {\n return `reason is ${String(bytes)} bytes in UTF-8; the program accepts at most ${String(MAX_DISPUTE_REASON_BYTES)}`;\n }\n return null;\n}\n\nexport * from \"./canonicalize.js\";\nexport * from \"./secret-scan.js\";\n","import { createHash } from \"node:crypto\";\nimport nacl from \"tweetnacl\";\nimport bs58 from \"bs58\";\nimport type { Keypair } from \"@solana/web3.js\";\n\n/** Lowercase hex SHA-256 of a UTF-8 string. Use \"\" for no-body requests. */\nexport function hashBody(rawBody: string): string {\n return createHash(\"sha256\").update(rawBody, \"utf8\").digest(\"hex\");\n}\n\n/** Canonical signed message format shared by SDK (signing) and API (verification). */\nexport function buildSignedMessage(\n timestamp: number | string,\n method: string,\n fullPath: string,\n bodyHash: string,\n): string {\n return `escro:${String(timestamp)}:${method}:${fullPath}:${bodyHash}`;\n}\n\n/**\n * Build all auth headers from a raw Ed25519 secret key and its base58 wallet\n * address. This is the web3.js-free core of {@link signRequest}: callers that\n * cannot depend on `@solana/web3.js` (the Bot Kit CLI keeps its runtime light)\n * sign with the raw keyfile bytes here, so the header names and the `escro:`\n * message format live in exactly ONE place and cannot drift from the API's\n * verifier. `rawBody` is the raw UTF-8 request body; pass \"\" when there is none.\n */\nexport function signRequestRaw(\n secretKey: Uint8Array,\n walletAddress: string,\n method: string,\n fullPath: string,\n rawBody: string,\n): Record<string, string> {\n const timestamp = Date.now();\n const bodyHash = hashBody(rawBody);\n const message = buildSignedMessage(timestamp, method, fullPath, bodyHash);\n const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), secretKey);\n return {\n \"x-wallet-address\": walletAddress,\n \"x-signature\": bs58.encode(sigBytes),\n \"x-timestamp\": String(timestamp),\n \"x-content-sha256\": bodyHash,\n };\n}\n\n/**\n * Build all auth headers needed for an authenticated request.\n * `rawBody` is the raw UTF-8 request body string; pass \"\" when there is no body.\n */\nexport function signRequest(\n wallet: Keypair,\n method: string,\n fullPath: string,\n rawBody: string,\n): Record<string, string> {\n return signRequestRaw(wallet.secretKey, wallet.publicKey.toBase58(), method, fullPath, rawBody);\n}\n","import nacl from \"tweetnacl\";\nimport bs58 from \"bs58\";\nimport { canonicalize } from \"./utils/canonicalize.js\";\nimport type { BotDescriptor, UnsignedBotDescriptor } from \"./types/bots.js\";\n\n/**\n * Canonical, deterministic byte-string a bot signs to prove authorship of its\n * capability descriptor (ARCHITECTURE §8 \"anyone can verify the signature\n * independently\"). Excludes `signature` itself. Shared by the SDK/kit (signing)\n * and the API (verification) so both sides agree byte-for-byte.\n */\nexport function canonicalBotDescriptorMessage(descriptor: UnsignedBotDescriptor): string {\n // `canonicalize` sorts keys and drops undefined values, so an absent\n // `endpoint` is naturally excluded and signing is order-independent.\n return canonicalize({\n wallet: descriptor.wallet,\n role: descriptor.role,\n capabilities: descriptor.capabilities,\n serviceRef: descriptor.serviceRef,\n pricingHint: descriptor.pricingHint,\n endpoint: descriptor.endpoint,\n signedAt: descriptor.signedAt,\n });\n}\n\n/**\n * Sign an unsigned descriptor with the bot's Ed25519 secret key, returning the\n * base58 detached signature to attach as `BotDescriptor.signature`.\n */\nexport function signBotDescriptor(\n secretKey: Uint8Array,\n descriptor: UnsignedBotDescriptor,\n): string {\n const message = new TextEncoder().encode(canonicalBotDescriptorMessage(descriptor));\n return bs58.encode(nacl.sign.detached(message, secretKey));\n}\n\n/**\n * Verify a descriptor's `signature` against its own `wallet`. Returns false on a\n * wrong signer, a tampered field, or malformed encoding - never throws. This is\n * the document-level check any third party can run; the API also enforces it.\n */\nexport function verifyBotDescriptorSignature(descriptor: BotDescriptor): boolean {\n try {\n const { signature, ...unsigned } = descriptor;\n const message = new TextEncoder().encode(canonicalBotDescriptorMessage(unsigned));\n const signatureBytes = bs58.decode(signature);\n if (signatureBytes.length !== 64) return false;\n const pubkeyBytes = bs58.decode(descriptor.wallet);\n if (pubkeyBytes.length !== 32) return false;\n return nacl.sign.detached.verify(message, signatureBytes, pubkeyBytes);\n } catch {\n return false;\n }\n}\n","import type { VersionedTransactionResponse } from \"@solana/web3.js\";\n\nimport type { SettlementCause } from \"./types/escrow.js\";\n\n/**\n * The single escrow-instruction table: every instruction that acts on one\n * escrow account, with its Anchor discriminator, the account indices of the\n * escrow PDA and the signing actor, and the settlement cause for the settling\n * instructions (null for the lifecycle ones). Locked to the committed IDL by\n * instructions.test.ts. The remaining per-package copies migrate under D18.\n */\nexport const ESCROW_INSTRUCTION_NAMES = [\n \"create_escrow\",\n \"claim_task\",\n \"submit_deliverable\",\n \"raise_dispute\",\n \"cancel_escrow\",\n \"release_payment\",\n \"timeout_release\",\n \"refund_buyer\",\n \"arbitration_release\",\n \"arbitration_refund\",\n] as const;\n\nexport type EscrowInstructionName = (typeof ESCROW_INSTRUCTION_NAMES)[number];\n\nexport interface EscrowInstructionSpec {\n readonly discriminator: Uint8Array;\n readonly escrowAccountIndex: number;\n readonly signerAccountIndex: number;\n readonly cause: SettlementCause | null;\n}\n\nfunction spec(\n discriminator: number[],\n escrowAccountIndex: number,\n cause: SettlementCause | null,\n): EscrowInstructionSpec {\n return {\n discriminator: Uint8Array.from(discriminator),\n escrowAccountIndex,\n signerAccountIndex: 0,\n cause,\n };\n}\n\nexport const ESCROW_INSTRUCTIONS: Readonly<Record<EscrowInstructionName, EscrowInstructionSpec>> = {\n create_escrow: spec([253, 215, 165, 116, 36, 108, 68, 80], 4, null),\n claim_task: spec([49, 222, 219, 238, 155, 68, 221, 136], 1, null),\n submit_deliverable: spec([38, 137, 64, 44, 237, 11, 125, 101], 1, null),\n raise_dispute: spec([41, 243, 1, 51, 150, 95, 246, 73], 1, null),\n cancel_escrow: spec([156, 203, 54, 179, 38, 72, 33, 21], 3, \"CANCELLED\"),\n release_payment: spec([24, 34, 191, 86, 145, 160, 183, 233], 3, \"EXPLICIT_RELEASE\"),\n timeout_release: spec([98, 176, 26, 12, 83, 105, 154, 68], 3, \"TIMEOUT_RELEASE\"),\n refund_buyer: spec([199, 139, 203, 146, 192, 150, 53, 218], 3, \"DEADLINE_REFUND\"),\n arbitration_release: spec([118, 157, 141, 26, 104, 117, 94, 229], 4, \"ARBITRATION_RELEASE\"),\n arbitration_refund: spec([255, 194, 84, 248, 185, 249, 120, 122], 4, \"ARBITRATION_REFUND\"),\n};\n\n/** A landed transaction reduced to what instruction matching needs. */\nexport interface TransactionView {\n /** Static keys, then loaded writable, then loaded readonly addresses (base58). */\n readonly accountKeys: readonly string[];\n readonly instructions: readonly {\n readonly programIdIndex: number;\n readonly accountKeyIndexes: readonly number[];\n readonly data: Uint8Array;\n }[];\n}\n\nexport interface EscrowInstructionMatch {\n name: EscrowInstructionName;\n /** The account at the instruction's signer index (base58). */\n signer: string;\n data: Uint8Array;\n}\n\n/** The table's entry whose discriminator opens `data`, of any program or escrow; null for none. */\nexport function escrowInstructionName(data: Uint8Array): EscrowInstructionName | null {\n for (const name of ESCROW_INSTRUCTION_NAMES) {\n const disc = ESCROW_INSTRUCTIONS[name].discriminator;\n if (disc.every((b, i) => data[i] === b)) return name;\n }\n return null;\n}\n\n/**\n * Every TOP-LEVEL instruction of `programId` in the transaction whose\n * discriminator is in the table and whose escrow account is `escrowPda`.\n * Instructions reached by CPI are not matched (ARCHITECTURE section 9).\n */\nexport function findEscrowInstructions(\n view: TransactionView,\n opts: { programId: string; escrowPda: string },\n): EscrowInstructionMatch[] {\n const matches: EscrowInstructionMatch[] = [];\n for (const ix of view.instructions) {\n if (view.accountKeys[ix.programIdIndex] !== opts.programId) continue;\n const name = escrowInstructionName(ix.data);\n if (name === null) continue;\n const entry = ESCROW_INSTRUCTIONS[name];\n const escrowKeyIndex = ix.accountKeyIndexes[entry.escrowAccountIndex];\n const signerKeyIndex = ix.accountKeyIndexes[entry.signerAccountIndex];\n if (escrowKeyIndex === undefined || signerKeyIndex === undefined) continue;\n if (view.accountKeys[escrowKeyIndex] !== opts.escrowPda) continue;\n const signer = view.accountKeys[signerKeyIndex];\n if (signer === undefined) continue;\n matches.push({ name, signer, data: ix.data });\n }\n return matches;\n}\n\ninterface Base58Key {\n toBase58(): string;\n}\n\n/** The fields of a `getTransaction` response that {@link toTransactionView} reads. */\nexport interface TransactionResponseLike {\n transaction: {\n message: {\n staticAccountKeys: readonly Base58Key[];\n compiledInstructions: readonly {\n programIdIndex: number;\n accountKeyIndexes: readonly number[];\n data: Uint8Array;\n }[];\n };\n };\n meta: {\n loadedAddresses?: { writable: readonly Base58Key[]; readonly: readonly Base58Key[] };\n } | null;\n}\n\n// A web3 VersionedTransactionResponse is accepted as-is.\ntype _AcceptsWeb3Response = VersionedTransactionResponse extends TransactionResponseLike\n ? true\n : never;\nconst _acceptsWeb3Response: _AcceptsWeb3Response = true;\nvoid _acceptsWeb3Response;\n\n/** Adapt a landed (legacy or v0, lookup-table-aware) transaction to a {@link TransactionView}. */\nexport function toTransactionView(response: TransactionResponseLike): TransactionView {\n const { message } = response.transaction;\n const loaded = response.meta?.loadedAddresses;\n const accountKeys = [\n ...message.staticAccountKeys,\n ...(loaded?.writable ?? []),\n ...(loaded?.readonly ?? []),\n ].map((k) => k.toBase58());\n return { accountKeys, instructions: message.compiledInstructions };\n}\n","/**\n * Reserved dual-path payment surface (ARCHITECTURE §7a, BOT_KIT_PRD §10).\n *\n * PLUMBING ONLY. The escrow rail is the sole implemented backend; the `x402`\n * (synchronous) rail is reserved and lands in Phase 9 as an additive backend.\n * Every name here is a FREEZE CONTRACT that Phase 9 inherits \"by name\":\n * enabling x402 must not be a breaking change for any kit-generated bot. The\n * shapes below are pinned by a type-level test (src/__tests__/payments.test.ts);\n * Phase 9 may add only OPTIONAL fields.\n */\n\n/** Single source for the rail identifiers. The {@link Rail} type is derived from\n * this list (drift-safe, mirroring the BOT_ROLES pattern in @escro/shared). */\nexport const RAILS = [\"escrow\", \"x402\"] as const;\n\n/** The payment rails Escro can route across. Only `escrow` is implemented today;\n * `x402` is RESERVED and not enabled until Phase 9. */\nexport type Rail = (typeof RAILS)[number];\n\n/** The rails enabled in this build. Frozen to escrow-only until Phase 9 enables\n * x402. Typed `readonly Rail[]` (not the literal tuple) so runtime membership\n * checks stay honest: `ENABLED_RAILS.includes(rail)` narrows nothing away. */\nexport const ENABLED_RAILS: readonly Rail[] = [\"escrow\"];\n\n/** Docs for the payment rails, linked from the reserved-rail error and the kit\n * config's rejection message so both point to the same place. */\nexport const RAILS_DOCS_URL = \"https://docs.escro.ai/rails\";\n\n/** The minimal payment shape a {@link PaymentRouter} inspects to choose a rail.\n * FROZEN; Phase 9 may add only optional fields. */\nexport interface TxShape {\n /** Recipient wallet address (base58). */\n readonly to: string;\n /** Amount to move, in USDC micro-units (integer, 6 decimals). */\n readonly amountMicroUsdc: number;\n /** `async` (verification-needed) work routes to escrow; `sync` work is x402's territory. */\n readonly mode: \"async\" | \"sync\";\n}\n\n/** Chooses the rail for a payment. Defined now with a single backend; `x402` is\n * returned only once that rail is enabled (Phase 9). FROZEN signature. */\nexport interface PaymentRouter {\n selectRail(tx: TxShape): Rail;\n}\n\n/** The one backend shipped today. Async work routes to escrow; sync work would\n * prefer x402, but x402 is reserved and not enabled (ARCHITECTURE §7a), so the\n * router falls back to escrow rather than ever returning a disabled rail. */\nexport class EscrowPaymentRouter implements PaymentRouter {\n selectRail(tx: TxShape): Rail {\n const preferred: Rail = tx.mode === \"sync\" ? \"x402\" : \"escrow\";\n return ENABLED_RAILS.includes(preferred) ? preferred : \"escrow\";\n }\n}\n\n/** Parameters for a synchronous payment via {@link Escro.pay}. FROZEN: both\n * fields are required now so Phase 9 adds only optional fields; a required field\n * added later would break every kit-generated bot. */\nexport interface PayParams {\n /** Recipient wallet address (base58). */\n readonly to: string;\n /** Amount to pay, in USDC micro-units (integer, 6 decimals). */\n readonly amountMicroUsdc: number;\n}\n\n/** Result of a completed payment. FROZEN and rail-generic: `reference` is the\n * rail-native settlement id (a Solana signature for escrow, an x402 receipt for\n * x402), so the shape describes either rail without change. */\nexport interface PaymentResult {\n /** Which rail settled the payment. */\n readonly rail: Rail;\n /** Rail-native settlement reference. */\n readonly reference: string;\n}\n","import { RAILS_DOCS_URL } from \"./payments.js\";\n\n/**\n * Base class for all errors thrown by the @escro/sdk. `retryAfterMs` is the\n * server's Retry-After delay, when it sent one in seconds.\n */\nexport class EscroError extends Error {\n constructor(\n message: string,\n public readonly code = \"ESCRO_ERROR\",\n public readonly retryAfterMs?: number,\n ) {\n super(message);\n this.name = \"EscroError\";\n }\n}\n\n/** The requested escrow was not found (HTTP 404). */\nexport class EscrowNotFoundError extends EscroError {\n constructor(address: string) {\n super(`Escrow not found: ${address}`, \"ESCROW_NOT_FOUND\");\n this.name = \"EscrowNotFoundError\";\n }\n}\n\n/**\n * The reputation endpoint is not available on this deployment (HTTP 404). A 404\n * from `GET /rep` means no `ReputationSource` is mounted (the surface is\n * unmounted), NOT that a wallet is unknown - unknown wallets return zeroed raw\n * components, never a 404. Kept distinct from {@link EscrowNotFoundError}, whose\n * 404 is about a missing escrow.\n */\nexport class ReputationUnavailableError extends EscroError {\n constructor() {\n super(\n \"Reputation endpoint is unavailable (HTTP 404): this deployment has no reputation source mounted.\",\n \"REPUTATION_UNAVAILABLE\",\n );\n this.name = \"ReputationUnavailableError\";\n }\n}\n\n/** The operation is not valid for the escrow's current state (HTTP 409). */\nexport class EscrowStateError extends EscroError {\n constructor(message: string) {\n super(message, \"ESCROW_INVALID_STATE\");\n this.name = \"EscrowStateError\";\n }\n}\n\n/** Polling timed out after 24 hours without reaching the expected state. */\nexport class EscrowTimeoutError extends EscroError {\n constructor(address: string) {\n super(`Polling timed out after 24h for escrow: ${address}`, \"ESCROW_TIMEOUT\");\n this.name = \"EscrowTimeoutError\";\n }\n}\n\n/**\n * A transaction landed (or was sent) but the API did not record it. `code` is the\n * server's code (e.g. TX_MISMATCH, TX_FAILED, or TX_NOT_FOUND after the retry\n * window), `NETWORK_ERROR` when the last attempt never reached the API, or\n * `HTTP_<status>` when the answer carried no code. Call {@link Escro.confirm} again\n * with `address` and `signature` to retry, no sooner than `retryAfterMs` when the\n * API sent one.\n */\nexport class EscroConfirmError extends EscroError {\n constructor(\n public readonly address: string,\n public readonly signature: string,\n code: string,\n message: string,\n retryAfterMs?: number,\n ) {\n super(\n `Confirm failed for escrow ${address} (signature ${signature}): ${message}`,\n code,\n retryAfterMs,\n );\n this.name = \"EscroConfirmError\";\n }\n}\n\n/** The caller is not authorized to perform this action (HTTP 401/403). */\nexport class UnauthorizedError extends EscroError {\n constructor(message = \"Unauthorized\") {\n super(message, \"UNAUTHORIZED\");\n this.name = \"UnauthorizedError\";\n }\n}\n\n/**\n * A payment rail was requested that is not enabled in this build. The `x402`\n * (synchronous) rail is reserved (ARCHITECTURE §7a) and lands in Phase 9;\n * {@link Escro.pay} throws this until then. `rail` names the unavailable rail.\n */\nexport class EscroRailNotEnabledError extends EscroError {\n constructor(public readonly rail: string) {\n super(\n `Payment rail \"${rail}\" is not enabled. Only the escrow rail is available today; ` +\n `the x402 rail is reserved and lands in Phase 9. See ${RAILS_DOCS_URL}`,\n \"ESCRO_RAIL_NOT_ENABLED\",\n );\n this.name = \"EscroRailNotEnabledError\";\n }\n}\n","import { signRequest } from \"@escro/shared\";\nimport type { Keypair } from \"@solana/web3.js\";\nimport type { BotDescriptor, EscrowAccount, EscrowErrorCode, EscrowState } from \"@escro/shared\";\nimport type { ServedWalletReputation } from \"@escro/reputation\";\nimport type {\n CreateEscrowParams,\n ListBotsParams,\n PaginatedResult,\n RaiseDisputeParams,\n SerializedEscrow,\n SubmitDeliverableParams,\n} from \"./types.js\";\nimport {\n EscroError,\n EscrowNotFoundError,\n EscrowStateError,\n ReputationUnavailableError,\n UnauthorizedError,\n} from \"./errors.js\";\n\n// ── Auth header builder ────────────────────────────────────────────────────────\n\nfunction authHeaders(\n wallet: Keypair,\n method: string,\n path: string,\n rawBody = \"\",\n): Record<string, string> {\n return signRequest(wallet, method, path, rawBody);\n}\n\n// ── Deserialization ────────────────────────────────────────────────────────────\n\nfunction deserialize(raw: SerializedEscrow): EscrowAccount {\n return { ...raw, amount: BigInt(raw.amount) };\n}\n\n// ── Error handling ─────────────────────────────────────────────────────────────\n\nasync function handleError(res: Response, address?: string): Promise<never> {\n const body = (await res.json().catch(() => ({}))) as {\n error?: string;\n code?: string;\n };\n const msg = body.error ?? `HTTP ${String(res.status)}`;\n if (res.status === 404) throw new EscrowNotFoundError(address ?? msg);\n if (res.status === 409) throw new EscrowStateError(msg);\n if (res.status === 401 || res.status === 403) throw new UnauthorizedError(msg);\n throw new EscroError(msg, body.code ?? \"UNKNOWN\", retryAfterMs(res.headers.get(\"retry-after\")));\n}\n\n/** Retry-After in whole seconds, as milliseconds; an HTTP-date is ignored. */\nfunction retryAfterMs(header: string | null): number | undefined {\n return header !== null && /^\\d+$/.test(header.trim()) ? Number(header.trim()) * 1000 : undefined;\n}\n\n// ── API client ─────────────────────────────────────────────────────────────────\n\nexport class ApiClient {\n constructor(\n private readonly baseUrl: string,\n private readonly wallet: Keypair,\n ) {\n const url = new URL(baseUrl);\n const isLocalhost = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\";\n if (url.protocol !== \"https:\" && !isLocalhost) {\n throw new Error(\"apiUrl must use HTTPS in production\");\n }\n }\n\n private url(path: string): string {\n return `${this.baseUrl}${path}`;\n }\n\n /** GET /v1/escrows/:address */\n async getEscrow(address: string): Promise<EscrowAccount> {\n const path = `/v1/escrows/${address}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res, address);\n return deserialize((await res.json()) as SerializedEscrow);\n }\n\n /** GET /v1/escrows?assignedTo=...&maker=...&state=... */\n async listEscrows(params: {\n assignedTo?: string;\n maker?: string;\n state?: EscrowState;\n limit?: number;\n offset?: number;\n }): Promise<PaginatedResult<EscrowAccount>> {\n const qs = new URLSearchParams();\n if (params.assignedTo) qs.set(\"assignedTo\", params.assignedTo);\n if (params.maker) qs.set(\"maker\", params.maker);\n if (params.state) qs.set(\"state\", params.state);\n if (params.limit != null) qs.set(\"limit\", String(params.limit));\n if (params.offset != null) qs.set(\"offset\", String(params.offset));\n\n const path = `/v1/escrows?${qs.toString()}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n const body = (await res.json()) as {\n items: SerializedEscrow[];\n total: number;\n limit: number;\n offset: number;\n };\n return {\n items: body.items.map(deserialize),\n total: body.total,\n limit: body.limit,\n offset: body.offset,\n };\n }\n\n /**\n * GET /v1/bots?capability=...&role=...&limit=...&offset= : EscroBots registry\n * read. Unauthenticated public read (no auth headers). Returns descriptors in\n * registry order (newest first); descriptors are self-reported claims.\n */\n async listBots(params: ListBotsParams): Promise<PaginatedResult<BotDescriptor>> {\n const qs = new URLSearchParams();\n if (params.capability != null) qs.set(\"capability\", params.capability);\n if (params.role != null) qs.set(\"role\", params.role);\n if (params.limit != null) qs.set(\"limit\", String(params.limit));\n if (params.offset != null) qs.set(\"offset\", String(params.offset));\n\n const path = `/v1/bots?${qs.toString()}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n const body = (await res.json()) as {\n items: BotDescriptor[];\n total: number;\n limit: number;\n offset: number;\n };\n return { items: body.items, total: body.total, limit: body.limit, offset: body.offset };\n }\n\n /**\n * GET /rep : EscroRep bulk export (ARCHITECTURE §9). Unauthenticated public\n * read (no auth headers). Returns every indexed wallet's RAW components exactly\n * once (no composite score). Ranking layers join against this ONE bulk fetch:\n * the per-wallet endpoint shares a 10/min public-metrics budget, so a\n * per-candidate fan-out would rate-limit itself. A 404 means the deployment\n * mounted no reputation source (unknown wallets return zeroed rep, never 404),\n * so it surfaces as {@link ReputationUnavailableError}, not EscrowNotFoundError.\n */\n async listReputations(): Promise<ServedWalletReputation[]> {\n const res = await fetch(this.url(\"/rep\"));\n if (!res.ok) {\n if (res.status === 404) throw new ReputationUnavailableError();\n await handleError(res);\n }\n const body = (await res.json()) as {\n wallets: ServedWalletReputation[];\n count: number;\n generatedAt: number;\n };\n return body.wallets;\n }\n\n /**\n * GET /rep/:wallet : one wallet's EscroRep RAW components (ARCHITECTURE §9).\n * Unauthenticated public read (no auth headers). Unknown wallets return zeroed\n * components, never 404; a 404 means the deployment mounted no reputation\n * source and surfaces as {@link ReputationUnavailableError}. Shares the public\n * per-wallet rate budget with every other caller, so fan-outs should use\n * {@link listReputations} instead.\n */\n async getReputation(wallet: string): Promise<ServedWalletReputation> {\n const res = await fetch(this.url(`/rep/${encodeURIComponent(wallet)}`));\n if (!res.ok) {\n if (res.status === 404) throw new ReputationUnavailableError();\n await handleError(res);\n }\n return (await res.json()) as ServedWalletReputation;\n }\n\n /**\n * POST /v1/escrows — create escrow, returns unsigned tx + ids.\n * Requires auth.\n */\n async createEscrow(params: CreateEscrowParams): Promise<{\n escrowId: string;\n escrowPda: string;\n unsignedTx: string;\n }> {\n const path = \"/v1/escrows\";\n const bodyObj: Record<string, unknown> = {\n taskSpec: params.taskSpec,\n amountUsdc: params.amountUsdc,\n deadlineUnix: params.deadlineUnix,\n assignedWorker: params.assignedWorker,\n };\n\n const rawBody = JSON.stringify(bodyObj);\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) await handleError(res);\n return res.json() as Promise<{ escrowId: string; escrowPda: string; unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/claim — returns unsigned tx.\n * Requires auth (worker).\n */\n async claimTask(address: string): Promise<{ unsignedTx: string }> {\n const path = `/v1/escrows/${address}/claim`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/submit — returns unsigned tx.\n * Requires auth (worker).\n */\n async submitDeliverable(\n address: string,\n params: SubmitDeliverableParams,\n ): Promise<{ unsignedTx: string }> {\n const path = `/v1/escrows/${address}/submit`;\n const rawBody = JSON.stringify({\n contentHash: params.contentHash,\n proofUri: params.proofUri,\n });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/release: records the landed release once the API's RPC shows\n * the escrow closed. Requires auth (buyer). No on-chain tx returned. A 409\n * `ESCROW_NOT_SETTLED`, a 5xx or a 429 throws an {@link EscroError} with the server's code,\n * or `HTTP_<status>` when the answer carries none; {@link Escro.releasePaymentWithOutcome}\n * decides which to retry. Other refusals throw as every route does.\n */\n async releasePaymentDb(address: string): Promise<void> {\n const path = `/v1/escrows/${address}/release`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (res.ok) return;\n if (res.status !== 409 && res.status !== 429 && res.status < 500) {\n await handleError(res, address);\n }\n const body = (await res.json().catch(() => ({}))) as { error?: string; code?: string };\n if (res.status === 409 && body.code !== (\"ESCROW_NOT_SETTLED\" satisfies EscrowErrorCode)) {\n throw new EscrowStateError(body.error ?? `HTTP ${String(res.status)}`);\n }\n throw new EscroError(\n body.error ?? `HTTP ${String(res.status)}`,\n body.code ?? `HTTP_${String(res.status)}`,\n retryAfterMs(res.headers.get(\"retry-after\")),\n );\n }\n\n /**\n * POST /v1/escrows/:address/cancel — returns unsigned tx.\n * Requires auth (buyer). Only valid when state is FUNDED.\n */\n async cancelEscrow(address: string): Promise<{ unsignedTx: string }> {\n const path = `/v1/escrows/${address}/cancel`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/dispute — returns unsigned tx.\n * Requires auth (buyer or worker).\n */\n async raiseDispute(\n address: string,\n params: Pick<RaiseDisputeParams, \"reason\">,\n ): Promise<{ unsignedTx: string }> {\n const path = `/v1/escrows/${address}/dispute`;\n const rawBody = JSON.stringify({ reason: params.reason });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/confirm: the API records the create, claim, submit,\n * cancel or dispute the landed `signature` carries, after verifying it on chain.\n * A non-2xx answer throws an {@link EscroError} with the server's code, or\n * `HTTP_<status>` when the answer carries none; a network failure rejects with\n * fetch's own error. {@link Escro.confirm} decides which to retry.\n */\n async confirm(address: string, signature: string, evidence?: string): Promise<EscrowAccount> {\n const path = `/v1/escrows/${address}/confirm`;\n const rawBody = JSON.stringify({ signature, evidence });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string; code?: string };\n throw new EscroError(\n body.error ?? `HTTP ${String(res.status)}`,\n body.code ?? `HTTP_${String(res.status)}`,\n retryAfterMs(res.headers.get(\"retry-after\")),\n );\n }\n const body = (await res.json()) as { escrow: SerializedEscrow };\n return deserialize(body.escrow);\n }\n\n /**\n * GET /v1/stats — public protocol-wide stats.\n * No auth required. Upstream typing in {@link Escro.getStats} narrows the\n * return shape.\n */\n async getStats(): Promise<unknown> {\n const path = \"/v1/stats\";\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n return res.json();\n }\n}\n","import { EscrowTimeoutError } from \"./errors.js\";\n\nconst MS_5_MIN = 5 * 60 * 1_000;\nconst MS_30_MIN = 30 * 60 * 1_000;\nconst MS_24_H = 24 * 60 * 60 * 1_000;\n\n/**\n * Returns the next polling interval in ms based on total elapsed time.\n * 0 – 5 min → 15 s\n * 5 – 30 min → 30 s\n * 30 min – ∞ → 60 s\n */\nexport function backoffInterval(elapsedMs: number): number {\n if (elapsedMs < MS_5_MIN) return 15_000;\n if (elapsedMs < MS_30_MIN) return 30_000;\n return 60_000;\n}\n\n/** Resolves after `ms` milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Polls `fetcher` with exponential backoff until `predicate` returns true,\n * then returns the result. Throws {@link EscrowTimeoutError} after 24 hours.\n *\n * @param address - Escrow address used in the timeout error message.\n * @param fetcher - Async function that returns a value or null.\n * @param predicate - Returns true when polling should stop.\n * @param timeoutMs - Maximum total wait time in ms (default: 24 h).\n */\nexport async function pollUntil<T>(\n address: string,\n fetcher: () => Promise<T | null>,\n predicate: (result: T | null) => result is T,\n timeoutMs = MS_24_H,\n): Promise<T> {\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const result = await fetcher();\n if (predicate(result)) return result;\n\n const elapsed = Date.now() - (deadline - timeoutMs);\n if (Date.now() >= deadline) {\n throw new EscrowTimeoutError(address);\n }\n\n const interval = backoffInterval(elapsed);\n // Clamp to remaining time so we don't sleep past the deadline\n const remaining = deadline - Date.now();\n await sleep(Math.min(interval, remaining));\n\n if (Date.now() >= deadline) {\n throw new EscrowTimeoutError(address);\n }\n }\n}\n","import { createHash } from \"node:crypto\";\nimport {\n ComputeBudgetProgram,\n Connection,\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n getAssociatedTokenAddressSync,\n createAssociatedTokenAccountIdempotentInstruction,\n} from \"@solana/spl-token\";\nimport {\n CURRENT_ACCOUNT_VERSION,\n getProgramId,\n assertProgramIdNotPlaceholder,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport { decodePlatformConfig, derivePlatformConfigPda } from \"@escro/shared/solana\";\nimport { EscroError } from \"./errors.js\";\n\n// ── Discriminator helper ───────────────────────────────────────────────────────\n\nfunction disc(name: string): Buffer {\n return Buffer.from(createHash(\"sha256\").update(`global:${name}`).digest()).subarray(0, 8);\n}\n\nconst DISC_RELEASE_PAYMENT = disc(\"release_payment\");\n\n// ── Cluster-aware program ID resolution ────────────────────────────────────────\n\n/**\n * Resolve the escro program ID for a cluster, asserting it isn't the\n * pre-bootstrap placeholder when targeting mainnet.\n */\nfunction resolveProgramId(cluster: SolanaCluster): PublicKey {\n const id = getProgramId(cluster);\n assertProgramIdNotPlaceholder(id, cluster);\n return new PublicKey(id);\n}\n\nfunction allowedProgramIds(programId: PublicKey): Set<string> {\n return new Set([\n programId.toBase58(),\n TOKEN_PROGRAM_ID.toBase58(),\n ASSOCIATED_TOKEN_PROGRAM_ID.toBase58(),\n ComputeBudgetProgram.programId.toBase58(),\n ]);\n}\n\nconst MAX_INSTRUCTIONS = 6;\n\n/**\n * SPL Token instruction tags (first data byte) that move funds or change\n * authority. Escro flows NEVER have the wallet top-level-sign any of these — all\n * token movement happens via CPI inside the escro program (PDA-signed on\n * release/refund, buyer-authority through create_escrow). The token program is\n * allow-listed only because it is referenced as a CPI target and appears in\n * account lists. A top-level token instruction of one of these types in a\n * server-built transaction is a wallet-drain vector, so we refuse to sign it\n * (L2). Benign token instructions (e.g. InitializeAccount, SyncNative) are not\n * listed and remain permitted.\n */\nconst FORBIDDEN_TOKEN_IX_TAGS = new Set<number>([\n 3, // Transfer\n 4, // Approve\n 6, // SetAuthority\n 7, // MintTo\n 8, // Burn\n 9, // CloseAccount\n 12, // TransferChecked\n 13, // ApproveChecked\n 14, // MintToChecked\n 15, // BurnChecked\n]);\n\n/**\n * The mint and treasury from the on-chain PlatformConfig. A wrong length,\n * discriminator or version throws rather than returning corrupted keys.\n */\nexport async function fetchPlatformConfig(\n connection: Connection,\n cluster: SolanaCluster,\n): Promise<{ mint: PublicKey; treasury: PublicKey }> {\n const pda = derivePlatformConfigPda(resolveProgramId(cluster));\n const info = await connection.getAccountInfo(pda);\n if (!info) throw new Error(\"PlatformConfig account not found on-chain\");\n const config = decodePlatformConfig(info.data);\n if (config.version !== CURRENT_ACCOUNT_VERSION) {\n throw new Error(\n `PlatformConfig version mismatch: expected ${String(CURRENT_ACCOUNT_VERSION)}, got ${String(config.version)}`,\n );\n }\n return { mint: new PublicKey(config.usdcMint), treasury: new PublicKey(config.treasury) };\n}\n\n// ── Sign and submit ────────────────────────────────────────────────────────────\n\nexport function validateTransaction(tx: Transaction, cluster: SolanaCluster): void {\n const programId = resolveProgramId(cluster);\n const allowed = allowedProgramIds(programId);\n const tokenProgram = TOKEN_PROGRAM_ID.toBase58();\n for (const ix of tx.instructions) {\n const id = ix.programId.toBase58();\n if (!allowed.has(id)) {\n throw new Error(\n `Unexpected program in transaction: ${id}. Allowed: ${[...allowed].join(\", \")}`,\n );\n }\n if (id === tokenProgram) {\n const tag = ix.data.length > 0 ? ix.data[0] : undefined;\n if (tag !== undefined && FORBIDDEN_TOKEN_IX_TAGS.has(tag)) {\n throw new Error(\n `Refusing to sign a fund-moving SPL Token instruction (tag ${String(tag)}) in a ` +\n \"server-built transaction. Escro never requires the wallet to directly sign a token \" +\n \"transfer/approve/burn/close; all token movement is a CPI inside the escro program.\",\n );\n }\n }\n }\n if (tx.instructions.length > MAX_INSTRUCTIONS) {\n throw new Error(\n `Too many instructions (${String(tx.instructions.length)}). Max allowed: ${String(MAX_INSTRUCTIONS)}`,\n );\n }\n}\n\n/**\n * Decode a base64 unsigned transaction, sign it with `wallet`, submit to Solana,\n * and return the transaction signature once it is confirmed. A transaction that\n * landed but failed at execution throws an {@link EscroError} with code `TX_FAILED`\n * naming the signature and the error.\n */\nexport async function signAndSend(\n base64Tx: string,\n wallet: Keypair,\n connection: Connection,\n cluster: SolanaCluster,\n): Promise<string> {\n const buf = Buffer.from(base64Tx, \"base64\");\n const tx = Transaction.from(buf);\n validateTransaction(tx, cluster);\n tx.partialSign(wallet);\n const raw = tx.serialize();\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(\"confirmed\");\n const signature = await connection.sendRawTransaction(raw, {\n skipPreflight: false,\n });\n const { value } = await connection.confirmTransaction(\n { signature, blockhash, lastValidBlockHeight },\n \"confirmed\",\n );\n if (value.err !== null) {\n throw new EscroError(\n `Transaction ${signature} failed at execution: ${JSON.stringify(value.err)}`,\n \"TX_FAILED\",\n );\n }\n return signature;\n}\n\n// ── release_payment transaction builder ───────────────────────────────────────\n\n/**\n * Build an unsigned `release_payment` transaction.\n * The buyer signs to approve payment to the assigned worker.\n *\n * Account order (matches the on-chain `ReleasePayment` context):\n * 0. buyer — Signer, writable\n * 1. platform_config — read\n * 2. mint — read\n * 3. escrow_account — writable\n * 4. vault — ATA(mint, escrowPda), writable\n * 5. worker_ata — ATA(mint, worker), writable\n * 6. treasury_ata — ATA(mint, treasury), writable\n * 7. worker — read\n * 8. treasury — read\n * 9. token_program — read\n * 10. associated_token_program — read\n */\nexport async function buildReleasePaymentTx(params: {\n buyer: PublicKey;\n escrowPda: PublicKey;\n worker: PublicKey;\n mint: PublicKey;\n treasury: PublicKey;\n connection: Connection;\n cluster: SolanaCluster;\n}): Promise<string> {\n const { buyer, escrowPda, worker, mint, treasury, connection, cluster } = params;\n const programId = resolveProgramId(cluster);\n\n const platformConfig = derivePlatformConfigPda(programId);\n const vault = getAssociatedTokenAddressSync(\n mint,\n escrowPda,\n true,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n const workerAta = getAssociatedTokenAddressSync(\n mint,\n worker,\n false,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n // allowOwnerOffCurve = true: the treasury is a Squads multisig vault, which is\n // a PDA (off-curve). getAssociatedTokenAddressSync throws TokenOwnerOffCurveError\n // for a PDA owner unless this flag is set. Safe/no-op for an on-curve treasury.\n const treasuryAta = getAssociatedTokenAddressSync(\n mint,\n treasury,\n true,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n\n const ix = new TransactionInstruction({\n programId: programId,\n keys: [\n { pubkey: buyer, isSigner: true, isWritable: true },\n { pubkey: platformConfig, isSigner: false, isWritable: false },\n { pubkey: mint, isSigner: false, isWritable: false },\n { pubkey: escrowPda, isSigner: false, isWritable: true },\n { pubkey: vault, isSigner: false, isWritable: true },\n { pubkey: workerAta, isSigner: false, isWritable: true },\n { pubkey: treasuryAta, isSigner: false, isWritable: true },\n { pubkey: worker, isSigner: false, isWritable: false },\n { pubkey: treasury, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n ],\n data: DISC_RELEASE_PAYMENT,\n });\n\n const { blockhash } = await connection.getLatestBlockhash(\"confirmed\");\n const tx = new Transaction();\n tx.recentBlockhash = blockhash;\n tx.feePayer = buyer;\n\n tx.add(createAssociatedTokenAccountIdempotentInstruction(buyer, workerAta, worker, mint));\n tx.add(createAssociatedTokenAccountIdempotentInstruction(buyer, treasuryAta, treasury, mint));\n tx.add(ix);\n return tx.serialize({ requireAllSignatures: false }).toString(\"base64\");\n}\n","// Program-derived addresses, the one off-chain copy of the program's seeds. Each takes the\n// program id, so localnet and ad hoc ids derive the same way as the pinned clusters.\nimport { PublicKey } from \"@solana/web3.js\";\n\nconst utf8 = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** EscrowAccount: seeds `[b\"escrow\", buyer, task_id]` (create_escrow.rs); `taskId` is at most 32 bytes. */\nexport function deriveEscrowPda(programId: PublicKey, buyer: PublicKey, taskId: string): PublicKey {\n return PublicKey.findProgramAddressSync(\n [utf8(\"escrow\"), buyer.toBytes(), utf8(taskId)],\n programId,\n )[0];\n}\n\n/** PlatformConfig: seeds `[b\"config\"]`, with the canonical bump the account stores. */\nexport function findPlatformConfigPda(programId: PublicKey): [PublicKey, number] {\n return PublicKey.findProgramAddressSync([utf8(\"config\")], programId);\n}\n\nexport function derivePlatformConfigPda(programId: PublicKey): PublicKey {\n return findPlatformConfigPda(programId)[0];\n}\n\n/** AdminConfig: seeds `[b\"admin\"]`. */\nexport function deriveAdminConfigPda(programId: PublicKey): PublicKey {\n return PublicKey.findProgramAddressSync([utf8(\"admin\")], programId)[0];\n}\n","// The PlatformConfig account layout, the one off-chain copy; accounts.test.ts locks it to the\n// committed IDL.\nimport bs58 from \"bs58\";\n\n/** Byte offsets after the 8-byte discriminator, and the account length. */\nexport const PLATFORM_CONFIG_LAYOUT = {\n version: 8,\n fee_bps: 9,\n oracle_authority: 11,\n usdc_mint: 43,\n treasury: 75,\n bump: 107,\n length: 108,\n} as const;\n\n/** `sha256(\"account:PlatformConfig\")[0..8]`. */\nexport const PLATFORM_CONFIG_DISCRIMINATOR: readonly number[] = [\n 160, 78, 128, 0, 248, 83, 230, 160,\n];\n\nexport interface PlatformConfigAccount {\n version: number;\n feeBps: number;\n oracleAuthority: string;\n usdcMint: string;\n treasury: string;\n bump: number;\n}\n\n/**\n * Decode PlatformConfig account data. Throws on a wrong length or discriminator; the\n * version is returned for the caller to check against `CURRENT_ACCOUNT_VERSION`.\n */\nexport function decodePlatformConfig(data: Uint8Array): PlatformConfigAccount {\n const L = PLATFORM_CONFIG_LAYOUT;\n if (data.length !== L.length) {\n throw new Error(\n `PlatformConfig account is ${String(data.length)} bytes, expected ${String(L.length)}`,\n );\n }\n if (PLATFORM_CONFIG_DISCRIMINATOR.some((byte, i) => data[i] !== byte)) {\n throw new Error(\"PlatformConfig discriminator mismatch: not a PlatformConfig account\");\n }\n const byte = (at: number): number => data[at] ?? 0;\n const key = (at: number): string => bs58.encode(data.subarray(at, at + 32));\n return {\n version: byte(L.version),\n feeBps: byte(L.fee_bps) | (byte(L.fee_bps + 1) << 8),\n oracleAuthority: key(L.oracle_authority),\n usdcMint: key(L.usdc_mint),\n treasury: key(L.treasury),\n bump: byte(L.bump),\n };\n}\n","import type { TaskSpec } from \"@escro/shared\";\n\nimport type { SubmitDeliverableParams } from \"./types.js\";\n\n/**\n * The result a {@link ServiceAdapter} returns from `execute`. Escro is agnostic\n * to what produced it: `content` is the deliverable itself, `contentHash` is the\n * SHA-256 hex digest the Buyer verifies the deliverable against, and `proofUri`\n * optionally points at where the content is pinned (IPFS/Arweave) or at a proof.\n * No currency or token field appears here; token conversion is adapter-internal\n * (ARCHITECTURE §3, §7).\n */\nexport interface ServiceResult {\n /** The deliverable itself. */\n content: string | Buffer;\n /** SHA-256 hex digest of {@link ServiceResult.content}. */\n contentHash: string;\n /** Content-addressed URI (ipfs://, ar://) or proof URI for the deliverable. */\n proofUri?: string;\n /** Arbitrary adapter-specific metadata (model, timings, subnet ids, ...). */\n metadata: Record<string, unknown>;\n}\n\n/**\n * A Worker Bot implements ServiceAdapter to wrap any async service (a Bittensor\n * subnet, an Akash deployment, a Render job, ...). Escro never sees what is\n * underneath and never sees a non-USDC token: the adapter handles any token\n * conversion internally (ARCHITECTURE §3, §7). Every pre-built adapter reuses\n * this interface and is validated by `assertServiceAdapterContract`.\n */\nexport interface ServiceAdapter {\n /** Stable identifier, e.g. \"bittensor:sn56\", \"akash\", \"render\". */\n id: string;\n /** Advertised capabilities, e.g. [\"llm_inference\", \"image_gen\"]. */\n capabilities: string[];\n /** Execute the task described by `spec` and return the deliverable. */\n execute(spec: TaskSpec): Promise<ServiceResult>;\n /** Report whether the underlying service is reachable and ready. */\n healthCheck(): Promise<boolean>;\n}\n\n/**\n * Map a {@link ServiceResult} onto {@link SubmitDeliverableParams}, surfacing the\n * `contentHash` (and `proofUri`, when present) that `submit_deliverable` records.\n * This is the single point where an adapter's output crosses into the escrow\n * worker flow.\n */\nexport function serviceResultToSubmitParams(result: ServiceResult): SubmitDeliverableParams {\n return {\n contentHash: result.contentHash,\n ...(result.proofUri !== undefined && { proofUri: result.proofUri }),\n };\n}\n","import { createHash } from \"crypto\";\n\nimport type { TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"./adapter.js\";\nimport { EscroError } from \"./errors.js\";\n\n/** Options controlling {@link assertServiceAdapterContract}. */\nexport interface AdapterContractOptions {\n /**\n * A representative TaskSpec the adapter can execute. The harness calls\n * `execute(sampleSpec)` and validates the returned ServiceResult, so the spec\n * should be one the adapter genuinely handles.\n */\n sampleSpec: TaskSpec;\n}\n\n/** Thrown by {@link assertServiceAdapterContract}, listing every contract violation. */\nexport class AdapterContractError extends EscroError {\n constructor(\n adapterId: string,\n public readonly violations: string[],\n ) {\n super(\n `ServiceAdapter \"${adapterId}\" violates the adapter contract:\\n- ${violations.join(\"\\n- \")}`,\n \"ADAPTER_CONTRACT_VIOLATION\",\n );\n this.name = \"AdapterContractError\";\n }\n}\n\nfunction errMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/** Validate the shape and hash integrity of a value returned by `execute`. */\nfunction validateServiceResult(result: unknown): string[] {\n if (typeof result !== \"object\" || result === null) {\n return [\"`execute()` must resolve to a ServiceResult object\"];\n }\n const violations: string[] = [];\n const r = result as {\n content?: unknown;\n contentHash?: unknown;\n proofUri?: unknown;\n metadata?: unknown;\n };\n\n const contentIsValid = typeof r.content === \"string\" || Buffer.isBuffer(r.content);\n if (!contentIsValid) {\n violations.push(\"`content` must be a string or Buffer\");\n }\n\n if (typeof r.contentHash !== \"string\" || r.contentHash.trim() === \"\") {\n violations.push(\"`contentHash` must be a non-empty string\");\n } else if (contentIsValid && r.contentHash !== sha256Hex(r.content as string | Buffer)) {\n violations.push(\"`contentHash` must equal the SHA-256 hex digest of `content`\");\n }\n\n if (r.proofUri !== undefined && typeof r.proofUri !== \"string\") {\n violations.push(\"`proofUri`, when present, must be a string\");\n }\n\n if (typeof r.metadata !== \"object\" || r.metadata === null || Array.isArray(r.metadata)) {\n violations.push(\"`metadata` must be a plain object\");\n }\n\n return violations;\n}\n\n/**\n * Assert that `adapter` satisfies the ServiceAdapter contract. Resolves with the\n * ServiceResult produced by `execute(sampleSpec)` when the adapter conforms;\n * rejects with an {@link AdapterContractError} listing every violation otherwise.\n *\n * Reusable across adapters (this phase's Bittensor one, Phase 6's four, Phase 8's\n * networks): a conforming adapter passes, a malformed one fails. The parameter is\n * typed `ServiceAdapter`, but the harness validates at runtime: JS callers and\n * `as`-cast objects reach this too, so every field is checked defensively.\n */\nexport async function assertServiceAdapterContract(\n adapter: ServiceAdapter,\n options: AdapterContractOptions,\n): Promise<ServiceResult> {\n const a = adapter as {\n id?: unknown;\n capabilities?: unknown;\n execute?: unknown;\n healthCheck?: unknown;\n };\n const violations: string[] = [];\n const id = typeof a.id === \"string\" && a.id.trim() !== \"\" ? a.id : \"(unknown)\";\n\n if (typeof a.id !== \"string\" || a.id.trim() === \"\") {\n violations.push(\"`id` must be a non-empty string\");\n }\n // capabilities must be non-empty so the adapter is discoverable in EscroBots.\n if (\n !Array.isArray(a.capabilities) ||\n a.capabilities.length === 0 ||\n (a.capabilities as unknown[]).some((c) => typeof c !== \"string\" || c.trim() === \"\")\n ) {\n violations.push(\"`capabilities` must be a non-empty array of non-empty strings\");\n }\n if (typeof a.healthCheck !== \"function\") {\n violations.push(\"`healthCheck` must be a function\");\n }\n if (typeof a.execute !== \"function\") {\n violations.push(\"`execute` must be a function\");\n }\n\n if (typeof a.healthCheck === \"function\") {\n try {\n const healthy = await (a.healthCheck as () => Promise<unknown>)();\n if (typeof healthy !== \"boolean\") {\n violations.push(\"`healthCheck()` must resolve to a boolean\");\n }\n } catch (err) {\n violations.push(`\\`healthCheck()\\` threw: ${errMessage(err)}`);\n }\n }\n\n let result: ServiceResult | undefined;\n if (typeof a.execute === \"function\") {\n try {\n result = await (a.execute as (spec: TaskSpec) => Promise<ServiceResult>)(options.sampleSpec);\n violations.push(...validateServiceResult(result));\n } catch (err) {\n violations.push(`\\`execute()\\` threw: ${errMessage(err)}`);\n result = undefined;\n }\n }\n\n if (violations.length > 0 || result === undefined) {\n throw new AdapterContractError(\n id,\n violations.length > 0 ? violations : [\"`execute()` produced no result\"],\n );\n }\n return result;\n}\n","/**\n * Shared Bittensor-subnet ServiceAdapter core. SN56 (gradients), SN17 (404gen) and\n * SN51 (lium) are three Bittensor-shaped adapters that swap a per-task USDC budget\n * into TAO internally, pay subnet miners in TAO, collect a deliverable, and return a\n * currency-free `ServiceResult`. This module owns what they share: the branded `Tao`\n * type (which exists ONLY in the adapter layer and can never reach a `ServiceResult`\n * or the escrow submit path -- see bittensor.type-test.ts for the compile-time proof),\n * the USDC->TAO swap / subnet-call / pin ports, the shared default ports, and the\n * `execute` skeleton. Each adapter supplies its own subnet id, capabilities, budget,\n * demo logic and default-port wiring, then delegates `execute` to\n * {@link createBittensorSubnetAdapter}. Ridges (USD-billed, no TAO) is deliberately\n * NOT part of this core.\n */\nimport { createHash } from \"crypto\";\n\nimport type { TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in TAO (Bittensor's token). Branded so it cannot be assigned to\n * or from a plain `number` by accident and (the point of the brand) so it can never\n * appear in a `ServiceResult` or the escrow submit path: those types have no field of\n * this type. TAO exists ONLY inside the Bittensor adapter layer.\n */\nexport type Tao = number & { readonly __brand: \"TAO\" };\n\n/** Construct a {@link Tao} amount from a plain number. Adapter-internal use only. */\nexport function tao(amount: number): Tao {\n return amount as Tao;\n}\n\n/** Swap a microUSDC budget into TAO. Real workers route this through a DEX (e.g. Jupiter). */\nexport type UsdcToTaoSwap = (microUsdc: number) => Promise<Tao>;\n\n/**\n * Pay subnet miners `budget` TAO to run `spec`; resolve with the raw deliverable. The\n * single shared port shape across every Bittensor adapter (a GPU-rental call is a paid\n * subnet call too; lium re-exports this as `RunGpuJob`).\n */\nexport type SubnetCall = (spec: TaskSpec, budget: Tao) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** SHA-256 hex digest of a deliverable. */\nexport function sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// Nominal reference rate: microUSDC -> TAO. Only the stub swap cares about the exact value.\nexport const REFERENCE_MICRO_USDC_PER_TAO = 300_000_000;\n\n/** Default fixed-rate reference swap, shared by every reference Bittensor adapter. */\nexport const defaultSwap: UsdcToTaoSwap = (microUsdc) =>\n Promise.resolve(tao(microUsdc / REFERENCE_MICRO_USDC_PER_TAO));\n\n/** Default deterministic `ipfs://` placeholder pin, shared by every reference adapter. */\nexport const defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/** Fully-resolved ports and identity for {@link createBittensorSubnetAdapter}. */\nexport interface BittensorSubnetAdapterConfig {\n /** Subnet identifier (e.g. \"sn56\"); forms the adapter id `bittensor:<subnet>`. */\n subnet: string;\n /** Advertised capabilities for EscroBots discovery. */\n capabilities: string[];\n /** microUSDC allocated to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc: number;\n /** USDC->TAO swap port. */\n swap: UsdcToTaoSwap;\n /** Subnet-call port (pays the subnet in TAO and returns the deliverable). */\n callSubnet: SubnetCall;\n /** Pinning port. */\n pin: PinContent;\n /** Health-check port. */\n checkHealth: () => Promise<boolean>;\n}\n\n/**\n * Build a Bittensor-subnet {@link ServiceAdapter} from fully-resolved ports. The\n * execute skeleton: swap the USDC budget into TAO (internal, never surfaced), pay the\n * subnet in TAO and collect the deliverable, then hash and pin. The recorded\n * `ServiceResult` is currency-free (no TAO field). Every reference TAO adapter resolves\n * its own defaults and delegates here.\n */\nexport function createBittensorSubnetAdapter(config: BittensorSubnetAdapterConfig): ServiceAdapter {\n const id = `bittensor:${config.subnet}`;\n return {\n id,\n capabilities: config.capabilities,\n healthCheck: config.checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into TAO (internal, never surfaced).\n const budgetTao = await config.swap(config.taskBudgetMicroUsdc);\n // 2. Pay subnet miners in TAO and collect the deliverable.\n const content = await config.callSubnet(spec, budgetTao);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await config.pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: id, subnet: config.subnet },\n };\n },\n };\n}\n","/**\n * Gradients (Bittensor SN56) ServiceAdapter: the first SHIPPED, supported adapter\n * (the reference pattern P6.T6b-d replicate). A Worker Bot wraps the Gradients\n * fine-tuning subnet behind the `ServiceAdapter` interface: it swaps a per-task\n * USDC budget into TAO internally, pays subnet miners in TAO to fine-tune, collects\n * a checkpoint + eval deliverable, and returns a currency-free `ServiceResult`. The\n * Buyer and the escrow contract only ever see USDC; no TAO-typed value crosses this\n * boundary into SDK core (ARCHITECTURE §3, §7; see ../bittensor/bittensor.type-test.ts\n * for the compile-time proof shared by the Bittensor trio).\n *\n * The swap, subnet call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN56 dendrite, Pinata/Arweave).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (checkpoint\n * + eval JSON). Whether the eval clears the threshold is decided by the BUYER's\n * review.ts, which independently recomputes the score (see `scoreGradientsDemoDeliverable`).\n * The worker never scores-for-release and never releases (CLAUDE.md product framing).\n *\n * Relationship to `examples/worker-bot/bittensor-adapter.ts`: that example is\n * pedagogy (\"author your own adapter against the public interface\", driven by e2e\n * scenario 13 / the P5.T2b obligation); THIS module is the shipped, importable\n * surface a generated bot uses. The USDC->TAO port skeleton and the execute shape are\n * shared with the other Bittensor adapters via `../bittensor/index.js`; this module\n * supplies only its subnet identity, capabilities, budget, and demo logic.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Configuration and injectable ports for {@link createGradientsAdapter}. */\nexport interface GradientsAdapterConfig {\n /** Subnet identifier. Defaults to \"sn56\" (Gradients); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"fine-tune\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n callSubnet?: SubnetCall;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** Stable id/capabilities, LOCKED against `ADAPTER_DESCRIPTORS.gradients` by a kit test. */\nexport const GRADIENTS_ADAPTER_ID = \"bittensor:sn56\";\nexport const GRADIENTS_CAPABILITIES = [\"fine-tune\"] as const;\n\nconst DEFAULT_SUBNET = \"sn56\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 5_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job (BOT_KIT_PRD §6 / §13): a deterministic fine-tune the buyer\n// template's 5-minute journey hires this bot for. The \"model\" learns the fixed\n// affine map y = 2x + 1 on a fixed dataset; the deliverable is the model's\n// predictions on that dataset. Acceptance is machine-checkable and recomputed by\n// the BUYER (see scoreGradientsDemoDeliverable); the worker's self-reported eval\n// score is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */\nexport const GRADIENTS_DEMO_MARKER = \"gradients-sn56-demo-v1\";\n\n/** The demo eval floor: predictions must be at least this accurate to be accepted. */\nexport const GRADIENTS_DEMO_EVAL_FLOOR = 0.8;\n\n/** The demo's fixed inputs. The reference target maps each `x` to `2x + 1`. */\nconst DEMO_DATASET: readonly number[] = [3, 7, 11, 15, 19];\n\nfunction demoExpectedOutputs(): number[] {\n return DEMO_DATASET.map((x) => 2 * x + 1);\n}\n\n/**\n * The canned Gradients demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const gradientsDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no fine-tune category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Fine-tune the reference model on the canned SN56 demo dataset and return its \" +\n \"predictions on the same inputs. The target map is y = 2x + 1. Acceptance is \" +\n \"deterministic and recomputed by the buyer: prediction accuracy must be >= 0.8; \" +\n \"the worker's self-reported eval score is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-eval-floor\",\n description:\n \"Prediction accuracy on the demo dataset is >= 0.8, recomputed by the buyer from the deliverable.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GRADIENTS_DEMO_MARKER,\n dataset: [...DEMO_DATASET],\n target: \"y = 2x + 1\",\n evalFloor: GRADIENTS_DEMO_EVAL_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the correct predictions plus a\n * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.\n * Exposed so the demo journey and tests share one source of the expected artifact.\n */\nexport function solveGradientsDemo(): string {\n const predictions = demoExpectedOutputs();\n return canonicalize({\n checkpoint: \"reference-sn56-demo-checkpoint\",\n eval: { metric: \"accuracy\", score: 1 },\n predictions,\n });\n}\n\ninterface DemoDeliverable {\n predictions: number[];\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const predictions = (parsed as { predictions?: unknown }).predictions;\n if (!Array.isArray(predictions) || predictions.some((p) => typeof p !== \"number\")) {\n return null;\n }\n return { predictions: predictions as number[] };\n}\n\n/**\n * The BUYER's independent recompute of the demo eval score in [0, 1]. Reads the\n * substantive output (the predictions) and compares it to the target map the buyer\n * itself defines; it deliberately IGNORES any self-reported `eval.score` in the\n * deliverable, so release can never be worker-controlled. Malformed\n * or unparseable content scores 0 and never throws.\n */\nexport function scoreGradientsDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n const expected = demoExpectedOutputs();\n let matches = 0;\n for (let i = 0; i < expected.length; i++) {\n if (parsed.predictions[i] === expected[i]) {\n matches++;\n }\n }\n return matches / expected.length;\n}\n\n// A generic (non-demo) fine-tune produces a placeholder checkpoint+eval so a fresh\n// worker returns a well-formed ServiceResult before a real SN56 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n checkpoint: \"reference-sn56-checkpoint\",\n eval: { metric: \"accuracy\", score: 0 },\n note: \"reference stub - replace the callSubnet port with a real SN56 miner call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultCallSubnet: SubnetCall = (spec) =>\n Promise.resolve(\n spec.metadata.demo === GRADIENTS_DEMO_MARKER\n ? solveGradientsDemo()\n : referencePlaceholder(spec),\n );\n\n/**\n * Build a Gradients (SN56) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core.\n */\nexport function createGradientsAdapter(config: GradientsAdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...GRADIENTS_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.callSubnet ?? defaultCallSubnet,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Ridges (AI coding agents) ServiceAdapter: a SHIPPED, supported reference adapter\n * built on the same pattern as the Gradients SN56 adapter. A Worker Bot\n * wraps a Ridges coding agent behind the `ServiceAdapter` interface: given a coding\n * task, it runs the agent to produce a solution, runs the task's test suite, and\n * returns a test report as the `ServiceResult` deliverable. The Buyer and the escrow\n * contract only ever see USDC.\n *\n * Unlike the Bittensor adapters (gradients SN56, 404gen SN17, lium SN51), Ridges is\n * billed in USD through its platform API, so there is no in-adapter token conversion\n * and no TAO-typed value to keep out of SDK core: `serviceRef` is a bare `\"ridges\"`,\n * not `bittensor:<subnet>` (kit `ADAPTER_DESCRIPTORS.ridges`). The worker still fronts\n * the service cost and is reimbursed in USDC at release (see README float profile).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (a test\n * report). Whether the suite passed and coverage cleared the target is decided by the\n * BUYER's review.ts, which independently recomputes the outcome from the delivered\n * test outputs (see `scoreRidgesDemoDeliverable`). The worker never scores-for-release\n * and never releases, and its self-reported pass/coverage is never trusted\n * (CLAUDE.md product framing).\n *\n * The coding-agent call and pinning are injectable ports so the reference runs (and is\n * tested) without a live Ridges endpoint or IPFS node. A production worker supplies\n * real implementations (the Ridges platform API for `runAgent`, Pinata/Arweave for\n * `pin`). The port pattern mirrors the gradients adapter deliberately. Ridges is\n * USD-billed with no TAO, so it deliberately does not use the shared `adapters/bittensor`\n * core (that core covers only the Bittensor trio: SN56, SN17, SN51).\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/** Run the coding agent for `spec`; resolve with the raw deliverable (a test report). */\nexport type RunCodingAgent = (spec: TaskSpec) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** Configuration and injectable ports for {@link createRidgesAdapter}. */\nexport interface RidgesAdapterConfig {\n /** Service identifier. Defaults to \"ridges\"; forms the adapter id. */\n service?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"code-generation\"]`. */\n capabilities?: string[];\n /** Coding-agent port. Default: solves the canned demo kata; a placeholder otherwise. */\n runAgent?: RunCodingAgent;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/**\n * Stable id/capabilities. Locked against `ADAPTER_DESCRIPTORS.ridges` by a kit test\n * at merge (consult C2; the lock lives in create-escro-bot, which depends on this\n * package, and is landed with the barrel wiring — LANE-NOTES merge step 3).\n */\nexport const RIDGES_ADAPTER_ID = \"ridges\";\nexport const RIDGES_CAPABILITIES = [\"code-generation\"] as const;\n\nconst DEFAULT_SERVICE = \"ridges\";\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ---------------------------------------------------------------------------\n// Canned demo kata (BOT_KIT_PRD §6 / §13): a deterministic coding job the buyer\n// template's 5-minute journey hires this bot for. The kata is a fixed FizzBuzz\n// repo: implement FizzBuzz and make its test battery pass. The deliverable is the\n// solution's test report (each battery input and the output the solution produced).\n// Acceptance is machine-checkable and recomputed by the BUYER (see\n// scoreRidgesDemoDeliverable): every delivered test must pass (exit 0) AND coverage\n// of the battery must clear the target. The worker's self-report is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default agent stub recognizes it. */\nexport const RIDGES_DEMO_MARKER = \"ridges-demo-v1\";\n\n/** The demo coverage target: the fraction of the test battery that must be covered. */\nexport const RIDGES_DEMO_COVERAGE_TARGET = 0.8;\n\n/**\n * The demo's fixed test battery: FizzBuzz over these inputs, chosen to exercise every\n * branch (plain number, Fizz, Buzz, FizzBuzz).\n */\nconst DEMO_INPUTS: readonly number[] = [1, 2, 3, 5, 15];\n\n/** The kata's reference logic; the buyer recomputes expected outputs from this. */\nfunction fizzbuzz(n: number): string {\n if (n % 15 === 0) return \"FizzBuzz\";\n if (n % 3 === 0) return \"Fizz\";\n if (n % 5 === 0) return \"Buzz\";\n return String(n);\n}\n\n/**\n * The canned Ridges demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const ridgesDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"code_generation\",\n description:\n \"Implement FizzBuzz for the fixed demo battery and return a test report: for each \" +\n \"battery input, the output your implementation produced. Acceptance is deterministic \" +\n \"and recomputed by the buyer: every delivered test must pass (exit 0) and coverage of \" +\n \"the battery must be >= 0.8; the worker's self-reported pass/coverage is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-tests-pass\",\n description:\n \"Every delivered test passes (exit 0), recomputed by the buyer from the test report.\",\n required: true,\n },\n {\n id: \"ac-coverage\",\n description: \"Coverage of the demo battery is >= 0.8, recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: RIDGES_DEMO_MARKER,\n kata: \"fizzbuzz\",\n inputs: [...DEMO_INPUTS],\n coverageTarget: RIDGES_DEMO_COVERAGE_TARGET,\n },\n};\n\n/** The reference source solution, carried in the deliverable for human readers only. */\nconst REFERENCE_SOLUTION =\n \"export function fizzbuzz(n: number): string {\\n\" +\n ' if (n % 15 === 0) return \"FizzBuzz\";\\n' +\n ' if (n % 3 === 0) return \"Fizz\";\\n' +\n ' if (n % 5 === 0) return \"Buzz\";\\n' +\n \" return String(n);\\n\" +\n \"}\\n\";\n\n/**\n * The reference solution to the demo kata: a passing test report over the full\n * battery, plus a (self-reported, buyer-ignored) pass/coverage block, as canonical\n * JSON. Deterministic. Exposed so the demo journey and tests share one source of the\n * expected artifact.\n */\nexport function solveRidgesDemo(): string {\n const tests = DEMO_INPUTS.map((input) => ({ input, output: fizzbuzz(input) }));\n return canonicalize({\n language: \"typescript\",\n solution: REFERENCE_SOLUTION,\n coverage: 1,\n passed: true,\n tests,\n });\n}\n\ninterface DemoTestResult {\n input: number;\n output: string;\n}\n\nfunction parseTestReport(content: string | Buffer): DemoTestResult[] | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const tests = (parsed as { tests?: unknown }).tests;\n if (!Array.isArray(tests)) {\n return null;\n }\n const results: DemoTestResult[] = [];\n for (const t of tests) {\n if (typeof t !== \"object\" || t === null) {\n return null;\n }\n const { input, output } = t as { input?: unknown; output?: unknown };\n if (typeof input !== \"number\" || typeof output !== \"string\") {\n return null;\n }\n results.push({ input, output });\n }\n return results;\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance, as a score in [0, 1].\n * It reads the substantive output (the delivered test outputs) and recomputes the\n * expected FizzBuzz result for each; it deliberately IGNORES any self-reported\n * pass/coverage in the deliverable, so release can never be worker-controlled.\n * Semantics:\n * - Any delivered test whose output is wrong = the suite did not pass (exit != 0):\n * score 0, no matter how much of the battery is covered.\n * - Otherwise the score is coverage = (distinct battery inputs delivered) / (battery\n * size); the buyer releases when it clears {@link RIDGES_DEMO_COVERAGE_TARGET}.\n * Malformed or unparseable content scores 0 and never throws.\n */\nexport function scoreRidgesDemoDeliverable(content: string | Buffer): number {\n const results = parseTestReport(content);\n if (results === null) {\n return 0;\n }\n const battery = new Set(DEMO_INPUTS);\n const coveredInputs = new Set<number>();\n for (const { input, output } of results) {\n if (!battery.has(input)) {\n // A result outside the battery does not fail the suite and does not count\n // toward coverage; it is simply ignored.\n continue;\n }\n if (output !== fizzbuzz(input)) {\n // A failing test = non-zero exit: the whole suite is rejected.\n return 0;\n }\n coveredInputs.add(input);\n }\n return coveredInputs.size / DEMO_INPUTS.length;\n}\n\n// A generic (non-demo) coding job produces a placeholder solution+report so a fresh\n// worker returns a well-formed ServiceResult before a real Ridges agent is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n language: \"typescript\",\n solution: \"// reference stub - replace the runAgent port with a real Ridges agent call.\",\n passed: false,\n tests: [],\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunAgent: RunCodingAgent = (spec) =>\n Promise.resolve(\n spec.metadata.demo === RIDGES_DEMO_MARKER ? solveRidgesDemo() : referencePlaceholder(spec),\n );\n\nconst defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/**\n * Build a Ridges {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with\n * the default ports; supply real ports for production use.\n */\nexport function createRidgesAdapter(config: RidgesAdapterConfig = {}): ServiceAdapter {\n const service = config.service ?? DEFAULT_SERVICE;\n const capabilities = config.capabilities ?? [...RIDGES_CAPABILITIES];\n const runAgent = config.runAgent ?? defaultRunAgent;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: service,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Run the coding agent and collect the test report (USD-billed; no swap).\n const content = await runAgent(spec);\n // 2. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: service },\n };\n },\n };\n}\n","/**\n * 404gen (Bittensor SN17) ServiceAdapter: a batch 3D-generation reference adapter,\n * built to the pattern the shipped Gradients (SN56) adapter established. A\n * Worker Bot wraps the 404gen text-to-3D subnet behind the `ServiceAdapter` interface:\n * it swaps a per-task USDC budget into TAO internally, pays subnet miners in TAO to\n * generate a batch of 3D assets, collects the batch deliverable, and returns a\n * currency-free `ServiceResult`. The Buyer and the escrow contract only ever see USDC;\n * no TAO-typed value crosses this boundary into SDK core (ARCHITECTURE §3, §7; see\n * ../bittensor/bittensor.type-test.ts for the compile-time proof shared by the Bittensor trio).\n *\n * The swap, subnet call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN17 dendrite, Pinata/Arweave).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (a batch of\n * 3D assets, each with a declared container format and polygon count). Whether the batch\n * is acceptable is decided by the BUYER's review.ts. For the canned demo the buyer knows\n * the exact expected artifact (the eval-threshold review re-verifies the fetched\n * deliverable hashes to the submitted contentHash) and additionally gates on the declared\n * per-asset descriptors via `score404genDemoDeliverable` (format, polygon range, batch\n * completeness). That recompute reads the DECLARED descriptors, not the asset bytes: a\n * production 404gen buyer generating novel assets must derive the container from the\n * fetched asset's magic bytes and the polygon count from its parsed geometry before\n * releasing. The worker never scores-for-release and never releases (CLAUDE.md framing).\n *\n * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor\n * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,\n * capabilities, budget, and demo logic.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Configuration and injectable ports for {@link create404genAdapter}. */\nexport interface Gen404AdapterConfig {\n /** Subnet identifier. Defaults to \"sn17\" (404gen); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"3d-generation\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n callSubnet?: SubnetCall;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** Stable id/capabilities, to be locked against `ADAPTER_DESCRIPTORS[\"404gen\"]` by a kit test at merge. */\nexport const GEN404_ADAPTER_ID = \"bittensor:sn17\";\nexport const GEN404_CAPABILITIES = [\"3d-generation\"] as const;\n\nconst DEFAULT_SUBNET = \"sn17\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 5_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job (BOT_KIT_PRD §6 / §13): a deterministic batch 3D job the buyer\n// template's 5-minute journey hires this bot for. The batch requests one asset with\n// a machine-checkable format + polygon-count contract. Acceptance is recomputed by\n// the BUYER (see score404genDemoDeliverable): each declared asset's format must be an\n// allowed container, its declared polygon count must fall in range, and the batch must\n// be complete. Any self-reported eval score is ignored (a production buyer parses the\n// actual asset geometry - see the module note).\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */\nexport const GEN404_DEMO_MARKER = \"404gen-sn17-demo-v1\";\n\n/** The demo eval floor: the batch must be complete and every asset valid (score 1). */\nexport const GEN404_DEMO_EVAL_FLOOR = 1;\n\n/** The demo batch contract: what the buyer independently checks each asset against. */\ninterface BatchExpectation {\n /** Number of assets the batch must contain to be complete. */\n requestedAssets: number;\n /** Container formats the buyer accepts (compared case-insensitively). */\n allowedFormats: readonly string[];\n /** Inclusive polygon-count bounds a valid asset must fall within. */\n minPolygons: number;\n maxPolygons: number;\n}\n\nconst DEMO_EXPECTATION: BatchExpectation = {\n requestedAssets: 1,\n allowedFormats: [\"GLB\", \"PLY\"],\n minPolygons: 1_000,\n maxPolygons: 1_000_000,\n};\n\n/**\n * The canned 404gen demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const gen404DemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no 3D category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Generate the canned SN17 demo batch: one 3D asset in a GLB or PLY container with a \" +\n \"polygon count between 1000 and 1000000. Acceptance is deterministic and recomputed \" +\n \"by the buyer: every requested asset must be present, in an allowed format, and in \" +\n \"polygon range; the worker's self-reported validity is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-format-valid\",\n description:\n \"Every asset is in an allowed container format (GLB or PLY), recomputed by the buyer.\",\n required: true,\n },\n {\n id: \"ac-polygon-range\",\n description:\n \"Every asset's polygon count is within [1000, 1000000], recomputed by the buyer.\",\n required: true,\n },\n {\n id: \"ac-batch-complete\",\n description:\n \"The batch contains all requested assets (completeness), recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GEN404_DEMO_MARKER,\n requestedAssets: DEMO_EXPECTATION.requestedAssets,\n allowedFormats: [...DEMO_EXPECTATION.allowedFormats],\n minPolygons: DEMO_EXPECTATION.minPolygons,\n maxPolygons: DEMO_EXPECTATION.maxPolygons,\n },\n};\n\n/**\n * The reference solution to the demo job: a complete batch of valid assets plus a\n * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.\n * Exposed so the demo journey and tests share one source of the expected artifact.\n */\nexport function solveGen404Demo(): string {\n return canonicalize({\n assets: [{ format: \"GLB\", polygonCount: 5_000, uri: \"ipfs://404gen-sn17-demo-asset-0\" }],\n eval: { metric: \"validity\", score: 1 },\n });\n}\n\ninterface DemoAsset {\n format: string;\n polygonCount: number;\n}\n\ninterface DemoBatch {\n assets: DemoAsset[];\n}\n\nfunction parseBatch(content: string | Buffer): DemoBatch | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const assets = (parsed as { assets?: unknown }).assets;\n if (!Array.isArray(assets)) {\n return null;\n }\n const cleaned: DemoAsset[] = [];\n for (const asset of assets) {\n if (typeof asset !== \"object\" || asset === null) {\n return null;\n }\n const format = (asset as { format?: unknown }).format;\n const polygonCount = (asset as { polygonCount?: unknown }).polygonCount;\n if (typeof format !== \"string\" || typeof polygonCount !== \"number\") {\n return null;\n }\n cleaned.push({ format, polygonCount });\n }\n return { assets: cleaned };\n}\n\nfunction isAssetValid(asset: DemoAsset): boolean {\n const formatOk = DEMO_EXPECTATION.allowedFormats.some(\n (f) => f.toLowerCase() === asset.format.toLowerCase(),\n );\n const rangeOk =\n asset.polygonCount >= DEMO_EXPECTATION.minPolygons &&\n asset.polygonCount <= DEMO_EXPECTATION.maxPolygons;\n return formatOk && rangeOk;\n}\n\n/**\n * The BUYER's recompute of the demo batch score in [0, 1] over the deliverable's\n * DECLARED per-asset descriptors. Every delivered asset must pass the format and\n * polygon-range checks (any single invalid asset scores 0, so a well-formed but junk\n * extra cannot slip through), and the batch must contain at least the requested count\n * (completeness); a short batch scores the filled fraction. Any self-reported `eval`\n * score in the deliverable is ignored. Malformed or unparseable content scores 0 and\n * never throws.\n *\n * NOTE: this gates the deliverable's declared `format`/`polygonCount` fields, not the\n * asset bytes. For the deterministic canned demo that is sufficient because the buyer\n * additionally knows the exact expected artifact (the eval-threshold review re-verifies\n * the fetched deliverable hashes to the submitted contentHash). A production 404gen\n * buyer generating NOVEL assets must derive the container from the fetched asset's magic\n * bytes and the polygon count from its parsed geometry before releasing (kit-docs debt).\n */\nexport function score404genDemoDeliverable(content: string | Buffer): number {\n const batch = parseBatch(content);\n if (batch === null) {\n return 0;\n }\n if (batch.assets.some((asset) => !isAssetValid(asset))) {\n return 0;\n }\n return Math.min(batch.assets.length / DEMO_EXPECTATION.requestedAssets, 1);\n}\n\n// A generic (non-demo) batch produces a placeholder asset so a fresh worker returns a\n// well-formed ServiceResult before a real SN17 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n assets: [{ format: \"GLB\", polygonCount: 0, uri: \"ipfs://placeholder\" }],\n note: \"reference stub - replace the callSubnet port with a real SN17 miner call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultCallSubnet: SubnetCall = (spec) =>\n Promise.resolve(\n spec.metadata.demo === GEN404_DEMO_MARKER ? solveGen404Demo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a 404gen (SN17) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core.\n */\nexport function create404genAdapter(config: Gen404AdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...GEN404_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.callSubnet ?? defaultCallSubnet,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Lium (Bittensor SN51) ServiceAdapter: a SHIPPED, supported adapter following the\n * P6.T6a Gradients pattern. A Worker Bot wraps the Lium GPU-compute subnet behind the\n * `ServiceAdapter` interface: it swaps a per-task USDC budget into TAO internally,\n * rents GPU compute from subnet miners in TAO to run the job, collects the output\n * artifact, and returns a currency-free `ServiceResult`. The Buyer and the escrow\n * contract only ever see USDC; no TAO-typed value crosses this boundary into SDK core\n * (ARCHITECTURE §3, §7; see ../bittensor/bittensor.type-test.ts for the compile-time\n * proof shared by the Bittensor trio).\n *\n * The swap, GPU-job call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN51 GPU-rental dendrite,\n * Pinata/Arweave for pinning).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the job's\n * output artifact). Whether the job completed with a matching artifact is decided by\n * the BUYER's review.ts, which independently recomputes the scripted job's output and\n * compares hashes (see `scoreLiumDemoDeliverable`). The worker never scores-for-release\n * and never releases, and its self-reported `artifactHash` is never trusted\n * (CLAUDE.md product framing: the buyer is the judge).\n *\n * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor\n * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,\n * capabilities, budget, and demo logic. A GPU-rental call is a paid subnet call, so its\n * port reuses the shared `SubnetCall` shape under the local `RunGpuJob` name.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n sha256Hex,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Rent GPU compute for `budget` TAO and run `spec`'s job; resolve with the raw output artifact. */\nexport type RunGpuJob = SubnetCall;\n\n/** Configuration and injectable ports for {@link createLiumAdapter}. */\nexport interface LiumAdapterConfig {\n /** Subnet identifier. Defaults to \"sn51\" (Lium GPU compute); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"gpu-compute\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** GPU-job port. Default: runs the canned demo job; a deterministic placeholder otherwise. */\n runJob?: RunGpuJob;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// Stable id/capabilities. The adapter's own tests pin its runtime output to these\n// constants; the main-owned kit seam test (`create-escro-bot/src/adapter-seam.test.ts`)\n// cross-checks them against `ADAPTER_DESCRIPTORS.lium` so the registry descriptor and the\n// shipped adapter cannot drift apart.\nexport const LIUM_ADAPTER_ID = \"bittensor:sn51\";\nexport const LIUM_CAPABILITIES = [\"gpu-compute\"] as const;\n\nconst DEFAULT_SUBNET = \"sn51\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 20_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job (BOT_KIT_PRD §6 / §13): a 5-minute scripted GPU job the buyer\n// template's journey hires this bot for. The \"GPU job\" is a deterministic hash\n// chain over a fixed seed, so its output artifact is reproducible: the buyer\n// RECOMPUTES it independently (see scoreLiumDemoDeliverable) and releases only when\n// the job completed, an artifact is present, and its hash matches. The worker's\n// self-reported artifactHash is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default job stub recognizes it. */\nexport const LIUM_DEMO_MARKER = \"lium-sn51-demo-v1\";\n\n/** The demo accept floor: hash-match is exact, so the buyer requires a full match. */\nexport const LIUM_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SEED = \"lium-sn51-demo-seed\";\nconst DEMO_ROUNDS = 1000;\n\n/**\n * The scripted GPU job's deterministic output artifact: a hash chain over the fixed\n * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.\n */\nexport function computeLiumDemoArtifact(): string {\n let h = DEMO_SEED;\n for (let i = 0; i < DEMO_ROUNDS; i++) {\n h = sha256Hex(h);\n }\n return h;\n}\n\n/**\n * The canned Lium demo job. Deterministic; its specHash is pinned by a test (consult\n * C8) because the buyer journey depends on hash stability.\n */\nexport const liumDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no GPU-compute category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Run the canned SN51 scripted GPU job (a fixed hash-chain compute over a known \" +\n \"seed) and return its output artifact. Acceptance is deterministic and recomputed \" +\n \"by the buyer: the job must complete, an output artifact must be present, and the \" +\n \"artifact must match the buyer's independent recompute; the worker's self-reported \" +\n \"artifact hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The scripted job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-artifact-present\",\n description: \"An output artifact is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-hash-match\",\n description:\n \"The output artifact matches the buyer's independent recompute of the scripted job.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: LIUM_DEMO_MARKER,\n seed: DEMO_SEED,\n rounds: DEMO_ROUNDS,\n acceptFloor: LIUM_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the\n * correct output artifact plus a (self-reported, buyer-ignored) artifactHash, as\n * canonical JSON. Deterministic. Exposed so the demo journey and tests share one\n * source of the expected artifact.\n */\nexport function solveLiumDemo(): string {\n const artifact = computeLiumDemoArtifact();\n return canonicalize({\n job: LIUM_DEMO_MARKER,\n status: \"completed\",\n rounds: DEMO_ROUNDS,\n artifact,\n // Self-reported and deliberately ignored by the buyer's recompute.\n artifactHash: sha256Hex(artifact),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n artifact: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as { status?: unknown; artifact?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const artifact = typeof obj.artifact === \"string\" ? obj.artifact : null;\n return { status, artifact };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1\n * when the deliverable satisfies all three criteria and 0 otherwise. It checks\n * completion (status), artifact presence, and hash match by RECOMPUTING the scripted\n * job's output and comparing the substantive artifact; it deliberately IGNORES any\n * self-reported `artifactHash`, so release can never be worker-controlled (consult\n * C10). Malformed or unparseable content scores 0 and never throws.\n */\nexport function scoreLiumDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.artifact === null) {\n return 0;\n }\n return parsed.artifact === computeLiumDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) GPU job produces a placeholder completion report so a fresh\n// worker returns a well-formed ServiceResult before a real SN51 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"lium-sn51-generic\",\n status: \"completed\",\n artifact: null,\n note: \"reference stub - replace the runJob port with a real SN51 GPU-rental call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunJob: RunGpuJob = (spec) =>\n Promise.resolve(\n spec.metadata.demo === LIUM_DEMO_MARKER ? solveLiumDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a Lium (SN51) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core; the GPU-rental\n * port is wired in as the core's `callSubnet`.\n */\nexport function createLiumAdapter(config: LiumAdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...LIUM_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.runJob ?? defaultRunJob,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Akash (Cosmos) ServiceAdapter: a SHIPPED, supported reference adapter that extends the\n * ServiceAdapter library beyond Bittensor (ROADMAP P8, ARCHITECTURE §7). A Worker Bot\n * wraps an Akash deployment behind the `ServiceAdapter` interface: it swaps a per-task\n * USDC budget into AKT internally, provisions a deployment/lease on the Akash decentralized\n * cloud (paying providers in AKT), runs the compute job, collects the output artifact, and\n * returns a currency-free `ServiceResult`. The Buyer and the escrow contract only ever see\n * USDC; no AKT-typed value crosses this boundary into SDK core (ARCHITECTURE §3, §7; see\n * ./akash.type-test.ts for the compile-time proof).\n *\n * Akash is Cosmos-based and billed in its own token (AKT), so -- like the Bittensor trio --\n * it converts USDC internally. But it is NOT a Bittensor subnet (its id is a bare \"akash\",\n * not `bittensor:<subnet>`), so it does not use the `adapters/bittensor` core: it carries\n * its own branded `Akt`, its own swap port, and its own copy of the boundary proof.\n *\n * The swap, deployment call, and pinning are injectable ports so the reference runs (and is\n * tested) without a live DEX, Akash provider, or IPFS node. A production worker supplies\n * real implementations (a DEX/CEX route for the USDC->AKT swap, the Akash SDL/lease flow for\n * the deployment, Pinata/Arweave for pinning). The swap default is a fixed reference rate,\n * not a live price feed -- no price-feed dependency is introduced anywhere in SDK core\n * (CLAUDE.md product framing forbids a price feed in the contract; the reference rate here is\n * a nominal constant a real worker replaces with its own routing).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the job's output\n * artifact). Whether the job completed with a matching artifact is decided by the BUYER's\n * review.ts, which independently recomputes the scripted job's output and compares hashes\n * (see `scoreAkashDemoDeliverable`). The worker never scores-for-release and never releases,\n * and its self-reported `artifactHash` is never trusted (CLAUDE.md product framing: the buyer\n * is the judge).\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in AKT (Akash's token). Branded so it cannot be assigned to or from a\n * plain `number` by accident and (the point of the brand) so it can never appear in a\n * `ServiceResult` or the escrow submit path: those types have no field of this type. AKT\n * exists ONLY inside the Akash adapter layer.\n */\nexport type Akt = number & { readonly __brand: \"AKT\" };\n\n/** Construct an {@link Akt} amount from a plain number. Adapter-internal use only. */\nexport function akt(amount: number): Akt {\n return amount as Akt;\n}\n\n/** Swap a microUSDC budget into AKT. Real workers route this through a DEX/CEX. */\nexport type UsdcToAktSwap = (microUsdc: number) => Promise<Akt>;\n\n/**\n * Provision an Akash deployment/lease funded with `budget` AKT to run `spec`; resolve with\n * the raw deliverable (the job's output artifact).\n */\nexport type RunAkashDeployment = (spec: TaskSpec, budget: Akt) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * Stable id/capabilities. The adapter's own tests pin its runtime output to these\n * constants; the EscroBots registry descriptor for `akash` is registered separately in\n * P8.T6 (capability taxonomy extension).\n */\nexport const AKASH_ADAPTER_ID = \"akash\";\nexport const AKASH_CAPABILITIES = [\"cloud-compute\"] as const;\n\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 10_000_000;\n\n// Nominal reference rate: microUSDC -> AKT. Only the stub swap cares about the exact value;\n// it is a fixed constant, never a live price feed (a real worker replaces the swap port).\nexport const REFERENCE_MICRO_USDC_PER_AKT = 3_000_000;\n\n/** Default fixed-rate reference swap. */\nconst defaultSwap: UsdcToAktSwap = (microUsdc) =>\n Promise.resolve(akt(microUsdc / REFERENCE_MICRO_USDC_PER_AKT));\n\n/** Default deterministic `ipfs://` placeholder pin. */\nconst defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/** Configuration and injectable ports for {@link createAkashAdapter}. */\nexport interface AkashAdapterConfig {\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"cloud-compute\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to AKT (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToAktSwap;\n /** Deployment port. Default: runs the canned demo job; a deterministic placeholder otherwise. */\n runDeployment?: RunAkashDeployment;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a deterministic batch compute job the buyer template's journey\n// hires this bot for. The \"compute job\" is a deterministic hash chain over a fixed\n// seed, so its output artifact is reproducible: the buyer RECOMPUTES it independently\n// (see scoreAkashDemoDeliverable) and releases only when the job completed, an artifact\n// is present, and its hash matches. The worker's self-reported artifactHash is never\n// trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default deployment stub recognizes it. */\nexport const AKASH_DEMO_MARKER = \"akash-demo-v1\";\n\n/** The demo accept floor: hash-match is exact, so the buyer requires a full match. */\nexport const AKASH_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SEED = \"akash-demo-seed\";\nconst DEMO_ROUNDS = 1000;\n\n/**\n * The scripted batch job's deterministic output artifact: a hash chain over the fixed\n * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.\n */\nexport function computeAkashDemoArtifact(): string {\n let h = DEMO_SEED;\n for (let i = 0; i < DEMO_ROUNDS; i++) {\n h = sha256Hex(h);\n }\n return h;\n}\n\n/**\n * The canned Akash demo job. Deterministic; its specHash is pinned by a test because the\n * buyer journey depends on hash stability.\n */\nexport const akashDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no cloud-compute category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Run the canned Akash scripted batch job (a fixed hash-chain compute over a known \" +\n \"seed) on a deployment and return its output artifact. Acceptance is deterministic and \" +\n \"recomputed by the buyer: the job must complete, an output artifact must be present, and \" +\n \"the artifact must match the buyer's independent recompute; the worker's self-reported \" +\n \"artifact hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The scripted job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-artifact-present\",\n description: \"An output artifact is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-hash-match\",\n description:\n \"The output artifact matches the buyer's independent recompute of the scripted job.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: AKASH_DEMO_MARKER,\n seed: DEMO_SEED,\n rounds: DEMO_ROUNDS,\n acceptFloor: AKASH_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the correct\n * output artifact plus a (self-reported, buyer-ignored) artifactHash, as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of the expected\n * artifact.\n */\nexport function solveAkashDemo(): string {\n const artifact = computeAkashDemoArtifact();\n return canonicalize({\n job: AKASH_DEMO_MARKER,\n status: \"completed\",\n rounds: DEMO_ROUNDS,\n artifact,\n // Self-reported and deliberately ignored by the buyer's recompute.\n artifactHash: sha256Hex(artifact),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n artifact: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n const obj = parsed as { status?: unknown; artifact?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const artifact = typeof obj.artifact === \"string\" ? obj.artifact : null;\n return { status, artifact };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when the\n * deliverable satisfies all three criteria and 0 otherwise. It checks completion (status),\n * artifact presence, and hash match by RECOMPUTING the scripted job's output and comparing\n * the substantive artifact; it deliberately IGNORES any self-reported `artifactHash`, so\n * release can never be worker-controlled. Malformed or unparseable content scores 0 and\n * never throws.\n */\nexport function scoreAkashDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.artifact === null) {\n return 0;\n }\n return parsed.artifact === computeAkashDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) job produces a placeholder completion report so a fresh worker\n// returns a well-formed ServiceResult before a real Akash deployment is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"akash-generic\",\n status: \"completed\",\n artifact: null,\n note: \"reference stub - replace the runDeployment port with a real Akash deployment call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunDeployment: RunAkashDeployment = (spec) =>\n Promise.resolve(\n spec.metadata.demo === AKASH_DEMO_MARKER ? solveAkashDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build an Akash {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the\n * default ports; supply real ports for production use. The execute skeleton: swap the USDC\n * budget into AKT (internal, never surfaced), provision the deployment and collect the\n * output, then hash and pin. The recorded `ServiceResult` is currency-free (no AKT field).\n */\nexport function createAkashAdapter(config: AkashAdapterConfig = {}): ServiceAdapter {\n const capabilities = config.capabilities ?? [...AKASH_CAPABILITIES];\n const taskBudgetMicroUsdc = config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC;\n const swap = config.swap ?? defaultSwap;\n const runDeployment = config.runDeployment ?? defaultRunDeployment;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: AKASH_ADAPTER_ID,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into AKT (internal, never surfaced).\n const budgetAkt = await swap(taskBudgetMicroUsdc);\n // 2. Provision the Akash deployment (paid in AKT) and collect the deliverable.\n const content = await runDeployment(spec, budgetAkt);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: AKASH_ADAPTER_ID },\n };\n },\n };\n}\n","/**\n * Render Network ServiceAdapter: a SHIPPED, supported adapter for decentralized GPU\n * rendering (3D scenes, video frames, diffusion/inference jobs). A Worker Bot wraps a\n * Render Network job behind the `ServiceAdapter` interface: it swaps a per-task USDC\n * budget into RENDER internally, pays for the render job in RENDER, collects the\n * rendered output artifact, and returns a currency-free `ServiceResult`. The Buyer and\n * the escrow contract only ever see USDC; no RENDER-typed value crosses this boundary\n * into SDK core (ARCHITECTURE §3, §7; see ./render.type-test.ts for the compile-time\n * proof).\n *\n * Render is Solana-native with MINIMAL BRIDGING: RENDER is a Solana SPL token, so the\n * USDC->RENDER conversion is a same-chain DEX swap (e.g. Jupiter) with no cross-chain\n * bridge. This is the distinction from the Bittensor trio (gradients SN56, 404gen SN17,\n * lium SN51), whose TAO must be bridged off Solana to Bittensor. Because its token and\n * network differ, Render carries its own branded `Render` type and its own execute\n * skeleton and is deliberately NOT part of the shared `adapters/bittensor` core.\n *\n * No price feed lives in SDK core: the USDC->RENDER rate is an injectable `swap` port\n * defaulting to a deterministic fixed reference rate (see `defaultSwap`). A production\n * worker injects a real DEX route; SDK core embeds no live price feed. The swap,\n * render-job call, and pinning are injectable ports so the reference runs (and is\n * tested) without a live DEX, Render Network endpoint, or IPFS node.\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the rendered\n * frame). Whether the render is acceptable is decided by the BUYER's review.ts, which\n * independently RE-RENDERS the scripted demo scene and compares the substantive frame\n * (see `scoreRenderDemoDeliverable`). The worker never scores-for-release and never\n * releases, and its self-reported `frameHash` is never trusted (CLAUDE.md product\n * framing: the buyer is the judge).\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in RENDER (Render Network's Solana SPL token). Branded so it cannot\n * be assigned to or from a plain `number` by accident and (the point of the brand) so it\n * can never appear in a `ServiceResult` or the escrow submit path: those types have no\n * field of this type. RENDER exists ONLY inside this adapter module.\n */\nexport type Render = number & { readonly __brand: \"RENDER\" };\n\n/** Construct a {@link Render} amount from a plain number. Adapter-internal use only. */\nexport function renderAmount(amount: number): Render {\n return amount as Render;\n}\n\n/** Swap a microUSDC budget into RENDER. Real workers route this through a Solana DEX (e.g. Jupiter). */\nexport type UsdcToRenderSwap = (microUsdc: number) => Promise<Render>;\n\n/** Submit `spec`'s render job funded with `budget` RENDER; resolve with the raw rendered artifact. */\nexport type RunRenderJob = (spec: TaskSpec, budget: Render) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** Configuration and injectable ports for {@link createRenderAdapter}. */\nexport interface RenderAdapterConfig {\n /** Service identifier. Defaults to \"render\"; forms the adapter id. */\n service?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to {@link RENDER_CAPABILITIES}. */\n capabilities?: string[];\n /** microUSDC the worker allocates to a single task before converting to RENDER (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub (no live price feed). */\n swap?: UsdcToRenderSwap;\n /** Render-job port. Default: renders the canned demo scene; a deterministic placeholder otherwise. */\n runJob?: RunRenderJob;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// Stable id/capabilities. The adapter's own tests pin its runtime output to these\n// constants; at merge the main-owned kit seam test cross-checks them against the\n// registry descriptor (ADAPTER_DESCRIPTORS.render) so the descriptor and the shipped\n// adapter cannot drift apart (coordinated with the capability taxonomy).\nexport const RENDER_ADAPTER_ID = \"render\";\nexport const RENDER_CAPABILITIES = [\"3d-rendering\", \"video-rendering\", \"gpu-inference\"] as const;\n\nconst DEFAULT_SERVICE = \"render\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 15_000_000;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// Nominal reference rate: microUSDC -> RENDER. Only the stub swap cares about the exact\n// value; a production worker injects a real DEX route via the `swap` port.\nexport const REFERENCE_MICRO_USDC_PER_RENDER = 2_000_000;\n\n/** Default fixed-rate reference swap: a pure function of its input, no live price feed. */\nexport const defaultSwap: UsdcToRenderSwap = (microUsdc) =>\n Promise.resolve(renderAmount(microUsdc / REFERENCE_MICRO_USDC_PER_RENDER));\n\n/** Default deterministic `ipfs://` placeholder pin. */\nexport const defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n// ---------------------------------------------------------------------------\n// Canned demo job (BOT_KIT_PRD §6 / §13): a 5-minute scripted render job the buyer\n// template's journey hires this bot for. The \"render\" is a deterministic procedural\n// raster (a fixed shader over a fixed-size frame), so its output artifact is\n// reproducible: the buyer RE-RENDERS it independently (see scoreRenderDemoDeliverable)\n// and releases only when the job completed, a frame is present, and the frame matches.\n// The worker's self-reported frameHash is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default job stub recognizes it. */\nexport const RENDER_DEMO_MARKER = \"render-demo-v1\";\n\n/** The demo accept floor: frame-match is exact, so the buyer requires a full match. */\nexport const RENDER_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SCENE = \"render-demo-scene-v1\";\nconst DEMO_WIDTH = 16;\nconst DEMO_HEIGHT = 16;\n\n/**\n * The deterministic per-pixel shader for the demo scene: a fixed grayscale value in\n * [0, 255] for pixel (x, y). Pure and reproducible, so the buyer can re-render and\n * compare independently.\n */\nfunction shade(x: number, y: number): number {\n return (x * 53 + y * 97 + (x ^ y) * 29) & 0xff;\n}\n\n/**\n * Render the fixed demo scene into a grayscale raster and return its hex encoding.\n * Deterministic and cheap to recompute, so the buyer verifies the frame independently.\n */\nexport function computeRenderDemoArtifact(): string {\n const raster = Buffer.alloc(DEMO_WIDTH * DEMO_HEIGHT);\n let i = 0;\n for (let y = 0; y < DEMO_HEIGHT; y++) {\n for (let x = 0; x < DEMO_WIDTH; x++) {\n raster[i++] = shade(x, y);\n }\n }\n return raster.toString(\"hex\");\n}\n\n/**\n * The canned Render demo job. Deterministic; its specHash is pinned by a test because\n * the buyer journey depends on hash stability.\n */\nexport const renderDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"image_generation\",\n description:\n \"Render the canned demo scene (a fixed procedural frame) and return the rendered \" +\n \"frame. Acceptance is deterministic and recomputed by the buyer: the job must \" +\n \"complete, a rendered frame must be present, and the frame must match the buyer's \" +\n \"independent re-render; the worker's self-reported frame hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The render job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-frame-present\",\n description: \"A rendered frame is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-frame-match\",\n description: \"The rendered frame matches the buyer's independent re-render of the scene.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: RENDER_DEMO_MARKER,\n scene: DEMO_SCENE,\n width: DEMO_WIDTH,\n height: DEMO_HEIGHT,\n acceptFloor: RENDER_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the correct\n * rendered frame plus a (self-reported, buyer-ignored) frameHash, as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of the expected\n * artifact.\n */\nexport function solveRenderDemo(): string {\n const frame = computeRenderDemoArtifact();\n return canonicalize({\n job: RENDER_DEMO_MARKER,\n status: \"completed\",\n width: DEMO_WIDTH,\n height: DEMO_HEIGHT,\n frame,\n // Self-reported and deliberately ignored by the buyer's recompute.\n frameHash: sha256Hex(frame),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n frame: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as { status?: unknown; frame?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const frame = typeof obj.frame === \"string\" ? obj.frame : null;\n return { status, frame };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when\n * the deliverable satisfies all three criteria and 0 otherwise. It checks completion\n * (status), frame presence, and a frame match by RE-RENDERING the scripted scene and\n * comparing the substantive frame; it deliberately IGNORES any self-reported\n * `frameHash`, so release can never be worker-controlled. Malformed or\n * unparseable content scores 0 and never throws.\n */\nexport function scoreRenderDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.frame === null) {\n return 0;\n }\n return parsed.frame === computeRenderDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) render job produces a placeholder completion report so a fresh\n// worker returns a well-formed ServiceResult before a real Render Network job is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"render-generic\",\n status: \"completed\",\n frame: null,\n note: \"reference stub - replace the runJob port with a real Render Network job submission.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunJob: RunRenderJob = (spec) =>\n Promise.resolve(\n spec.metadata.demo === RENDER_DEMO_MARKER ? solveRenderDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a Render {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the\n * default ports; supply real ports for production use. The execute skeleton: swap the\n * USDC budget into RENDER (internal, same-chain, never surfaced), pay the render job in\n * RENDER and collect the frame, then hash and pin. The recorded `ServiceResult` is\n * currency-free (no RENDER field).\n */\nexport function createRenderAdapter(config: RenderAdapterConfig = {}): ServiceAdapter {\n const service = config.service ?? DEFAULT_SERVICE;\n const capabilities = config.capabilities ?? [...RENDER_CAPABILITIES];\n const taskBudgetMicroUsdc = config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC;\n const swap = config.swap ?? defaultSwap;\n const runJob = config.runJob ?? defaultRunJob;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: service,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into RENDER (internal, same-chain DEX; no bridge).\n const budgetRender = await swap(taskBudgetMicroUsdc);\n // 2. Pay for the render job in RENDER and collect the rendered frame.\n const content = await runJob(spec, budgetRender);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: service, network: \"render\" },\n };\n },\n };\n}\n","/**\n * Gensyn ServiceAdapter + REE-proof acceptance (Phase 8, P8.T4). Gensyn is a\n * network for VERIFIABLE compute: a worker runs a job in a Reproducible Execution\n * Environment (REE) and returns a proof that binds the task, the delivered output,\n * and a reproducible execution transcript. The novelty this task adds over the\n * Phase 6 adapters is buyer-side ACCEPTANCE by proof: the Buyer auto-releases iff\n * the REE proof verifies.\n *\n * The judgment is entirely BUYER-LAYER (this module, called by the buyer's bot),\n * exactly like `scoreGradientsDemoDeliverable` in the Gradients adapter. The\n * protocol still judges nothing: verification never enters the program or the\n * oracle (CLAUDE.md product framing). `zero-diff-guard.test.ts` pins that\n * packages/program and packages/oracle stay byte-for-byte unchanged.\n *\n * `verifyReeProof` is deliberately a BUYER recompute, mirroring the Gradients\n * pattern where the buyer re-derives the eval score rather than trusting the\n * worker's self-report: it re-runs the reproducible execution and checks the\n * worker's transcript hash against its own. A production Gensyn verifier would\n * replace the full recompute with Gensyn's interactive verification game over the\n * same `transcriptHash`; the acceptance contract (a proof binding spec, content,\n * and reproducible transcript) is unchanged.\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/** Stable adapter identity + EscroBots capability (locked by gensyn.test.ts). */\nexport const GENSYN_ADAPTER_ID = \"gensyn\";\nexport const GENSYN_CAPABILITIES = [\"verifiable-compute\"] as const;\n\n/** REE proof scheme tag. A verifier accepts only proofs carrying this exact scheme. */\nexport const GENSYN_REE_SCHEME = \"gensyn-ree-v1\";\n\n/** Marker on the demo spec's metadata so the default reproducible compute recognizes it. */\nexport const GENSYN_DEMO_MARKER = \"gensyn-ree-demo-v1\";\n\n/** The demo's fixed reproducible-execution parameters (a deterministic LCG walk). */\nexport const GENSYN_DEMO_SEED = 12345;\nexport const GENSYN_DEMO_STEPS = 16;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ---------------------------------------------------------------------------\n// Reproducible execution: the deterministic computation the REE proof attests to.\n// A fixed linear congruential generator walked `steps` times from `seed`; the\n// ordered states are the transcript, the final state is the result. Deterministic\n// from the spec alone, so the buyer can reproduce it and confirm the worker's\n// transcript hash (the essence of a Reproducible Execution Environment).\n// ---------------------------------------------------------------------------\n\nconst LCG_MULT = 1103515245n;\nconst LCG_INC = 12345n;\nconst LCG_MOD = 1n << 31n;\n\n/** The result of one reproducible execution: its transcript and final output. */\nexport interface ReeExecution {\n /** Seed the walk started from. */\n seed: number;\n /** Number of steps walked. */\n steps: number;\n /** Ordered per-step states (the execution transcript). */\n states: number[];\n /** Final state (the deliverable's numeric result). */\n result: number;\n}\n\n/** Run the reproducible compute for `spec`, deriving the transcript and result. */\nexport type ReproduceCompute = (spec: TaskSpec) => ReeExecution;\n\nfunction readComputeParams(spec: TaskSpec): { seed: number; steps: number } {\n const rawSeed = spec.metadata.seed;\n const rawSteps = spec.metadata.steps;\n const seed =\n typeof rawSeed === \"number\" && Number.isInteger(rawSeed) ? rawSeed : GENSYN_DEMO_SEED;\n const steps =\n typeof rawSteps === \"number\" && Number.isInteger(rawSteps) && rawSteps > 0\n ? rawSteps\n : GENSYN_DEMO_STEPS;\n return { seed, steps };\n}\n\n/**\n * The reference reproducible execution. Deterministic from `spec` (its seed/steps\n * come from `spec.metadata`, defaulting to the demo parameters), so both worker and\n * buyer derive the same transcript.\n */\nexport const reproduceGensynCompute: ReproduceCompute = (spec) => {\n const { seed, steps } = readComputeParams(spec);\n const states: number[] = [];\n let x = BigInt(seed) % LCG_MOD;\n if (x < 0n) {\n x += LCG_MOD;\n }\n for (let i = 0; i < steps; i++) {\n x = (LCG_MULT * x + LCG_INC) % LCG_MOD;\n states.push(Number(x));\n }\n return { seed, steps, states, result: states[states.length - 1] ?? seed };\n};\n\n/** Serialize a reproducible execution's output into the deliverable content. */\nexport function gensynDeliverable(exec: ReeExecution): string {\n return canonicalize({ result: exec.result, steps: exec.steps });\n}\n\n// ---------------------------------------------------------------------------\n// REE proof\n// ---------------------------------------------------------------------------\n\n/**\n * A Gensyn REE proof. Every field is a commitment the buyer re-derives:\n * `commitment` binds the whole tuple, `outputHash` binds the delivered content,\n * `specHash` binds the task asked, `transcriptHash` binds the reproducible run.\n */\nexport interface ReeProof {\n scheme: typeof GENSYN_REE_SCHEME;\n /** SHA-256 hex of the canonical task spec. */\n specHash: string;\n /** SHA-256 hex of the delivered content. */\n outputHash: string;\n /** Number of reproducible execution steps (positive integer). */\n steps: number;\n /** SHA-256 hex of the canonical execution transcript. */\n transcriptHash: string;\n /** SHA-256 hex binding scheme, specHash, outputHash, steps, and transcriptHash. */\n commitment: string;\n}\n\ntype ReeProofBase = Omit<ReeProof, \"commitment\">;\n\n/** The single canonical binding the commitment (and its verification) is computed over. */\nfunction commitmentOf(base: ReeProofBase): string {\n return sha256Hex(\n [base.scheme, base.specHash, base.outputHash, String(base.steps), base.transcriptHash].join(\n \"\\n\",\n ),\n );\n}\n\n/**\n * Build the REE proof a worker attaches to its deliverable. Not a trust anchor on\n * its own: `verifyReeProof` re-derives every field, so a proof only accepts when it\n * genuinely binds the content, spec, and a reproducible transcript.\n */\nexport function buildReeProof(\n spec: TaskSpec,\n exec: ReeExecution,\n content: string | Buffer,\n): ReeProof {\n const base: ReeProofBase = {\n scheme: GENSYN_REE_SCHEME,\n specHash: sha256Hex(canonicalize(spec)),\n outputHash: sha256Hex(content),\n steps: exec.steps,\n transcriptHash: sha256Hex(canonicalize(exec.states)),\n };\n return { ...base, commitment: commitmentOf(base) };\n}\n\n/** The verifier's verdict: a proof is either valid, or invalid/malformed with a reason. */\nexport interface ReeVerification {\n valid: boolean;\n /** Prefixed `malformed` (shape/structure) or `invalid` (a binding failed), or a pass note. */\n reason: string;\n}\n\n/** Inputs the buyer verifies a proof against: the task asked and the content received. */\nexport interface ReeVerifyContext {\n /** The task spec the buyer commissioned. */\n spec: TaskSpec;\n /** The deliverable content the buyer received (fetched from proofUri in production). */\n content: string | Buffer;\n /** The reproducible compute; defaults to the reference {@link reproduceGensynCompute}. */\n reproduce?: ReproduceCompute;\n}\n\nconst HEX_64 = /^[0-9a-f]{64}$/;\n\nfunction isHex64(v: unknown): v is string {\n return typeof v === \"string\" && HEX_64.test(v);\n}\n\nfunction malformed(reason: string): ReeVerification {\n return { valid: false, reason: `malformed: ${reason}` };\n}\n\nfunction invalid(reason: string): ReeVerification {\n return { valid: false, reason: `invalid: ${reason}` };\n}\n\n/**\n * The BUYER's verification of an REE proof (untrusted input from the worker). Returns\n * `valid: true` only when the proof is well-formed AND every binding holds: the\n * commitment is self-consistent, the committed output hash equals the delivered\n * content, the spec hash equals the commissioned task, and the transcript hash\n * matches the buyer's own reproduction of the execution. Never throws.\n */\nexport function verifyReeProof(proof: unknown, ctx: ReeVerifyContext): ReeVerification {\n if (typeof proof !== \"object\" || proof === null) {\n return malformed(\"proof is not an object\");\n }\n const p = proof as Record<string, unknown>;\n\n if (p.scheme !== GENSYN_REE_SCHEME) {\n return malformed(`scheme must be \"${GENSYN_REE_SCHEME}\"`);\n }\n if (!isHex64(p.specHash)) {\n return malformed(\"specHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.outputHash)) {\n return malformed(\"outputHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.transcriptHash)) {\n return malformed(\"transcriptHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.commitment)) {\n return malformed(\"commitment must be a 64-char lowercase hex string\");\n }\n if (typeof p.steps !== \"number\" || !Number.isInteger(p.steps) || p.steps <= 0) {\n return malformed(\"steps must be a positive integer\");\n }\n\n const base: ReeProofBase = {\n scheme: GENSYN_REE_SCHEME,\n specHash: p.specHash,\n outputHash: p.outputHash,\n steps: p.steps,\n transcriptHash: p.transcriptHash,\n };\n\n if (commitmentOf(base) !== p.commitment) {\n return invalid(\"commitment does not bind the proof fields (tampered)\");\n }\n if (sha256Hex(ctx.content) !== p.outputHash) {\n return invalid(\"outputHash does not match the delivered content\");\n }\n if (sha256Hex(canonicalize(ctx.spec)) !== p.specHash) {\n return invalid(\"specHash does not match the commissioned task spec\");\n }\n const exec = (ctx.reproduce ?? reproduceGensynCompute)(ctx.spec);\n if (p.steps !== exec.steps) {\n return invalid(\"steps does not match the reproduced execution\");\n }\n if (sha256Hex(canonicalize(exec.states)) !== p.transcriptHash) {\n return invalid(\"transcriptHash is not reproducible from the task spec\");\n }\n // The load-bearing acceptance check: the delivered content must be the ACTUAL output\n // of the reproduced execution, not merely something the worker hashed into a\n // self-consistent proof. Without this, a worker could attach a valid proof to\n // arbitrary content (its outputHash would still equal the delivered garbage) and\n // trigger auto-release. Binding outputHash to the buyer's own reproduced deliverable\n // (and, via the check above, to the delivered content) closes that forgery.\n if (sha256Hex(gensynDeliverable(exec)) !== p.outputHash) {\n return invalid(\"outputHash does not match the reproduced deliverable\");\n }\n\n return {\n valid: true,\n reason:\n \"REE proof verified: commitment, spec, transcript, and the reproduced deliverable all bind to the delivered content.\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Buyer-layer auto-release\n// ---------------------------------------------------------------------------\n\n/** What the buyer assembles to decide acceptance: the received content and the worker's proof. */\nexport interface GensynDeliverableBundle {\n /** The deliverable content the buyer received. */\n content: string | Buffer;\n /** The REE proof the worker attached (untrusted; verified before any release). */\n proof: unknown;\n}\n\n/** A buyer auto-release decision. `release: true` means \"call release_payment()\". */\nexport interface AutoReleaseDecision {\n release: boolean;\n reason: string;\n}\n\n/**\n * The buyer bot's auto-release decision for a Gensyn deliverable. Releases ONLY when\n * the REE proof verifies against the delivered content and the commissioned spec;\n * an invalid or malformed proof never releases. This is the whole T4 acceptance\n * mechanism, and it lives entirely at the buyer layer.\n */\nexport function gensynAutoRelease(\n bundle: GensynDeliverableBundle,\n ctx: { spec: TaskSpec; reproduce?: ReproduceCompute },\n): AutoReleaseDecision {\n const verdict = verifyReeProof(bundle.proof, {\n spec: ctx.spec,\n content: bundle.content,\n ...(ctx.reproduce !== undefined && { reproduce: ctx.reproduce }),\n });\n return { release: verdict.valid, reason: verdict.reason };\n}\n\n// ---------------------------------------------------------------------------\n// Adapter (worker side)\n// ---------------------------------------------------------------------------\n\n/** Configuration and injectable ports for {@link createGensynAdapter}. */\nexport interface GensynAdapterConfig {\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"verifiable-compute\"]`. */\n capabilities?: string[];\n /** The reproducible compute the worker runs. Default: the reference LCG walk. */\n runCompute?: ReproduceCompute;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: (content: string | Buffer) => Promise<string>;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** The canned demo job the buyer template's journey hires a Gensyn worker for. */\nexport const gensynDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"custom\",\n description:\n \"Run the reference reproducible compute (a fixed LCG walk from the seed in \" +\n \"metadata) and return its final result. Acceptance is a valid gensyn-ree-v1 REE \" +\n \"proof: the buyer recomputes the transcript and confirms the proof binds the \" +\n \"delivered content, this spec, and the reproducible execution. The worker's \" +\n \"self-reported result is never trusted on its own.\",\n acceptanceCriteria: [\n {\n id: \"ac-ree-proof\",\n description:\n \"A valid gensyn-ree-v1 proof binding the delivered content, this spec, and a reproducible transcript.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GENSYN_DEMO_MARKER,\n seed: GENSYN_DEMO_SEED,\n steps: GENSYN_DEMO_STEPS,\n },\n};\n\nconst defaultPin = (content: string | Buffer): Promise<string> =>\n Promise.resolve(`ipfs://gensyn-${sha256Hex(content).slice(0, 16)}`);\n\n/**\n * Build a Gensyn {@link ServiceAdapter}. `execute` runs the reproducible compute,\n * serializes the deliverable, and attaches an REE proof (in `metadata.reeProof`) the\n * buyer verifies with {@link verifyReeProof} / {@link gensynAutoRelease}. Passes\n * `assertServiceAdapterContract` with the default ports; supply real ports (a real\n * Gensyn job runner, a real pinner) for production.\n */\nexport function createGensynAdapter(config: GensynAdapterConfig = {}): ServiceAdapter {\n const runCompute = config.runCompute ?? reproduceGensynCompute;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n const capabilities = config.capabilities ?? [...GENSYN_CAPABILITIES];\n\n return {\n id: GENSYN_ADAPTER_ID,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n const exec = runCompute(spec);\n const content = gensynDeliverable(exec);\n const contentHash = sha256Hex(content);\n const proof = buildReeProof(spec, exec, content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: GENSYN_ADAPTER_ID, reeProof: proof },\n };\n },\n };\n}\n","/**\n * ZKML proof-verifier ServiceAdapter. A Worker Bot wraps a zk-verified\n * inference service: it runs the model, then attaches a proof that the delivered\n * output is the correct result of running a committed model on a committed input.\n * The proof travels on `ServiceResult.proofUri`; the Buyer configures auto-release\n * on proof validation. Same buyer-layer-only shape as every adapter -- the escrow\n * program and the oracle judge nothing (CLAUDE.md product framing): verification is\n * pure TypeScript that runs in the Buyer's bot, never on-chain and never in the\n * oracle (see zero-program-diff.test.ts).\n *\n * WHAT THE SHIPPED VERIFIER IS -- AND IS NOT. The default scheme (`escro-zkml-ref-v1`)\n * is a REFERENCE verifier with NO cryptographic soundness. Its tag is a plain keyless\n * hash of the public inputs (see `computeZkmlVerificationTag`) and `buildZkmlProof` is\n * exported, so ANY party can mint a proof that `verifyZkmlProof` accepts, over whatever\n * output it chooses and any model commitment. It exists to demonstrate the lifecycle\n * (proof shape, transport on `proofUri`, decode, and the buyer-side auto-release seam)\n * deterministically and with no external prover. It must NEVER be the sole gate on a\n * production release. A production ZKML buyer passes a REAL SNARK/STARK verifier to\n * `zkmlProofAutoRelease` (the `verify` option): a verifying key over the same public\n * inputs, which is where soundness actually lives.\n *\n * TWO DISCIPLINES THAT DO CARRY TO PRODUCTION. (1) The buyer RE-HASHES the artifact it\n * holds and requires `sha256(artifact)` equals the worker-submitted `contentHash`\n * before trusting anything (`zkmlProofAutoRelease`'s `fetchContent` port). The submitted\n * hash is the worker's claim, never trusted on its own -- the same discipline as the\n * buyer template's `evalThresholdReview` and the T0 harness. (2) Verification is\n * buyer-layer only: it runs in the Buyer's bot, never on-chain and never in the oracle\n * (see zero-program-diff.test.ts). RELEASE JUDGMENT IS THE BUYER'S: the adapter only\n * PRODUCES the deliverable and its proof; whether to release is `zkmlProofAutoRelease`\n * in the Buyer's review, never the worker and never the protocol.\n */\nimport { createHash } from \"crypto\";\n\nimport {\n canonicalize,\n type ReviewDeliverable,\n type ReviewPolicy,\n type ReviewResult,\n type TaskSpec,\n} from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/** Stable id/capabilities; locked against the EscroBots registry descriptor by a kit test at merge. */\nexport const ZKML_ADAPTER_ID = \"zkml\";\nexport const ZKML_CAPABILITIES = [\"zk-verified-inference\"] as const;\n\n/** Marker on the demo spec's metadata so the default inference port recognizes it. */\nexport const ZKML_DEMO_MARKER = \"zkml-demo-v1\";\n\n/** The reference proving scheme this verifier understands. Unknown schemes are malformed to it. */\nexport const ZKML_PROOF_SCHEME = \"escro-zkml-ref-v1\";\n\n/** Prefix marking an inline (self-contained) zkml proof URI: `zkml-proof:<base64url(json)>`. */\nexport const ZKML_PROOF_URI_PREFIX = \"zkml-proof:\";\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ── Proof shape ──────────────────────────────────────────────────────────────────\n\n/**\n * A ZKML proof: its public inputs plus a `verificationTag` binding them. In the\n * reference scheme the tag is recomputable (see {@link computeZkmlVerificationTag});\n * in a production scheme it is a SNARK/STARK checked against a verifying key over the\n * same public inputs.\n */\nexport interface ZkmlProof {\n /** Proving scheme identifier; the verifier only understands {@link ZKML_PROOF_SCHEME}. */\n scheme: string;\n /** Commitment to the model that produced the output (e.g. a weights hash). */\n modelCommitment: string;\n /** Commitment to the input the model was run on. */\n inputCommitment: string;\n /** SHA-256 hex of the delivered output; binds the proof to a specific deliverable. */\n outputHash: string;\n /** Binding tag over the public inputs (reference: recomputable; production: a SNARK). */\n verificationTag: string;\n}\n\n/** The public inputs a proof commits to (everything except the tag itself). */\ntype ZkmlPublicInputs = Omit<ZkmlProof, \"verificationTag\">;\n\n/** Recompute the reference binding tag over a proof's public inputs. Deterministic. */\nexport function computeZkmlVerificationTag(publicInputs: ZkmlPublicInputs): string {\n return sha256Hex(\n canonicalize({\n scheme: publicInputs.scheme,\n modelCommitment: publicInputs.modelCommitment,\n inputCommitment: publicInputs.inputCommitment,\n outputHash: publicInputs.outputHash,\n }),\n );\n}\n\n/** Build a well-formed reference proof binding the given public inputs. */\nexport function buildZkmlProof(args: {\n scheme?: string;\n modelCommitment: string;\n inputCommitment: string;\n outputHash: string;\n}): ZkmlProof {\n const publicInputs: ZkmlPublicInputs = {\n scheme: args.scheme ?? ZKML_PROOF_SCHEME,\n modelCommitment: args.modelCommitment,\n inputCommitment: args.inputCommitment,\n outputHash: args.outputHash,\n };\n return { ...publicInputs, verificationTag: computeZkmlVerificationTag(publicInputs) };\n}\n\n/** Encode a proof as a self-contained inline proof URI. */\nexport function encodeZkmlProofUri(proof: ZkmlProof): string {\n return ZKML_PROOF_URI_PREFIX + Buffer.from(canonicalize(proof), \"utf8\").toString(\"base64url\");\n}\n\nfunction isProofShaped(value: unknown): value is ZkmlProof {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const p = value as Record<string, unknown>;\n return (\n typeof p.scheme === \"string\" &&\n typeof p.modelCommitment === \"string\" &&\n typeof p.inputCommitment === \"string\" &&\n typeof p.outputHash === \"string\" &&\n typeof p.verificationTag === \"string\"\n );\n}\n\n/**\n * Decode an inline zkml proof URI back to a {@link ZkmlProof}. Returns null for any\n * URI that is not an inline zkml proof or does not decode to the proof shape (a\n * pinned `ipfs://`/`ar://` proof is fetched by the caller, then passed to\n * {@link verifyZkmlProof} directly).\n */\nexport function decodeZkmlProofUri(uri: string): ZkmlProof | null {\n if (!uri.startsWith(ZKML_PROOF_URI_PREFIX)) {\n return null;\n }\n const encoded = uri.slice(ZKML_PROOF_URI_PREFIX.length);\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n return isProofShaped(parsed) ? parsed : null;\n}\n\n// ── Verification ─────────────────────────────────────────────────────────────────\n\n/**\n * The outcome of verifying a proof. `malformed` = the verifier cannot understand the\n * proof (missing/wrong-typed fields, unsupported scheme, undecodable URI); `invalid`\n * = a well-formed proof that fails verification (tag does not recompute, or attests a\n * different output/model than expected).\n */\nexport type ZkmlVerification =\n | { valid: true }\n | { valid: false; category: \"invalid\" | \"malformed\"; reason: string };\n\n/** What the Buyer expects the proof to attest to. */\nexport interface ZkmlExpectation {\n /** The submitted deliverable's contentHash; the proof's outputHash must equal it. */\n contentHash: string;\n /** When set, the proof's modelCommitment must equal it (pin to a specific model). */\n modelCommitment?: string;\n}\n\n/**\n * Verify a decoded proof against the Buyer's expectation. NOTE: this is the REFERENCE\n * verifier and is NOT cryptographically sound -- the tag is a keyless hash, so a `valid`\n * result means only that the proof is internally consistent and bound to\n * `expected.contentHash`, not that a trustworthy party produced it. Pass a real verifier\n * to {@link zkmlProofAutoRelease} for production. `malformed` = an unusable proof;\n * `invalid` = a usable proof that fails the checks.\n */\nexport function verifyZkmlProof(proof: unknown, expected: ZkmlExpectation): ZkmlVerification {\n if (!isProofShaped(proof)) {\n return { valid: false, category: \"malformed\", reason: \"proof is missing required fields\" };\n }\n if (proof.scheme !== ZKML_PROOF_SCHEME) {\n return {\n valid: false,\n category: \"malformed\",\n reason: `unsupported proof scheme \"${proof.scheme}\"`,\n };\n }\n if (proof.verificationTag !== computeZkmlVerificationTag(proof)) {\n return {\n valid: false,\n category: \"invalid\",\n reason:\n \"verification tag does not recompute (public inputs altered after the tag was computed)\",\n };\n }\n if (proof.outputHash !== expected.contentHash) {\n return {\n valid: false,\n category: \"invalid\",\n reason: \"proof attests a different output than the submitted deliverable\",\n };\n }\n if (\n expected.modelCommitment !== undefined &&\n proof.modelCommitment !== expected.modelCommitment\n ) {\n return { valid: false, category: \"invalid\", reason: \"proof attests a different model\" };\n }\n return { valid: true };\n}\n\n/** Decode an inline proof URI (or reject a missing/foreign one) and verify it. */\nexport function verifyZkmlProofUri(\n uri: string | null | undefined,\n expected: ZkmlExpectation,\n): ZkmlVerification {\n if (typeof uri !== \"string\" || uri === \"\") {\n return { valid: false, category: \"malformed\", reason: \"no proof URI attached\" };\n }\n const proof = decodeZkmlProofUri(uri);\n if (proof === null) {\n return {\n valid: false,\n category: \"malformed\",\n reason: \"proof URI is not a decodable inline zkml proof\",\n };\n }\n return verifyZkmlProof(proof, expected);\n}\n\n// ── Buyer-layer auto-release predicate ───────────────────────────────────────────\n\n/** The submitted deliverable as the Buyer's review reads it off the escrow read model. */\nexport type ZkmlDeliverable = ReviewDeliverable;\n\n/** A release decision: release, and if not, whether to contest via dispute. */\nexport type ZkmlReviewResult = ReviewResult;\n\n/** A named release policy the Buyer's review wires in; `evaluate` may be sync or async. */\nexport type ZkmlReviewPolicy = ReviewPolicy;\n\n/** Options for {@link zkmlProofAutoRelease}. */\nexport interface ZkmlProofAutoReleaseOptions {\n /**\n * Fetch the ACTUAL delivered artifact so the predicate can re-hash it. Integrity comes\n * from the buyer recomputing `sha256(artifact)` and requiring it equals the worker-\n * submitted `contentHash` -- never from trusting the submitted hash (mirror of the\n * buyer template's `evalThresholdReview`). Required: without the artifact the predicate\n * would be trusting a worker-chosen number.\n */\n fetchContent: (deliverable: ZkmlDeliverable) => Promise<string | Buffer> | string | Buffer;\n /** When set, the proof's modelCommitment must equal it (pin to a specific model). */\n modelCommitment?: string;\n /**\n * The proof verifier. DEFAULT is {@link verifyZkmlProof}, the reference verifier, which\n * is NOT cryptographically sound. A production buyer MUST pass a real SNARK/STARK\n * verifier here; the default is for demos only.\n */\n verify?: (proof: ZkmlProof, expected: ZkmlExpectation) => ZkmlVerification;\n /**\n * Resolve a non-inline (pinned) proof URI to a proof. Default: only inline\n * `zkml-proof:` URIs are understood; a pinned `ipfs://` proof needs this port.\n */\n fetchProof?: (uri: string) => Promise<ZkmlProof | null> | ZkmlProof | null;\n}\n\nasync function resolveZkmlProof(\n uri: string | null,\n fetchProof?: (uri: string) => Promise<ZkmlProof | null> | ZkmlProof | null,\n): Promise<ZkmlProof | null> {\n if (typeof uri !== \"string\" || uri === \"\") {\n return null;\n }\n if (uri.startsWith(ZKML_PROOF_URI_PREFIX)) {\n return decodeZkmlProofUri(uri);\n }\n return fetchProof ? await fetchProof(uri) : null;\n}\n\n/**\n * Buyer-layer auto-release predicate for zk-verified jobs. RELEASE only when BOTH hold:\n * (1) the delivered artifact re-hashes to the worker-submitted `contentHash` (fetched via\n * `fetchContent`, never trusted), and (2) the attached proof verifies against that buyer-\n * recomputed hash (and the pinned model, when given). Otherwise DISPUTE. Disputing rather\n * than holding is deliberate -- a held SUBMITTED escrow is auto-released to the worker by\n * the 24h protocol timeout, so a buyer who required a proof contests a missing/invalid one\n * instead of letting it time out to release. This is the Buyer's judgment, not the\n * protocol's. Soundness of step (2) lives in the `verify` option; the default reference\n * verifier is a demo and proves nothing on its own. A port that throws (e.g.\n * `fetchContent` failing to retrieve the artifact) PROPAGATES: a transient infra failure\n * is not a verdict, so the caller retries it -- it is never silently converted into a\n * dispute.\n */\nexport function zkmlProofAutoRelease(opts: ZkmlProofAutoReleaseOptions): ZkmlReviewPolicy {\n const verify = opts.verify ?? verifyZkmlProof;\n return {\n name: \"zkml-proof-auto-release\",\n async evaluate(d: ZkmlDeliverable): Promise<ZkmlReviewResult> {\n const recomputed = sha256Hex(await opts.fetchContent(d));\n if (recomputed !== d.contentHash) {\n return {\n accept: false,\n dispute: true,\n reason:\n \"delivered artifact does not hash to the submitted contentHash (tampered or wrong)\",\n };\n }\n const proof = await resolveZkmlProof(d.proofUri, opts.fetchProof);\n if (proof === null) {\n return { accept: false, dispute: true, reason: \"no decodable zkml proof attached\" };\n }\n const verdict = verify(proof, {\n contentHash: recomputed,\n ...(opts.modelCommitment !== undefined && { modelCommitment: opts.modelCommitment }),\n });\n if (verdict.valid) {\n return {\n accept: true,\n dispute: false,\n reason: \"zkml proof verified against the re-hashed deliverable\",\n };\n }\n return {\n accept: false,\n dispute: true,\n reason: `zkml proof ${verdict.category}: ${verdict.reason}`,\n };\n },\n };\n}\n\n// ── Adapter ──────────────────────────────────────────────────────────────────────\n\n/** What an inference run yields: the output plus the commitments the proof binds. */\nexport interface ZkmlInferenceOutput {\n /** The deliverable content. */\n content: string;\n /** Commitment to the model that produced `content`. */\n modelCommitment: string;\n /** Commitment to the input the model was run on. */\n inputCommitment: string;\n}\n\n/** Configuration and injectable ports for {@link createZkmlAdapter}. */\nexport interface ZkmlAdapterConfig {\n /** Adapter id. Defaults to `\"zkml\"`. */\n id?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"zk-verified-inference\"]`. */\n capabilities?: string[];\n /** Inference port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n runInference?: (spec: TaskSpec) => Promise<ZkmlInferenceOutput> | ZkmlInferenceOutput;\n /** Proving port. Default: builds a reference proof binding the output to its commitments. */\n prove?: (args: {\n spec: TaskSpec;\n output: ZkmlInferenceOutput;\n outputHash: string;\n }) => Promise<ZkmlProof> | ZkmlProof;\n /** Pinning port. Default: a self-contained inline proof URI. A production worker pins the proof. */\n pin?: (proof: ZkmlProof) => Promise<string> | string;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/**\n * The canned zk-verified-inference demo job (BOT_KIT_PRD §6 / §13): a deterministic\n * classification the buyer template's zero-config journey hires this bot for.\n * Acceptance is machine-checkable by the buyer via {@link zkmlProofAutoRelease}.\n */\nexport const zkmlDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"custom\",\n description:\n \"Run the canned zk-verified inference demo: classify the fixed demo input and \" +\n \"attach a proof that the output is the correct result of the committed model on \" +\n \"the committed input. Acceptance is deterministic and recomputed by the buyer: the \" +\n \"attached proof must verify against the submitted deliverable's contentHash.\",\n acceptanceCriteria: [\n {\n id: \"ac-proof-verifies\",\n description:\n \"The attached proof verifies against the submitted deliverable's contentHash, recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: { demo: ZKML_DEMO_MARKER },\n};\n\n/** Commitment to the demo model; deterministic so the demo journey settles with zero config. */\nconst DEMO_MODEL_COMMITMENT = sha256Hex(\"zkml-demo-classifier-v1\");\n/** Commitment to the demo input. */\nconst DEMO_INPUT_COMMITMENT = sha256Hex(\"zkml-demo-input-v1\");\n\n/**\n * The reference solution to the demo job: the classifier's output as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of truth.\n */\nexport function solveZkmlDemo(): string {\n return canonicalize({\n model: \"zkml-demo-classifier-v1\",\n output: { label: \"cat\", confidence: 0.98 },\n });\n}\n\nfunction referencePlaceholderOutput(spec: TaskSpec): ZkmlInferenceOutput {\n return {\n content: canonicalize({\n note: \"reference stub - replace the runInference port with a real zk-verified inference call.\",\n taskType: spec.taskType,\n }),\n modelCommitment: sha256Hex(\"zkml-reference-stub-model\"),\n inputCommitment: sha256Hex(canonicalize(spec)),\n };\n}\n\nconst defaultRunInference = (spec: TaskSpec): ZkmlInferenceOutput =>\n spec.metadata.demo === ZKML_DEMO_MARKER\n ? {\n content: solveZkmlDemo(),\n modelCommitment: DEMO_MODEL_COMMITMENT,\n inputCommitment: DEMO_INPUT_COMMITMENT,\n }\n : referencePlaceholderOutput(spec);\n\n/**\n * Build a ZKML {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the\n * default ports and, out of the box, produces a demo deliverable whose proof verifies\n * under {@link zkmlProofAutoRelease}. Supply real ports (a genuine inference call, a\n * real prover, a pin to IPFS/Arweave) for production use.\n */\nexport function createZkmlAdapter(config: ZkmlAdapterConfig = {}): ServiceAdapter {\n const id = config.id ?? ZKML_ADAPTER_ID;\n const capabilities = config.capabilities ?? [...ZKML_CAPABILITIES];\n const runInference = config.runInference ?? defaultRunInference;\n const prove =\n config.prove ??\n ((args: { output: ZkmlInferenceOutput; outputHash: string }): ZkmlProof =>\n buildZkmlProof({\n modelCommitment: args.output.modelCommitment,\n inputCommitment: args.output.inputCommitment,\n outputHash: args.outputHash,\n }));\n const pin = config.pin ?? ((proof: ZkmlProof): string => encodeZkmlProofUri(proof));\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id,\n capabilities,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n const output = await runInference(spec);\n const contentHash = sha256Hex(output.content);\n const proof = await prove({ spec, output, outputHash: contentHash });\n const proofUri = await pin(proof);\n return {\n content: output.content,\n contentHash,\n proofUri,\n metadata: {\n adapterId: id,\n scheme: proof.scheme,\n modelCommitment: proof.modelCommitment,\n },\n };\n },\n healthCheck(): Promise<boolean> {\n return checkHealth();\n },\n };\n}\n"],"mappings":"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","names":["Connection","PublicKey","nacl","bs58","EscrowState","bs58","nacl","retryAfterMs","body","createHash","PublicKey","bs58","byte","bs58","createHash","PublicKey","sleep","Connection","PublicKey","retryAfterMs","createHash","createHash","createHash","sha256Hex","spec","spec","createHash","sha256Hex","createHash","referencePlaceholder","spec","defaultPin","DEFAULT_SUBNET","DEFAULT_TASK_BUDGET_MICRO_USDC","referencePlaceholder","spec","defaultCallSubnet","DEFAULT_SUBNET","DEFAULT_TASK_BUDGET_MICRO_USDC","sha256Hex","parseDemoDeliverable","referencePlaceholder","spec","createHash","sha256Hex","createHash","DEFAULT_TASK_BUDGET_MICRO_USDC","defaultSwap","defaultPin","DEMO_SEED","DEMO_ROUNDS","parseDemoDeliverable","referencePlaceholder","spec","createHash","DEFAULT_SERVICE","DEFAULT_TASK_BUDGET_MICRO_USDC","sha256Hex","createHash","defaultSwap","defaultPin","parseDemoDeliverable","referencePlaceholder","spec","defaultRunJob","createHash","sha256Hex","createHash","spec","defaultPin","createHash","sha256Hex","createHash","spec"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../../shared/src/types/escrow.ts","../../shared/src/types/bots.ts","../../shared/src/config.ts","../../shared/src/utils/text.ts","../../shared/src/utils/canonicalize.ts","../../shared/src/utils/printable.ts","../../shared/src/utils/secret-scan.ts","../../shared/src/utils/index.ts","../../shared/src/rpc-redact.ts","../../shared/src/auth.ts","../../shared/src/bot-descriptor.ts","../../shared/src/instructions.ts","../../shared/src/instruction-args.ts","../../shared/src/pda.ts","../../shared/src/accounts.ts","../src/errors.ts","../src/public-key.ts","../src/api.ts","../src/payments.ts","../src/poll.ts","../src/spend-cap.ts","../src/x402/accept.ts","../src/chain-read.ts","../../shared/src/chain/events.ts","../../shared/src/config.ts","../../shared/src/chain/logs.ts","../../shared/src/chain/transaction.ts","../../shared/src/instructions.ts","../../shared/src/utils/text.ts","../../shared/src/chain/storable.ts","../../shared/src/chain/transaction-version.ts","../src/x402/errors.ts","../src/x402/extension.ts","../src/x402/signer.ts","../src/solana.ts","../src/x402/exact.ts","../src/x402/fund.ts","../src/x402/buyer-signature.ts","../src/x402/pinned-request.ts","../src/x402/headers.ts","../src/x402/pay.ts","../src/predicates/core.ts","../src/predicates/attestation-valid.ts","../src/predicates/ci-check.ts","../src/predicates/file-format.ts","../src/predicates/hash.ts","../src/predicates/json-schema.ts","../src/predicates/llm-rubric.ts","../src/predicates/period-sla.ts","../src/predicates/pod-receipt.ts","../src/predicates/tests-pass.ts","../src/predicates/index.ts","../src/adapter.ts","../src/adapter-contract.ts","../src/adapters/bittensor/index.ts","../src/adapters/gradients/index.ts","../src/adapters/ridges/index.ts","../src/adapters/404gen/index.ts","../src/adapters/lium/index.ts","../src/adapters/akash/index.ts","../src/adapters/render/index.ts","../src/adapters/gensyn/index.ts","../src/adapters/zkml/index.ts","../src/pay-guards.ts","../src/x402/bazaar.ts","../src/x402/exact-accept.ts","../src/x402/facilitator.ts","../src/x402/verify.ts"],"sourcesContent":["import { Connection, PublicKey, SendTransactionError } from \"@solana/web3.js\";\nimport {\n computeTaskSpecHash,\n disputeReasonError,\n escrowFee,\n getCaip2Network,\n isSafeUrl,\n verifyBotDescriptorSignature,\n} from \"@escro/shared\";\nimport type {\n EscrowAccount,\n EscrowErrorCode,\n EscrowState,\n ProtocolStats,\n SolanaCluster,\n} from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\nimport type { ServedWalletReputation } from \"@escro/reputation\";\nimport type {\n CreateEscrowParams,\n CreateEscrowResult,\n EscroOptions,\n ListOptions,\n PaginatedResult,\n PollOptions,\n RaiseDisputeParams,\n ReleasePaymentOutcome,\n ReleaseWithPredicateOutcome,\n SendOptions,\n SpendCap,\n SubmitDeliverableParams,\n WorkerCandidate,\n X402SpendCap,\n} from \"./types.js\";\nimport { ApiClient } from \"./api.js\";\nimport { EscroConfirmError, EscroError, EscrowNotFoundError, attachToError } from \"./errors.js\";\nimport { EscrowPaymentRouter } from \"./payments.js\";\nimport type { PayParams, PaymentResult, PaymentRouter } from \"./payments.js\";\nimport { pollUntil } from \"./poll.js\";\nimport { assertPublicKey } from \"./public-key.js\";\nimport { payOver402 } from \"./x402/pay.js\";\nimport {\n SPEND_CAP_ERROR_CODES,\n admit,\n assertWithinSpendCap,\n boundedRead,\n dropFailed,\n dropPending,\n isMicroUsdc,\n outstandingFromAnswer,\n pendingMicroUsdc,\n recordSent,\n walletLedger,\n type WalletLedger,\n} from \"./spend-cap.js\";\nimport {\n buildReleasePaymentTx,\n fetchPlatformConfig,\n resolveProgramId,\n signAndSend,\n type ExpectedTransaction,\n} from \"./solana.js\";\nimport { ChainReadError, decodeEscrowAccount } from \"./chain-read.js\";\nimport { predicateMemo, type DecisionJob, type PredicateResult } from \"./predicates/index.js\";\n\n// How long {@link Escro.confirm} keeps retrying a not-yet-visible transaction.\nconst CONFIRM_WINDOW_MS = 30_000;\nconst CONFIRM_FIRST_DELAY_MS = 500;\nconst CONFIRM_MAX_DELAY_MS = 4_000;\n// Codes worth retrying: the transaction is not visible yet, the RPC failed, a\n// gateway answered without a server code (502/503/504 from the load balancer),\n// or a rate limit (confirm is idempotent).\nconst RETRYABLE_CONFIRM_CODES = [\n \"TX_NOT_FOUND\",\n \"RPC_UNAVAILABLE\",\n \"HTTP_502\",\n \"HTTP_503\",\n \"HTTP_504\",\n \"RATE_LIMITED\",\n \"HTTP_429\",\n] as const;\n\nfunction isRetryableConfirmCode(code: string): boolean {\n return (RETRYABLE_CONFIRM_CODES as readonly string[]).includes(code);\n}\n\n// A release the API's RPC cannot yet see as settled is refused, retryable.\nfunction isRetryableReleaseCode(code: string): boolean {\n return code === (\"ESCROW_NOT_SETTLED\" satisfies EscrowErrorCode) || isRetryableConfirmCode(code);\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n// Evidence that a sent create never took effect on chain, so its deposit is not in flight: the\n// RPC refused it for a reason other than its having been processed already, or it landed and\n// failed at execution. Anything else after the send (a transport error, a confirmation timeout,\n// \"already processed\") may have landed, so the deposit stays counted.\nfunction neverLanded(err: unknown): boolean {\n if (err instanceof SendTransactionError) {\n return !/already been processed/i.test(err.transactionError.message);\n }\n return err instanceof EscroError && err.code === (\"TX_FAILED\" satisfies EscrowErrorCode);\n}\n\nexport class Escro {\n private readonly connection: Connection;\n private readonly api: ApiClient;\n private readonly options: EscroOptions;\n private readonly cluster: SolanaCluster;\n private readonly router: PaymentRouter = new EscrowPaymentRouter();\n private readonly spendCap: Readonly<SpendCap> | undefined;\n private readonly x402SpendCap: Readonly<X402SpendCap> | undefined;\n\n constructor(options: EscroOptions) {\n const cap = options.spendCap;\n if (cap !== undefined && !isMicroUsdc(cap.maxOutstandingMicroUsdc)) {\n throw new EscroError(\n `spendCap.maxOutstandingMicroUsdc must be a whole, non-negative micro-USDC amount: ${String(cap.maxOutstandingMicroUsdc)}`,\n \"VALIDATION_ERROR\",\n );\n }\n this.spendCap =\n cap === undefined\n ? undefined\n : Object.freeze({\n maxOutstandingMicroUsdc: cap.maxOutstandingMicroUsdc,\n ...(cap.outstanding !== undefined && { outstanding: cap.outstanding.bind(cap) }),\n });\n const x402Cap = options.x402SpendCap;\n if (x402Cap !== undefined && !isMicroUsdc(x402Cap.maxMicroUsdc)) {\n throw new EscroError(\n `x402SpendCap.maxMicroUsdc must be a whole, non-negative micro-USDC amount: ${String(x402Cap.maxMicroUsdc)}`,\n \"VALIDATION_ERROR\",\n );\n }\n this.x402SpendCap =\n x402Cap === undefined\n ? undefined\n : Object.freeze({\n maxMicroUsdc: x402Cap.maxMicroUsdc,\n ...(x402Cap.spent !== undefined && { spent: x402Cap.spent.bind(x402Cap) }),\n });\n this.options = options;\n this.cluster = options.cluster;\n this.connection = new Connection(options.rpcUrl, \"confirmed\");\n this.api = new ApiClient(options.apiUrl, options.wallet);\n }\n\n /**\n * Create a new escrow: registers with the API, signs and submits the\n * on-chain `create_escrow` transaction, then confirms it with the API.\n * Before any request it refuses (`VALIDATION_ERROR`) an `assignedWorker` that is not a\n * base-58 public key or an `amountUsdc` that is not a positive whole number and, on\n * `\"mainnet\"`, a client constructed without the `spendCap` option (`SPEND_CAP_REQUIRED`).\n * With a `spendCap` it refuses (`SPEND_CAP_EXCEEDED`), before the create is sent, a create\n * whose deposit would pass the cap; see {@link EscroOptions.spendCap}. With\n * `{ wait: false }` it returns once the create is sent; see {@link SendOptions.wait}.\n * An error thrown after the transaction was handed to the RPC, unless it shows the transaction\n * never took effect, is the original error with two own string properties set, `escrowPda` and\n * `signature`: the create may have landed, and those name it. A rejection that is not an `Error`\n * becomes a new `Error` carrying the two properties, with the original value as its `cause`.\n *\n * @returns `{ escrowId, escrowPda, signature }`; use `escrowPda` for all subsequent calls.\n */\n async createEscrow(\n params: CreateEscrowParams,\n options?: SendOptions,\n ): Promise<CreateEscrowResult> {\n const wait = options?.wait ?? true;\n if (!isCanonicalPubkey(params.assignedWorker)) {\n throw new EscroError(\n `assignedWorker must be a base-58 public key: ${JSON.stringify(params.assignedWorker)}`,\n \"VALIDATION_ERROR\",\n );\n }\n if (!Number.isSafeInteger(params.amountUsdc) || params.amountUsdc <= 0) {\n throw new EscroError(\n `amountUsdc must be a positive whole micro-USDC amount: ${String(params.amountUsdc)}`,\n \"VALIDATION_ERROR\",\n );\n }\n const cap = this.spendCap;\n if (cap === undefined && this.cluster === \"mainnet\") {\n throw new EscroError(\n \"createEscrow on mainnet needs a spend cap: construct Escro with the spendCap option.\",\n SPEND_CAP_ERROR_CODES.required,\n );\n }\n const wallet = this.options.wallet.publicKey.toBase58();\n const { escrowId, escrowPda, unsignedTx } =\n cap === undefined\n ? await this.api.createEscrow(params)\n : await this.admitCreate(cap, wallet, params);\n // Set once the transaction is handed to the RPC: a failure before then holds nothing.\n let sent = false as boolean;\n let signature: string;\n try {\n signature = await this.send(\n unsignedTx,\n {\n name: \"create_escrow\",\n escrowPda,\n taskId: escrowId,\n amount: BigInt(params.amountUsdc),\n deadline: BigInt(params.deadlineUnix),\n specHash: computeTaskSpecHash(params.taskSpec),\n assignedWorker: params.assignedWorker,\n },\n () => {\n sent = true;\n },\n wait,\n );\n } catch (err) {\n if (!sent || neverLanded(err)) dropPending(this.cluster, wallet, escrowPda);\n else attachToError(err, \"escrowPda\", escrowPda);\n throw err;\n }\n recordSent(this.cluster, wallet, escrowPda, signature);\n if (wait) await this.confirm(escrowPda, signature);\n return { escrowId, escrowPda, signature };\n }\n\n /**\n * Release payment to the worker. Buyer must be the wallet in the constructor.\n * Builds and submits the `release_payment` on-chain tx FIRST (the chain is the\n * source of truth), then has the API record it, retrying as\n * {@link Escro.releasePaymentWithOutcome} does. Use that method to see whether the\n * API recorded the release. With `{ wait: false }` it returns once the release is sent and\n * asks the API to record nothing; see {@link SendOptions.wait}.\n *\n * @returns Solana transaction signature.\n */\n async releasePayment(address: string, options?: SendOptions): Promise<string> {\n if (options?.wait === false) return this.sendRelease(address, false);\n const { signature } = await this.releasePaymentWithOutcome(address);\n return signature;\n }\n\n /**\n * {@link Escro.releasePayment}, reporting whether the API recorded the release.\n * `ESCROW_NOT_SETTLED` (the API's RPC does not yet show the escrow closed), the codes\n * {@link Escro.confirm} retries and a network failure are retried for about 30 s. A\n * failed record never throws: the release already landed, so the signature is returned\n * with `confirm.landed: false` and an `EscroConfirmError` (the API's code, or\n * `NETWORK_ERROR` when the last call never reached it). A release that failed at\n * execution on chain throws an {@link EscroError} with code `TX_FAILED`, and the API is\n * never asked to record it.\n *\n * @returns `{ signature, confirm }`.\n */\n async releasePaymentWithOutcome(address: string): Promise<ReleasePaymentOutcome> {\n return this.release(address);\n }\n\n /**\n * Release payment on a passing predicate result, with its decision memo\n * (`escro:predicate:<name>:pass:<record hash>`) as one SPL Memo instruction, last, in the\n * buyer's own `release_payment`. Before anything is signed it refuses, with an\n * {@link EscroError}, an `address` that is not a base-58 public key (`VALIDATION_ERROR`, before\n * any read), then a result whose decision is not `pass` (`PREDICATE_NOT_PASSED`), a record the\n * extension refuses, a record with no `job` included (`PREDICATE_RECORD`), then a record whose\n * `job` names another network (`PREDICATE_NETWORK_MISMATCH`), another program\n * (`PREDICATE_PROGRAM_MISMATCH`) or another escrow (`PREDICATE_JOB_MISMATCH`) than this\n * client's cluster and `address`, all before any read; and, from the escrow's account read on\n * chain, an escrow that is not on chain, not owned by the Escro program, not SUBMITTED, or whose\n * committed `deliverable_hash` is not the record's `deliverableHash`\n * (`PREDICATE_DELIVERABLE_MISMATCH`). The memo is computed from `result.record`, never taken\n * from `result.memo`. The release then runs and is recorded as\n * {@link Escro.releasePaymentWithOutcome} does.\n *\n * @returns `{ signature, confirm, memo }`.\n */\n async releaseWithPredicate(\n address: string,\n result: PredicateResult,\n ): Promise<ReleaseWithPredicateOutcome> {\n assertPublicKey(\"address\", address);\n const { record } = result;\n if (record.decision !== \"pass\") {\n throw new EscroError(\n `The predicate decided ${record.decision} for escrow ${address}; nothing is released`,\n \"PREDICATE_NOT_PASSED\",\n );\n }\n const memo = predicateMemo(record);\n this.assertOwnJob(address, record.job);\n await this.assertCommitted(address, record.deliverableHash);\n return { ...(await this.release(address, memo)), memo };\n }\n\n // A record decides one job: a record for another network, program or escrow is a replay.\n private assertOwnJob(address: string, job: DecisionJob): void {\n const refuse = (member: string, own: string, named: string, code: string): void => {\n if (named !== own) {\n throw new EscroError(\n `The record's job.${member} ${named} is not ${own}, the ${member} of escrow ${address} on this client; nothing is released`,\n code,\n );\n }\n };\n refuse(\"network\", getCaip2Network(this.cluster), job.network, \"PREDICATE_NETWORK_MISMATCH\");\n refuse(\n \"program\",\n resolveProgramId(this.cluster).toBase58(),\n job.program,\n \"PREDICATE_PROGRAM_MISMATCH\",\n );\n refuse(\"id\", address, job.id, \"PREDICATE_JOB_MISMATCH\");\n }\n\n // The escrow's own account, read from chain: SUBMITTED, and committing exactly `deliverableHash`.\n private async assertCommitted(address: string, deliverableHash: string): Promise<void> {\n const mismatch = (why: string, cause?: unknown): never => {\n throw new EscroError(\n `Escrow ${address} ${why}; the predicate's record is not over its committed deliverable`,\n \"PREDICATE_DELIVERABLE_MISMATCH\",\n undefined,\n cause === undefined ? undefined : { cause },\n );\n };\n const info = await this.connection.getAccountInfo(new PublicKey(address), \"confirmed\");\n if (info === null) return mismatch(\"has no account on chain\");\n if (!info.owner.equals(resolveProgramId(this.cluster))) {\n return mismatch(\"is not owned by the Escro program\");\n }\n let account: ReturnType<typeof decodeEscrowAccount>;\n try {\n account = decodeEscrowAccount(info.data);\n } catch (err) {\n if (!(err instanceof ChainReadError)) throw err;\n return mismatch(\"is not a current EscrowAccount\", err);\n }\n if (account.state !== \"Submitted\") {\n return mismatch(`is ${String(account.state)} on chain, not Submitted`);\n }\n if (account.deliverable_hash !== deliverableHash) {\n return mismatch(`commits ${String(account.deliverable_hash)}, not ${deliverableHash}`);\n }\n }\n\n // The one release body: the plain release and the predicate release differ only by the memo.\n private async release(address: string, memo?: string): Promise<ReleasePaymentOutcome> {\n const signature = await this.sendRelease(address, true, memo);\n\n // Record it AFTER the chain settled: /release records COMPLETED only once the API's RPC\n // shows the account closed, and refuses with ESCROW_NOT_SETTLED until then. A failure\n // past the retry window is reported, never thrown: the on-chain signature is authoritative.\n try {\n await this.retryRecord(\n address,\n signature,\n () => this.api.releasePaymentDb(address),\n isRetryableReleaseCode,\n );\n } catch (err) {\n if (!(err instanceof EscroConfirmError)) throw err;\n return { signature, confirm: { landed: false, error: err } };\n }\n\n return { signature, confirm: { landed: true } };\n }\n\n // Builds, signs and sends the buyer's release_payment, with the memo when given; with `wait`,\n // returns once it confirmed.\n private async sendRelease(address: string, wait: boolean, memo?: string): Promise<string> {\n // Fetch escrow metadata for worker pubkey + mint\n const escrow = await this.api.getEscrow(address);\n if (!escrow.taker) {\n throw new EscrowNotFoundError(`Escrow ${address} has no assigned worker`);\n }\n\n // Fetch platform config for treasury pubkey + usdc mint\n const { treasury, mint } = await fetchPlatformConfig(this.connection, this.cluster);\n\n // Build, sign, and submit the on-chain release_payment FIRST. The API's COMPLETED\n // record must NOT precede settlement: a failed on-chain tx would otherwise leave\n // the escrow COMPLETED in the API's record but funded on-chain, and the oracle\n // would no longer time it out. The chain is the source of truth.\n const unsignedTx = await buildReleasePaymentTx({\n buyer: this.options.wallet.publicKey,\n escrowPda: new PublicKey(address),\n worker: new PublicKey(escrow.taker),\n mint,\n treasury,\n connection: this.connection,\n cluster: this.cluster,\n ...(memo === undefined ? {} : { memo }),\n });\n return this.send(\n unsignedTx,\n {\n name: \"release_payment\",\n escrowPda: address,\n worker: escrow.taker,\n treasury: treasury.toBase58(),\n mint: mint.toBase58(),\n ...(memo === undefined ? {} : { memo }),\n },\n undefined,\n wait,\n );\n }\n\n /**\n * Raise a dispute for an escrow. Either the buyer or the assigned worker\n * may call this. Signs and submits the `raise_dispute` on-chain tx, then confirms it with the API.\n * With `{ wait: false }` it returns once the dispute is sent; `evidence` then is refused\n * (`VALIDATION_ERROR`) before any request: attach it later with\n * `confirm(address, signature, { evidence })`. See {@link SendOptions.wait}.\n *\n * @returns Solana transaction signature.\n */\n async raiseDispute(\n address: string,\n params: RaiseDisputeParams,\n options?: SendOptions,\n ): Promise<string> {\n const wait = options?.wait ?? true;\n const reasonError = disputeReasonError(params.reason);\n if (reasonError !== null) throw new EscroError(reasonError, \"VALIDATION_ERROR\");\n // Checked before anything lands: confirm validates evidence only after the\n // dispute is on chain, where a rejection would leave it unrecorded.\n if (params.evidence !== undefined && !isSafeUrl(params.evidence)) {\n throw new EscroError(\n `evidence must be an http(s), ipfs or ar URL: ${params.evidence}`,\n \"VALIDATION_ERROR\",\n );\n }\n // Evidence reaches the arbitrator only through the disputant's confirm, which an async\n // dispute never sends.\n if (!wait && params.evidence !== undefined) {\n throw new EscroError(\n \"evidence travels only with the dispute's confirm: raise the dispute with { wait: false } and no evidence, then attach it with confirm(address, signature, { evidence })\",\n \"VALIDATION_ERROR\",\n );\n }\n const { unsignedTx } = await this.api.raiseDispute(address, { reason: params.reason });\n const signature = await this.send(\n unsignedTx,\n {\n name: \"raise_dispute\",\n escrowPda: address,\n reason: params.reason,\n },\n undefined,\n wait,\n );\n if (!wait) return signature;\n await this.confirm(address, signature, {\n ...(params.evidence !== undefined && { evidence: params.evidence }),\n });\n return signature;\n }\n\n /**\n * Cancel a funded escrow before any worker has claimed it.\n * Buyer must be the wallet in the constructor. Only valid when state is `FUNDED`.\n * Signs and submits the `cancel_escrow` on-chain tx, then confirms it with the API; full USDC refund to buyer.\n * With `{ wait: false }` it returns once the cancel is sent; see {@link SendOptions.wait}.\n *\n * @returns Solana transaction signature.\n */\n async cancelEscrow(address: string, options?: SendOptions): Promise<string> {\n const { unsignedTx } = await this.api.cancelEscrow(address);\n return this.sendAndConfirm(\n address,\n unsignedTx,\n { name: \"cancel_escrow\", escrowPda: address },\n options,\n );\n }\n\n /**\n * Pays an x402 V2 402: `params.url`, which the SDK requests for its 402, or\n * `params.paymentRequired`, a 402 the caller already decoded. Only an entry paying exactly\n * `params.amountMicroUsdc` to `params.to` on this client's cluster is paid; `params.policy` can\n * only narrow the choice. An `on-delivery` (or `job-escrow`) entry is funded through\n * {@link createEscrow}, with `to` as the assigned worker and its spend cap unchanged, and the\n * payment is presented once to the URL that answered the 402 (no redirect followed, nothing\n * retried); the result carries the `create_escrow` signature as `reference`, the escrow PDA, and\n * the paid request's decoded `PAYMENT-RESPONSE` and response.\n *\n * Without a `policy` the escrow rail wins: when an `on-delivery` or `job-escrow` entry matches\n * the caller's terms it is the one paid, whatever the 402's order. An `exact` entry is paid over\n * the x402 rail, from this wallet, under {@link EscroOptions.x402SpendCap} (required on mainnet):\n * the official client builds the transaction, a guarded signer checks it against the entry and\n * the caller's terms before the key runs, and the payment header goes once to the 402's resource\n * URL, never to a facilitator. The result's `reference` is the settlement's transaction. An `upto`\n * entry is never paid ({@link EscroPayError} `unsupported_scheme`). A failure after the payment\n * left the process (`settlement`, `presentation`, `redirect`, `timeout`) carries `payment`, the\n * Memo text, amount and `payTo`, to match against the wallet's token-account history; the amount\n * stays counted. x402 V2 has no idempotency key: two calls are two payments, each counted.\n *\n * The first request is bounded by 30 s, the paid request by the entry's `maxTimeoutSeconds`; an\n * entry over 3600 seconds is not paid. A network failure of the first request rejects\n * {@link EscroError} `NETWORK_ERROR`, with nothing funded. Refusals are {@link EscroPayError}s; a\n * failure after the escrow is funded carries `escrowPda` and `createSignature`, and\n * `cancelEscrow(escrowPda)` recovers the deposit while it is Funded. There is no idempotency key:\n * two calls fund two escrows. The signature is FROZEN.\n */\n pay(params: PayParams): Promise<PaymentResult> {\n return payOver402(\n {\n escro: this,\n wallet: this.options.wallet,\n cluster: this.cluster,\n rpc: this.connection,\n router: this.router,\n rpcUrl: this.options.rpcUrl,\n x402SpendCap: this.x402SpendCap,\n },\n params,\n );\n }\n\n /**\n * Claim an assigned task. Worker must be the wallet in the constructor.\n * Signs and submits the `claim_task` on-chain tx, then confirms it with the API.\n * With `{ wait: false }` it returns once the claim is sent; see {@link SendOptions.wait}.\n *\n * @returns Solana transaction signature.\n */\n async claimTask(address: string, options?: SendOptions): Promise<string> {\n const { unsignedTx } = await this.api.claimTask(address);\n return this.sendAndConfirm(\n address,\n unsignedTx,\n { name: \"claim_task\", escrowPda: address },\n options,\n );\n }\n\n /**\n * Submit a deliverable for the buyer to review. Worker must be the wallet.\n * Signs and submits the `submit_deliverable` on-chain tx, then confirms it with the API.\n * With `{ wait: false }` it returns once the submit is sent; see {@link SendOptions.wait}.\n *\n * @returns Solana transaction signature.\n */\n async submitDeliverable(\n address: string,\n params: SubmitDeliverableParams,\n options?: SendOptions,\n ): Promise<string> {\n const { unsignedTx } = await this.api.submitDeliverable(address, params);\n return this.sendAndConfirm(\n address,\n unsignedTx,\n {\n name: \"submit_deliverable\",\n escrowPda: address,\n deliverableHash: params.contentHash,\n proofUri: params.proofUri ?? null,\n },\n options,\n );\n }\n\n /**\n * List tasks assigned to the wallet's public key.\n * Optionally filter by state(s) and paginate results.\n *\n * If `options.poll` is true, polls with exponential backoff until at least\n * one task is returned.\n *\n * Serves open tasks only (FUNDED, IN_PROGRESS, SUBMITTED); a DISPUTED or settled\n * escrow assigned to the wallet comes from {@link getMyAssignedEscrows}.\n *\n * @param state - Filter by one or more states (first state used as API filter).\n * @param options - Polling, pagination (limit/offset).\n */\n async getMyTasks(\n state?: EscrowState[],\n options?: PollOptions & ListOptions,\n ): Promise<PaginatedResult<EscrowAccount>> {\n const assignedTo = this.options.wallet.publicKey.toBase58();\n const params: Parameters<ApiClient[\"listEscrows\"]>[0] = {\n assignedTo,\n ...(state?.[0] != null && { state: state[0] }),\n ...(options?.limit != null && { limit: options.limit }),\n ...(options?.offset != null && { offset: options.offset }),\n };\n\n if (!options?.poll) {\n return this.api.listEscrows(params);\n }\n\n const fetcher = () =>\n this.api.listEscrows(params).then((result) => (result.items.length > 0 ? result : null));\n\n return pollUntil(\n assignedTo,\n fetcher,\n (r): r is PaginatedResult<EscrowAccount> => r !== null,\n options.timeoutMs,\n );\n }\n\n /**\n * List every escrow assigned to the wallet's public key in any served state,\n * DISPUTED and the settled states (COMPLETED, REFUNDED) included, unlike\n * {@link getMyTasks}, which serves open tasks only. Optionally filter by state\n * and paginate. Never polls.\n *\n * A Worker Bot uses this to read its DISPUTED escrows, whose fronted cost stays\n * committed until arbitration settles them.\n *\n * @param state - Filter by one or more states (first state used as API filter).\n * @param options - Pagination (limit/offset).\n */\n async getMyAssignedEscrows(\n state?: EscrowState[],\n options?: ListOptions,\n ): Promise<PaginatedResult<EscrowAccount>> {\n return this.api.listEscrows({\n taker: this.options.wallet.publicKey.toBase58(),\n ...(state?.[0] != null && { state: state[0] }),\n ...(options?.limit != null && { limit: options.limit }),\n ...(options?.offset != null && { offset: options.offset }),\n });\n }\n\n /**\n * List escrows CREATED by the wallet's public key (the maker / buyer), the\n * mirror of {@link getMyTasks} for the buyer side. Optionally filter by state\n * and paginate.\n *\n * A Buyer Bot uses this to sum its own outstanding (still-locked) escrows for\n * the client-side spend cap: the program is the source of truth, so the total\n * is read from chain state (via the API), never a local tally a crash could lose.\n *\n * @param state - Filter by one or more states (first state used as API filter).\n * @param options - Polling, pagination (limit/offset).\n */\n async getMyEscrows(\n state?: EscrowState[],\n options?: PollOptions & ListOptions,\n ): Promise<PaginatedResult<EscrowAccount>> {\n const maker = this.options.wallet.publicKey.toBase58();\n const params: Parameters<ApiClient[\"listEscrows\"]>[0] = {\n maker,\n ...(state?.[0] != null && { state: state[0] }),\n ...(options?.limit != null && { limit: options.limit }),\n ...(options?.offset != null && { offset: options.offset }),\n };\n\n if (!options?.poll) {\n return this.api.listEscrows(params);\n }\n\n const fetcher = () =>\n this.api.listEscrows(params).then((result) => (result.items.length > 0 ? result : null));\n\n return pollUntil(\n maker,\n fetcher,\n (r): r is PaginatedResult<EscrowAccount> => r !== null,\n options.timeoutMs,\n );\n }\n\n /**\n * Find worker bots in the EscroBots registry, optionally filtered by\n * capability. Queries `GET /v1/bots?role=worker` (the API includes `both`\n * bots) and returns candidates in REGISTRY ORDER: this method does no\n * ranking, scoring, or reordering: the directory is an open index with no\n * curation, not a marketplace. Escro-shipped code never ranks; the caller's own bot decides.\n *\n * Each candidate keeps the CLAIM (`descriptor`) separate from the AUTHORSHIP\n * check (`signatureValid`, verified locally so a third party need not trust the\n * API). Capabilities remain unverified claims; on-chain history (EscroRep)\n * is their verification, deliberately not merged in here.\n */\n async findWorkers(\n params: { capability?: string } & ListOptions = {},\n ): Promise<WorkerCandidate[]> {\n const { items } = await this.api.listBots({\n role: \"worker\",\n ...(params.capability != null && { capability: params.capability }),\n ...(params.limit != null && { limit: params.limit }),\n ...(params.offset != null && { offset: params.offset }),\n });\n return items.map((descriptor) => ({\n descriptor,\n signatureValid: verifyBotDescriptorSignature(descriptor),\n }));\n }\n\n /**\n * Fetch the EscroRep bulk export: every indexed wallet's RAW reputation\n * components, each wallet exactly once, in one fetch. Returns\n * the raw components verbatim - this method does NO ranking, scoring, or default\n * weighting (Escro-shipped code never ranks; the caller's own bot weights and\n * decides). Selection layers join these components to {@link findWorkers}\n * candidates by wallet. Throws {@link ReputationUnavailableError} when the\n * deployment mounts no reputation source (HTTP 404).\n */\n async listReputations(): Promise<ServedWalletReputation[]> {\n return this.api.listReputations();\n }\n\n /**\n * Fetch protocol-wide stats from the public `GET /v1/stats` endpoint.\n *\n * @returns protocol-wide {@link ProtocolStats}.\n */\n async getStats(): Promise<ProtocolStats> {\n const data = await this.api.getStats();\n return data as ProtocolStats;\n }\n\n /**\n * Ask the API to record the create, claim, submit, cancel or dispute that the\n * landed `signature` carries; the API verifies it on chain first. Retries a\n * not-yet-visible transaction, an RPC failure, a gateway error or a rate limit\n * for about 30 s (waiting at least a sent Retry-After), never a rejection. Throws\n * {@link EscroConfirmError}; calling again is safe (a replay of a recorded\n * transition succeeds). An `address` that is not a base-58 public key throws an\n * {@link EscroError} with code `VALIDATION_ERROR` before any request, not an\n * `EscroConfirmError`. A successful confirm of a create, or a confirm of its signature\n * refused `TX_FAILED` (the create landed and failed), ends its in-flight hold under\n * {@link EscroOptions.spendCap}.\n */\n async confirm(\n address: string,\n signature: string,\n opts: { evidence?: string } = {},\n ): Promise<EscrowAccount> {\n assertPublicKey(\"address\", address);\n const wallet = this.options.wallet.publicKey.toBase58();\n let escrow: EscrowAccount;\n try {\n escrow = await this.retryRecord(\n address,\n signature,\n () => this.api.confirm(address, signature, opts.evidence),\n isRetryableConfirmCode,\n );\n } catch (err) {\n // The create's own transaction failed at execution, so it moved no deposit.\n if (err instanceof EscroConfirmError && err.code === \"TX_FAILED\") {\n dropFailed(this.cluster, wallet, address, signature);\n }\n throw err;\n }\n // The API now counts the escrow, so the spend cap stops holding it as in flight.\n dropPending(this.cluster, wallet, address);\n return escrow;\n }\n\n // Calls `record` until the API records the landed `signature`: a code `retryable` accepts or\n // a network failure is retried for about 30 s (waiting at least a sent Retry-After), any\n // other refusal is not. Throws EscroConfirmError.\n private async retryRecord<T>(\n address: string,\n signature: string,\n record: () => Promise<T>,\n retryable: (code: string) => boolean,\n ): Promise<T> {\n const deadline = Date.now() + CONFIRM_WINDOW_MS;\n let delay = CONFIRM_FIRST_DELAY_MS;\n for (;;) {\n let code: string;\n let message: string;\n let retryAfterMs: number | undefined;\n let wait = delay;\n try {\n return await record();\n } catch (err) {\n if (err instanceof EscroError) {\n if (!retryable(err.code)) {\n throw new EscroConfirmError(\n address,\n signature,\n err.code,\n err.message,\n err.retryAfterMs,\n );\n }\n code = err.code;\n message = err.message;\n retryAfterMs = err.retryAfterMs;\n wait = Math.max(delay, err.retryAfterMs ?? 0);\n } else {\n // A network failure: the request may not have reached the API.\n code = \"NETWORK_ERROR\";\n message = err instanceof Error ? err.message : String(err);\n }\n }\n if (Date.now() + wait > deadline) {\n throw new EscroConfirmError(address, signature, code, message, retryAfterMs);\n }\n await sleep(wait);\n delay = Math.min(delay * 2, CONFIRM_MAX_DELAY_MS);\n }\n }\n\n // Prices the deposit, checks the cap and POSTs inside the wallet's admission, then holds the\n // deposit as in flight: the API counts no CREATED escrow, so without the hold a concurrent\n // create of the same wallet would read a total that misses this one. The fee is read inside so\n // a create is priced at the fee in force after every create admitted before it.\n private async admitCreate(\n cap: Readonly<SpendCap>,\n wallet: string,\n params: CreateEscrowParams,\n ): Promise<{ escrowId: string; escrowPda: string; unsignedTx: string }> {\n const ledger = walletLedger(this.cluster, wallet);\n return admit(ledger, async () => {\n const { feeBps } = await boundedRead(\"The PlatformConfig read\", () =>\n fetchPlatformConfig(this.connection, this.cluster),\n );\n const amount = BigInt(params.amountUsdc);\n const deposit = amount + escrowFee(amount, feeBps);\n await this.dropServed(ledger);\n // Taken before the read: a create confirmed during the read leaves the in-flight set and\n // may be missing from the read, and the reverse order would count it nowhere.\n const inFlight = pendingMicroUsdc(ledger);\n const read = await this.readOutstanding(cap, wallet);\n // A total past 2^53 rounds as a number but stays above every cap, a safe integer.\n assertWithinSpendCap({\n maxOutstandingMicroUsdc: cap.maxOutstandingMicroUsdc,\n outstandingMicroUsdc: Number(inFlight + BigInt(read)),\n proposedMicroUsdc: Number(deposit),\n });\n const created = await this.api.createEscrow(params);\n // A new create's escrow is never one already in flight: a repeated answer would replace\n // that create's hold, and a failed send of this one would drop it.\n if (ledger.pending.has(created.escrowPda)) {\n throw new EscroError(\n `The API answered a create with escrow ${created.escrowPda}, which this wallet already has in flight`,\n \"UNEXPECTED_TRANSACTION\",\n );\n }\n ledger.pending.set(created.escrowPda, { deposit });\n return created;\n });\n }\n\n // Ends the hold of each in-flight create the API now serves (an unconfirmed create is never\n // served, so a served escrow landed and its deposit is in the API's own count while open). A\n // read that fails keeps the hold: it only overcounts.\n private async dropServed(ledger: WalletLedger): Promise<void> {\n await Promise.all(\n [...ledger.pending.keys()].map(async (address) => {\n try {\n await boundedRead(\"The escrow read\", () => this.api.getEscrow(address));\n } catch {\n return;\n }\n ledger.pending.delete(address);\n }),\n );\n }\n\n // The deposits the API counts for the wallet, or the injected `outstanding()`. Any failure is\n // `SPEND_CAP_UNREADABLE`: an unread total is never taken as zero.\n private async readOutstanding(cap: Readonly<SpendCap>, wallet: string): Promise<number> {\n let value: number;\n try {\n value =\n cap.outstanding === undefined\n ? outstandingFromAnswer(await this.api.getOutstandingDeposits(wallet), wallet)\n : await boundedRead(\"spendCap.outstanding()\", cap.outstanding);\n } catch (err) {\n if (err instanceof EscroError && err.code === SPEND_CAP_ERROR_CODES.unreadable) throw err;\n throw new EscroError(\n `The outstanding deposits could not be read: ${err instanceof Error ? err.message : String(err)}`,\n SPEND_CAP_ERROR_CODES.unreadable,\n undefined,\n { cause: err },\n );\n }\n if (!isMicroUsdc(value)) {\n throw new EscroError(\n `The outstanding deposits read as ${String(value)}, not a whole micro-USDC amount a number holds exactly`,\n SPEND_CAP_ERROR_CODES.unreadable,\n );\n }\n return value;\n }\n\n private send(\n unsignedTx: string,\n expected: ExpectedTransaction,\n onSend?: () => void,\n wait = true,\n ): Promise<string> {\n return signAndSend(\n unsignedTx,\n this.options.wallet,\n this.connection,\n this.cluster,\n expected,\n onSend,\n wait,\n );\n }\n\n private async sendAndConfirm(\n address: string,\n unsignedTx: string,\n expected: ExpectedTransaction,\n options?: SendOptions,\n ): Promise<string> {\n const wait = options?.wait ?? true;\n const signature = await this.send(unsignedTx, expected, undefined, wait);\n if (wait) await this.confirm(address, signature);\n return signature;\n }\n\n /**\n * Fetch an escrow by its PDA address.\n * If `options.poll` is true, polls with exponential backoff until the escrow\n * appears (useful immediately after a create tx before the API records it).\n * An `address` that is not a base-58 public key throws an {@link EscroError} with code\n * `VALIDATION_ERROR` at once, with or without `poll`.\n */\n async getEscrow(address: string, options?: PollOptions): Promise<EscrowAccount> {\n if (!options?.poll) {\n return this.api.getEscrow(address);\n }\n\n return pollUntil(\n address,\n () =>\n this.api.getEscrow(address).catch((e: unknown) => {\n if (e instanceof EscrowNotFoundError) return null;\n throw e instanceof Error ? e : new Error(String(e));\n }),\n (r): r is EscrowAccount => r !== null,\n options.timeoutMs,\n );\n }\n}\n","import type { SolanaCluster } from \"../config.js\";\n\n/**\n * Lifecycle states of an escrow, each transition validated by the on-chain program.\n *\n * Happy path: FUNDED → IN_PROGRESS → SUBMITTED → COMPLETED (buyer release or the 24h\n * timeout release).\n *\n * Exception paths:\n * IN_PROGRESS | SUBMITTED → DISPUTED (resolved only by arbitration, to COMPLETED or REFUNDED)\n * FUNDED → CANCELLED (buyer cancels before the claim; on chain the account is REFUNDED)\n * FUNDED | IN_PROGRESS → REFUNDED (deadline plus grace passed before a submission)\n */\nexport enum EscrowState {\n /**\n * An unconfirmed intent: the API's create build recorded it and no landed create_escrow has\n * funded it yet. Never persisted on chain and never served by a read.\n */\n CREATED = \"CREATED\",\n /** Maker deposited tokens into the vault; open for agent acceptance. */\n FUNDED = \"FUNDED\",\n /** An agent accepted the task; work is underway. */\n IN_PROGRESS = \"IN_PROGRESS\",\n /** Agent submitted a deliverable URI; awaiting buyer review or 24h auto-release. */\n SUBMITTED = \"SUBMITTED\",\n /** Funds released to the agent. Terminal state. */\n COMPLETED = \"COMPLETED\",\n /** Buyer cancelled before work started. Terminal state. */\n CANCELLED = \"CANCELLED\",\n /** Maker or agent raised a dispute; requires human arbitration. */\n DISPUTED = \"DISPUTED\",\n /** Funds returned to the maker (deadline expiry or dispute resolution). Terminal state. */\n REFUNDED = \"REFUNDED\",\n}\n\n/** Solana cluster the escrow account lives on. */\nexport type Network = \"mainnet-beta\" | \"devnet\" | \"localnet\";\n\n/**\n * Full on-chain representation of an AgentEscrow PDA, enriched with\n * off-chain metadata resolved by the API server.\n *\n * `amount` and all `*At` timestamps use the on-chain units:\n * - `amount` is in the SPL token's smallest denomination (e.g. μUSDC = 10⁻⁶ USDC).\n * - timestamps are Unix seconds as stored in the Anchor account.\n *\n * When serialising over HTTP (the API's escrow responses), `amount` is represented as a\n * decimal `string` of the smallest denomination to avoid JSON `number` precision loss.\n */\nexport interface EscrowAccount {\n /** Base-58 public key of the escrow PDA. */\n address: string;\n /** Base-58 public key of the task creator (the party paying for the work). */\n maker: string;\n /** Base-58 public key of the worker assigned at creation (every escrow has one). */\n taker: string | null;\n /** Base-58 public key of the SPL token mint used for payment (e.g. USDC mint). */\n mint: string;\n /**\n * Payment amount held in escrow, in the mint's smallest denomination.\n * Stored as `bigint` to preserve full u64 precision from the on-chain account.\n */\n amount: bigint;\n /** Current lifecycle state of the escrow. */\n state: EscrowState;\n /**\n * SHA-256 hex digest of the canonical UTF-8 JSON serialisation of the {@link TaskSpec}.\n * Recorded on-chain (the account's `spec_hash` holds this hash, bare, or as `ipfs://<hash>` on\n * older escrows), so the buyer and worker (and an arbitrator) can check that a\n * spec is the one the escrow was created for.\n */\n taskSpecHash: string;\n /**\n * The exact string the escrow's on-chain `spec_hash` holds: the bare 64-hex `taskSpecHash`\n * (current creates), `ipfs://<taskSpecHash>` (older escrows), or `null` where the API's record\n * of an older escrow lacks it. A label for the {@link TaskSpec}'s hash, not a fetchable copy\n * (Escro stores no spec body; the buyer shares the spec).\n */\n taskSpecUri: string | null;\n /**\n * Base-58 public key of the oracle authority permitted to sign timeout_release\n * (refund_buyer is permissionless).\n */\n oracle: string;\n /**\n * Platform fee in basis points. Once the API has read the escrow's `create_escrow` from chain,\n * it serves the escrow's on-chain `fee_bps` from its `EscrowCreated` event (PlatformConfig's\n * value, stored per escrow at creation); on a CREATED intent not yet read it serves its\n * `PLATFORM_FEE_BPS` mirror. Additive: the buyer deposits `amount` plus the fee and the\n * worker receives the full `amount`.\n */\n oracleFeeBps: number;\n /** Unix timestamp (seconds) when the escrow PDA was initialised. */\n createdAt: number;\n /**\n * Unix timestamp (seconds) at which the escrow deadline expires; mirrors the\n * on-chain `deadline` field set at `create_escrow`. A Worker Bot reads this to\n * decide whether it can finish a job before the deadline (never claim what it\n * can't finish); after it passes, an unstarted escrow is refundable to the maker.\n */\n deadline: number;\n /** Unix timestamp (seconds) of the most recent agent submission, or `null`. */\n submittedAt: number | null;\n /**\n * SHA-256 hex digest of the worker's submitted deliverable, mirrored from the\n * on-chain `deliverable_hash` written at `submit_deliverable`; `null` until the\n * escrow reaches SUBMITTED. The on-chain value is authoritative: a Buyer Bot's\n * review re-verifies a deliverable against a hash it independently expects and\n * never treats this mirror as proof of integrity on its own.\n */\n deliverableHash: string | null;\n /**\n * URI of the submitted deliverable artifact (S3 presigned / IPFS / Arweave),\n * mirrored from the off-chain `proof_uri` recorded at `submit_deliverable`;\n * `null` until SUBMITTED. The Buyer Bot fetches the deliverable content here to\n * review it.\n */\n proofUri: string | null;\n /** PDA canonical bump seed, stored on-chain to validate future instructions. */\n bump: number;\n /** Solana cluster this account belongs to. */\n network: Network;\n}\n\n/**\n * `GET /v1/escrows/outstanding?maker=`: the maker's open deposits, the escrows whose vault still\n * holds the buyer's money (FUNDED, IN_PROGRESS, SUBMITTED, DISPUTED; never CREATED).\n */\nexport interface OutstandingDeposits {\n /** Base-58 public key of the buyer the figures are for. */\n maker: string;\n /** Number of open escrows counted. */\n count: number;\n /**\n * Sum over those escrows of `amount` plus the program's fee at the escrow's stored rate, in\n * micro-USDC, as a decimal u64 string (it can exceed `Number.MAX_SAFE_INTEGER`).\n */\n depositsMicroUsdc: string;\n}\n\n/**\n * First-class settlement cause for an escrow, recorded off-chain (EscroRep\n * fidelity). One value per fund-moving instruction, keyed 1:1 to the\n * EscroRep reducer's `EscrowEventKind` so the reputation the API serves\n * matches the on-chain reducer. The cause also encodes the dispute OUTCOME:\n * `ARBITRATION_RELEASE` = worker prevailed, `ARBITRATION_REFUND` = buyer\n * prevailed. Single-sourced here: whatever stores or validates a cause accepts\n * exactly this list; never caller-supplied.\n *\n * Declared as a `const` array (not a bare union) so the value list has a single\n * runtime source any test or validator reads from.\n */\nexport const SETTLEMENT_CAUSES = [\n /** Buyer-signed release_payment: explicit completion. */\n \"EXPLICIT_RELEASE\",\n /** Oracle timeout_release: 24h auto-release completion (buyer non-response). */\n \"TIMEOUT_RELEASE\",\n /** admin arbitration_release: worker prevailed in a dispute, not a completion. */\n \"ARBITRATION_RELEASE\",\n /** Deadline-expiry refund_buyer (any cranker): worker non-delivery. */\n \"DEADLINE_REFUND\",\n /** admin arbitration_refund: buyer prevailed in a dispute. */\n \"ARBITRATION_REFUND\",\n /** cancel_escrow: buyer cancelled a FUNDED escrow before any claim. */\n \"CANCELLED\",\n] as const;\n\n/** The settlement cause recorded for a settled escrow (see {@link SETTLEMENT_CAUSES}). */\nexport type SettlementCause = (typeof SETTLEMENT_CAUSES)[number];\n\n/**\n * Every outcome the oracle records for a settlement it attempts. Single-sourced\n * here: the oracle's recorder takes an {@link OracleEventType}, and whatever\n * accepts a recorded outcome must accept every value here (it may also keep\n * retired values nothing records any more).\n *\n * Declared as a `const` array (not a bare union) so the value list has a single\n * runtime source any test or validator reads from.\n */\nexport const ORACLE_EVENT_TYPES = [\n /** Oracle-signed timeout_release settled the escrow (24h auto-release completion). */\n \"TIMEOUT_RELEASE\",\n /** Permissionless refund_buyer settled the escrow (deadline-expiry refund). */\n \"AUTO_REFUND\",\n /** A repeated settlement request: the escrow was already settled, nothing signed. */\n \"ALREADY_SETTLED\",\n /**\n * An escrow recorded off-chain as DISPUTED, whose dispute never landed on chain, was restored to\n * its on-chain state.\n */\n \"DISPUTE_RECONCILED\",\n /** A closed escrow's off-chain record was brought to its actual on-chain settlement. */\n \"RECONCILED\",\n /** A closed escrow's settling instruction could not be read, so no settlement was recorded. */\n \"RECONCILE_INDETERMINATE\",\n /** Settlement attempted before its on-chain time gate opened (silent backoff, not a failure). */\n \"NOT_YET_ELIGIBLE\",\n /** A request of an unknown or forged type was dropped (the oracle acts only on its own types). */\n \"UNKNOWN_MESSAGE_TYPE\",\n] as const;\n\n/** An outcome the oracle records (see {@link ORACLE_EVENT_TYPES}). */\nexport type OracleEventType = (typeof ORACLE_EVENT_TYPES)[number];\n\n/** One set of `GET /v1/stats` figures: the public block, or the operator block. */\nexport interface ProtocolStatsFigures {\n totalEscrows: number;\n totalVolumeUsdc: string;\n /**\n * Settled USDC volume: the sum of `amount_usdc` (the job amount, which the\n * worker keeps in full; the additive platform fee is protocol revenue, not\n * settled work volume) over escrows in the COMPLETED terminal state. COMPLETED\n * is reached only by the three worker-paying instructions (release_payment,\n * timeout_release, arbitration_release); refunded and cancelled escrows never\n * paid a worker and are excluded. This is the honest headline number: it counts\n * settlement, not transaction volume.\n */\n settledVolumeUsdc: string;\n byState: Record<EscrowState, number>;\n activeEscrows: number;\n}\n\n/** Protocol-wide aggregate statistics: public, unauthenticated. */\nexport interface ProtocolStats extends ProtocolStatsFigures {\n /** The Solana cluster this API serves (its `CLUSTER`). */\n cluster: SolanaCluster;\n /** That cluster's one USDC mint (`getUsdcMint`): every figure here is in this token. */\n usdcMint: string;\n /**\n * Escro-operated fleet figures: the same fields over\n * escrows whose buyer and assigned worker are both in the API's operator\n * allowlist. They are real settlements but not third-party demand, so every\n * public field excludes them; never sum this block with the public fields.\n */\n operator: ProtocolStatsFigures;\n}\n\n/** One worker's settled earnings over an activity window; wallet anonymised. */\nexport interface ActivityEarner {\n /**\n * Anonymised worker wallet: a truncated display form (`first4...last4`), never\n * the full address. Truncation is a display convenience, not a privacy boundary\n * (Solana addresses are public and EscroRep exposes full per-wallet history).\n */\n wallet: string;\n /** Settled USDC (job amount) the worker earned in the window. */\n settledVolumeUsdc: string;\n /** Number of escrows the worker settled (reached COMPLETED) in the window. */\n jobsSettled: number;\n}\n\n/**\n * Activity leaderboard: anonymised top earners over a rolling window. The data\n * source behind escro.ai/activity (weekly earners). Public, unauthenticated.\n */\nexport interface ActivityLeaderboard {\n /** The Solana cluster this API serves (its `CLUSTER`). */\n cluster: SolanaCluster;\n /** That cluster's one USDC mint (`getUsdcMint`): every earning here is in this token. */\n usdcMint: string;\n /** Rolling window length in days (7 = weekly earners). */\n periodDays: number;\n /** Top earners, descending by settled volume. */\n earners: ActivityEarner[];\n}\n","/**\n * EscroBots v0 - the permissionless capability directory.\n *\n * A bot advertises itself by publishing a wallet-signed capability descriptor.\n * The descriptor is a *claim*, not a verified fact - on-chain history is the\n * verification (surfaced in the v1 directory). The registry performs no\n * approval, review, or ranking; fraud against the protocol is the only removal\n * criterion. The descriptor document itself is independently verifiable: anyone\n * holding it can check `signature` against `wallet` without trusting the API.\n */\n\n/**\n * The advertisable roles. Single source for both the `BotRole` type and the API's\n * validation of a role, so the accepted values and the type cannot drift: a role\n * added here flows into validation automatically.\n */\nexport const BOT_ROLES = [\"worker\", \"buyer\", \"both\"] as const;\n\n/** Whether the bot hires work, performs work, or both. */\nexport type BotRole = (typeof BOT_ROLES)[number];\n\n/**\n * The descriptor fields the bot's wallet signs. Everything a registry consumer\n * needs to find and reach the bot, minus the signature over these fields.\n */\nexport interface UnsignedBotDescriptor {\n /** Base58 Solana pubkey - the advertising bot and the descriptor's signer. */\n wallet: string;\n /** What the bot does in the escrow relationship. */\n role: BotRole;\n /** Free-form capability tags, e.g. `[\"fine-tune\", \"eval\"]`. Filterable. */\n capabilities: string[];\n /** The underlying service the bot wraps, e.g. `\"bittensor:sn56\"`. */\n serviceRef: string;\n /** Human-readable pricing guidance, e.g. `\"~$5 per fine-tune job\"`. */\n pricingHint: string;\n /** Optional http(s) endpoint a buyer can reach the bot at. */\n endpoint?: string;\n /** Unix milliseconds when the descriptor was signed. Monotonic per wallet. */\n signedAt: number;\n}\n\n/**\n * A signed capability descriptor as stored and served by the registry.\n * `signature` is a base58 detached Ed25519 signature over the canonical form of\n * the {@link UnsignedBotDescriptor} fields (see `canonicalBotDescriptorMessage`).\n */\nexport interface BotDescriptor extends UnsignedBotDescriptor {\n /** Base58 detached Ed25519 signature over the canonical unsigned descriptor. */\n signature: string;\n}\n","// The devnet deploy tooling rewrites the devnet values after each devnet deploy; only the\n// mainnet deploy tooling or a human mainnet bootstrap changes the mainnet values. The two\n// clusters have distinct program ids and upgrade authorities, so a leaked devnet upgrade authority\n// cannot upgrade mainnet.\n\nexport type SolanaCluster = \"devnet\" | \"mainnet\";\n\nexport const PROGRAM_ID_DEVNET = \"EjLpJ3obUYk1f2KDensU7UdGBZTxSdxufm7CSnMA3H5C\" as const;\nexport const PLATFORM_CONFIG_PDA_DEVNET = \"5BYnq9YsCTaMxBLJhBn4TPnCQuxiHcG5eZ2ygLJBu9dc\" as const;\nexport const DEVNET_USDC_MINT = \"4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU\" as const;\nexport const DEPLOYED_AT_DEVNET = \"2026-08-15T17:24:37.149Z\" as const;\n\nexport const PROGRAM_ID_MAINNET = \"4CwLNRF4mFXutiBGjtMHQBxh8whW8T8EyvJXdRhY1rvr\" as const;\nexport const PLATFORM_CONFIG_PDA_MAINNET = \"7zPti535SmzvkdtmKaGR8w4niHLiEidWCqCaQXLbQvhn\" as const;\nexport const MAINNET_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\" as const;\n// Pinned mainnet PlatformConfig values: the treasury and oracle authority the program is\n// configured with.\nexport const MAINNET_TREASURY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\nexport const MAINNET_ORACLE_AUTHORITY = \"G2Cr4PAJ58ZSYX2ceCMt2DtP1KBFXA9oYDtJJKZaKKJT\" as const;\n// The 2-of-2 Squads vault: the treasury's address, named apart because the roles differ.\nexport const MAINNET_UPGRADE_AUTHORITY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\n// The AdminConfig PDA, seeds [b\"admin\"] under PROGRAM_ID_MAINNET (a test derives it).\nexport const ADMIN_CONFIG_PDA_MAINNET = \"9SoVXPDjKFKA6sEo5oVp1RHij2FKVR52SCvoD2ELDHgD\" as const;\n// MAINNET_TREASURY's associated token account for MAINNET_USDC_MINT (a test derives it).\nexport const MAINNET_TREASURY_USDC_ATA = \"DAQfw4T3MzzfrWjkVy3mbWtWuUYVoaZThvsEF1RdM2kg\" as const;\n\n// An RPC proves its cluster by its genesis hash; the ops CLIs refuse a mismatch.\nexport const DEVNET_GENESIS_HASH = \"EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG\" as const;\nexport const MAINNET_GENESIS_HASH = \"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d\" as const;\n\n// CAIP-2 ids: `solana:` plus the first 32 characters of the genesis hash (a test locks them to\n// the hashes above and to the binding's appendix, docs/specs/scheme_on_delivery_svm.md).\nexport const SOLANA_CAIP2_MAINNET = \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\" as const;\nexport const SOLANA_CAIP2_DEVNET = \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\" as const;\n\nexport function getCaip2Network(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? SOLANA_CAIP2_MAINNET : SOLANA_CAIP2_DEVNET;\n}\n\n/** The cluster a CAIP-2 id names, exactly; undefined for any other string. */\nexport function clusterOfCaip2(network: string): SolanaCluster | undefined {\n if (network === SOLANA_CAIP2_MAINNET) return \"mainnet\";\n if (network === SOLANA_CAIP2_DEVNET) return \"devnet\";\n return undefined;\n}\n\n// The default API base per cluster: a mirror of the hosted API's domain name per cluster.\nexport const API_URLS: Record<SolanaCluster, string> = {\n devnet: \"https://api-devnet.escro.ai\",\n mainnet: \"https://api.escro.ai\",\n};\n\nexport function getApiUrl(cluster: SolanaCluster): string {\n return API_URLS[cluster];\n}\n\n/** Solana's public RPC per cluster: the default where no keyed endpoint is configured. */\nexport const PUBLIC_RPC_URLS: Readonly<Record<SolanaCluster, string>> = {\n devnet: \"https://api.devnet.solana.com\",\n mainnet: \"https://api.mainnet-beta.solana.com\",\n};\n\nexport function getPublicRpcUrl(cluster: SolanaCluster): string {\n return PUBLIC_RPC_URLS[cluster];\n}\n\n/** Platform oracle fee rate in basis points (50 bps = 0.50%). */\nexport const PLATFORM_FEE_BPS = 50 as const;\n\n/**\n * The program's fee on an escrow `amount` at `feeBps`, in micro-USDC: `floor(amount * feeBps /\n * 10_000)`, as `create_escrow` computes it. The buyer deposits `amount` plus this fee.\n */\nexport function escrowFee(amount: bigint, feeBps: number): bigint {\n return (amount * BigInt(feeBps)) / 10_000n;\n}\n\n/**\n * The minimum escrow `amount` in micro-USDC ($5.00): the worker's net, not the buyer's deposit\n * (amount plus the additive fee). Mirrors `MIN_ESCROW_AMOUNT` in the program; a test reads the\n * program source and fails on drift.\n */\nexport const MIN_ESCROW_AMOUNT = 5_000_000 as const;\n\n/**\n * The account layout version the program writes and accepts. MIRROR of\n * `CURRENT_ACCOUNT_VERSION` in the program; a test reads the program source and fails on\n * drift.\n */\nexport const CURRENT_ACCOUNT_VERSION = 1 as const;\n\n/**\n * The most UTF-8 bytes `raise_dispute` accepts as a reason. MIRROR of the program's\n * `MAX_REASON_LEN` in its `raise_dispute` instruction; a test reads the program source and fails\n * on drift. Checked off chain by `disputeReasonError`.\n */\nexport const MAX_DISPUTE_REASON_BYTES = 200 as const;\n\n/**\n * The most UTF-8 bytes `create_escrow`'s `spec_hash` may hold. MIRROR of `#[max_len(64)]` on\n * `spec_hash` in the program's `EscrowAccount`; a test reads the program source and fails on\n * drift. The program bounds the field only by the account's allocation; the\n * API's create builder enforces this cap.\n */\nexport const MAX_SPEC_HASH_BYTES = 64 as const;\n\n/**\n * The most UTF-8 bytes `submit_deliverable`'s `proof_uri` may hold. MIRROR of the `#[max_len]` on\n * `proof_uri` in the program's `EscrowAccount`; a test reads the program source and fails on\n * drift. The program bounds the field only by the account's allocation; the\n * API's submit builder enforces this cap. Checked off chain by `proofUriError`.\n */\nexport const MAX_PROOF_URI_BYTES = 128 as const;\n\n/**\n * Indeterminate settlement reads one escrow may accrue before the oracle stops retrying it and\n * alerts once. Each one follows a read that found the escrow's account closed, so an escrow past\n * the bound has nothing left to sign. Every off-chain reader of the bound reads this one constant.\n */\nexport const RECONCILE_ATTEMPT_BOUND = 5;\n\n// Mirrors of refund_buyer.rs REFUND_GRACE_SECONDS and timeout_release.rs TIMEOUT_SECONDS (the\n// non-feature builds); a test reads the program source and fails on drift.\nexport const ONCHAIN_REFUND_GRACE_SECONDS = 900 as const;\nexport const ONCHAIN_TIMEOUT_SECONDS = 86_400 as const;\n\n/**\n * The cluster clock lags wall clock, so an off-chain gate that must clear an on-chain one runs\n * at the on-chain offset plus this margin; at the bare boundary the chain still rejects.\n */\nexport const CLOCK_SKEW_SECONDS = 60 as const;\n\nexport const SCANNER_REFUND_GRACE_SECONDS = (ONCHAIN_REFUND_GRACE_SECONDS +\n CLOCK_SKEW_SECONDS) as 960;\nexport const SCANNER_TIMEOUT_SECONDS = (ONCHAIN_TIMEOUT_SECONDS + CLOCK_SKEW_SECONDS) as 86_460;\n\n/**\n * The furthest escrow deadline, in seconds from now, an agent-driven pay surface accepts (7 days): the\n * ceiling and the default of the MCP's, SAK's and Eliza's pay bound.\n */\nexport const PAY_MAX_DEADLINE_SECONDS = 604_800 as const;\n\n/** The System Program address: no program deploys there, so it marks an unbootstrapped mainnet. */\nexport const MAINNET_PROGRAM_ID_PLACEHOLDER = \"11111111111111111111111111111111\" as const;\n\nexport function getProgramId(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PROGRAM_ID_MAINNET : PROGRAM_ID_DEVNET;\n}\n\nexport function getPlatformConfigPda(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PLATFORM_CONFIG_PDA_MAINNET : PLATFORM_CONFIG_PDA_DEVNET;\n}\n\nexport function getUsdcMint(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? MAINNET_USDC_MINT : DEVNET_USDC_MINT;\n}\n\nexport function isPlaceholderProgramId(id: string): boolean {\n return id === MAINNET_PROGRAM_ID_PLACEHOLDER;\n}\n\n/** Throws on mainnet while the program id is the placeholder; call at module init. */\nexport function assertProgramIdNotPlaceholder(id: string, cluster: SolanaCluster): void {\n if (cluster === \"mainnet\" && isPlaceholderProgramId(id)) {\n throw new Error(\n `PROGRAM_ID_MAINNET is still the System Program placeholder (${MAINNET_PROGRAM_ID_PLACEHOLDER}). ` +\n \"This build carries no deployed mainnet program id: use a release built after the \" +\n \"mainnet bootstrap.\",\n );\n }\n}\n\nexport function parseClusterEnv(raw: string | undefined): SolanaCluster {\n if (raw === \"mainnet\") return \"mainnet\";\n if (raw === \"devnet\" || raw === undefined || raw === \"\") return \"devnet\";\n throw new Error(`CLUSTER env var must be \"devnet\" or \"mainnet\", got \"${raw}\"`);\n}\n","// The one U+0000 rule: a text column refuses U+0000, so no value the store keeps may hold it. The\n// request validators and the chain ingester's store rules both read it. A leaf: it imports nothing.\n\n/** False exactly when `value` holds U+0000, which a text column refuses. */\nexport function storableText(value: string): boolean {\n return !value.includes(\"\\u0000\");\n}\n","import { createHash } from \"node:crypto\";\nimport type { TaskSpec } from \"../types/index.js\";\n\nexport function canonicalize(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) {\n return \"[\" + value.map((v) => (v === undefined ? \"null\" : canonicalize(v))).join(\",\") + \"]\";\n }\n if (typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n return \"{\" + keys.map((k) => JSON.stringify(k) + \":\" + canonicalize(obj[k])).join(\",\") + \"}\";\n }\n return JSON.stringify(value);\n}\n\n// The fields the API's TaskSpec schema keeps; it drops every other key before hashing, so a\n// client hashing the raw spec must drop them too. metadata is free-form and kept whole.\nconst SPEC_KEYS = [\n \"version\",\n \"taskType\",\n \"description\",\n \"acceptanceCriteria\",\n \"deliverableFormat\",\n \"metadata\",\n] as const;\nconst CRITERION_KEYS = [\"id\", \"description\", \"weight\", \"required\"] as const;\nconst FORMAT_KEYS = [\"type\", \"schema\", \"mimeType\", \"maxSizeBytes\", \"language\"] as const;\n\nfunction pick(value: unknown, keys: readonly string[]): unknown {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return value;\n const source = value as Record<string, unknown>;\n return Object.fromEntries(keys.filter((k) => k in source).map((k) => [k, source[k]]));\n}\n\nfunction normalizeTaskSpec(spec: TaskSpec): unknown {\n const top = pick(spec, SPEC_KEYS) as Record<string, unknown>;\n const criteria = top.acceptanceCriteria;\n return {\n ...top,\n acceptanceCriteria: Array.isArray(criteria)\n ? criteria.map((c) => pick(c, CRITERION_KEYS))\n : criteria,\n deliverableFormat: pick(top.deliverableFormat, FORMAT_KEYS),\n };\n}\n\n/** The hex SHA-256 of a TaskSpec's canonical JSON: what an escrow's `spec_hash` holds. */\nexport function computeTaskSpecHash(spec: TaskSpec): string {\n return createHash(\"sha256\")\n .update(canonicalize(normalizeTaskSpec(spec)), \"utf8\")\n .digest(\"hex\");\n}\n","/**\n * Escapes every character that could end or reorder a terminal line (Unicode categories Cc, Cf,\n * Zl, Zp: C0, C1, bidi and zero-width controls, the line and paragraph separators), so text a\n * dispute party or an RPC controls cannot end or reorder a line.\n */\nexport function printable(line: string): string {\n return line.replace(/[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}]/gu, (c) => {\n const hex = (c.codePointAt(0) ?? 0).toString(16);\n return hex.length > 4 ? `\\\\u{${hex}}` : `\\\\u${hex.padStart(4, \"0\")}`;\n });\n}\n","/**\n * Secret detection for task-spec content, which is shared and not secret.\n *\n * A task spec and its metadata go to the worker (and, in a dispute, the arbitrator),\n * and its hash and URI are recorded on-chain, so nothing in them is secret. Escro\n * stores no spec body. The original finding (L3) is that secrets CAN be placed in the\n * free-form metadata map. We actively REJECT obvious secret material rather than\n * merely document the boundary: \"documented as not secret\" is weaker than \"refuses\n * a secret\".\n *\n * Design goal: near-zero false positives. We flag only high-confidence patterns\n * (keypair byte arrays, base58 64-byte secret keys, PEM private-key blocks, AWS\n * access keys, and a small set of unambiguous secret field names). We do NOT do\n * entropy heuristics or fuzzy mnemonic matching, which would risk rejecting\n * legitimate task descriptions.\n */\n\n/**\n * Thrown when caller-supplied content appears to contain a secret. Carries a\n * 400 statusCode + code so the API's global error handler returns a clean\n * client error rather than a 500.\n */\nexport class SecretInMetadataError extends Error {\n readonly code = \"METADATA_CONTAINS_SECRET\";\n readonly statusCode = 400;\n readonly path: string;\n readonly reason: string;\n constructor(path: string, reason: string) {\n super(\n `Refused: a suspected secret was found at ${path} (${reason}). ` +\n \"Task metadata is shared with the worker and its hash is recorded on-chain; it is not secret storage: remove the secret and retry.\",\n );\n this.name = \"SecretInMetadataError\";\n this.path = path;\n this.reason = reason;\n }\n}\n\nconst PEM_PRIVATE_KEY = /-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/;\nconst AWS_ACCESS_KEY_ID = /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/;\n// A 64-byte ed25519 secret key base58-encodes to ~87-88 chars. 32-byte pubkeys\n// (~43-44 chars) are legitimate in metadata, so only the long form is a signal.\n// Anchored to the whole (trimmed) value for precision — base64 of similar length\n// carries chars outside the base58 alphabet and won't match.\nconst BASE58_64_BYTE = /^[1-9A-HJ-NP-Za-km-z]{86,90}$/;\n\n/** Unambiguous secret-bearing field names (normalized: lowercased, separators stripped). */\nconst SECRET_FIELD_NAMES = new Set([\"privatekey\", \"secretkey\", \"mnemonic\", \"seedphrase\"]);\n\nfunction normalizeFieldName(key: string): string {\n return key.toLowerCase().replace(/[\\s_-]/g, \"\");\n}\n\nfunction looksLikeKeypairByteArray(arr: unknown[]): boolean {\n // Solana keypair secret = 64 bytes; raw secret seed = 32 bytes.\n if (arr.length !== 64 && arr.length !== 32) return false;\n return arr.every((n) => typeof n === \"number\" && Number.isInteger(n) && n >= 0 && n <= 255);\n}\n\nfunction scanString(value: string): string | null {\n if (PEM_PRIVATE_KEY.test(value)) return \"PEM private key block\";\n if (AWS_ACCESS_KEY_ID.test(value)) return \"AWS access key id\";\n if (BASE58_64_BYTE.test(value.trim())) return \"base58-encoded 64-byte secret key\";\n return null;\n}\n\n/**\n * Recursively scan an arbitrary JSON-like value for obvious secret material.\n * Returns the first match as `{ path, reason }`, or `null` if none is found.\n */\nexport function scanForSecrets(\n value: unknown,\n path = \"$\",\n): { path: string; reason: string } | null {\n if (typeof value === \"string\") {\n const reason = scanString(value);\n return reason === null ? null : { path, reason };\n }\n if (Array.isArray(value)) {\n if (looksLikeKeypairByteArray(value)) {\n return { path, reason: \"array of bytes resembling an ed25519 keypair\" };\n }\n for (let i = 0; i < value.length; i++) {\n const hit = scanForSecrets(value[i], `${path}[${String(i)}]`);\n if (hit !== null) return hit;\n }\n return null;\n }\n if (value !== null && typeof value === \"object\") {\n for (const [k, v] of Object.entries(value)) {\n if (typeof v === \"string\" && v.length > 0 && SECRET_FIELD_NAMES.has(normalizeFieldName(k))) {\n return { path: `${path}.${k}`, reason: `field name \"${k}\" indicates a secret value` };\n }\n const hit = scanForSecrets(v, `${path}.${k}`);\n if (hit !== null) return hit;\n }\n return null;\n }\n return null;\n}\n\n/** Throws {@link SecretInMetadataError} if `value` contains obvious secret material. */\nexport function assertNoSecrets(value: unknown, context = \"$\"): void {\n const hit = scanForSecrets(value, context);\n if (hit !== null) {\n throw new SecretInMetadataError(hit.path, hit.reason);\n }\n}\n","import { MAX_DISPUTE_REASON_BYTES, MAX_PROOF_URI_BYTES } from \"../config.js\";\nimport { storableText } from \"./text.js\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function invariant(condition: boolean, message: string): asserts condition {\n if (!condition) {\n throw new Error(`Invariant violation: ${message}`);\n }\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Why `reason` cannot go on chain as a dispute reason, or null when it can. The program\n * counts UTF-8 bytes, so a short reason of multi-byte characters can still be too long.\n */\nexport function disputeReasonError(reason: string): string | null {\n if (!storableText(reason)) return \"reason must not hold U+0000\";\n if (reason.length === 0) return \"reason must not be empty\";\n const bytes = new TextEncoder().encode(reason).length;\n if (bytes > MAX_DISPUTE_REASON_BYTES) {\n return `reason is ${String(bytes)} bytes in UTF-8; the program accepts at most ${String(MAX_DISPUTE_REASON_BYTES)}`;\n }\n return null;\n}\n\n/** Schemes a stored deliverable or evidence URL may use: none that runs, inlines or reads files. */\nexport const SAFE_URL_SCHEMES = [\"http:\", \"https:\", \"ipfs:\", \"ar:\"] as const;\n\nexport function isSafeUrl(value: string): boolean {\n try {\n return (SAFE_URL_SCHEMES as readonly string[]).includes(new URL(value).protocol);\n } catch {\n return false;\n }\n}\n\n/**\n * Why `uri` cannot be submitted as a deliverable's `proofUri`, or null when it can. The on-chain\n * `proof_uri` allocation counts UTF-8 bytes, so a URI whose UTF-16 length fits can still be too long.\n */\nexport function proofUriError(uri: string): string | null {\n if (!storableText(uri)) return \"proofUri must not hold U+0000\";\n if (!isSafeUrl(uri)) return \"proofUri must be an http(s), ipfs or ar URL\";\n const bytes = new TextEncoder().encode(uri).length;\n if (bytes > MAX_PROOF_URI_BYTES) {\n return `proofUri is ${String(bytes)} bytes in UTF-8; the program allocates at most ${String(MAX_PROOF_URI_BYTES)}`;\n }\n return null;\n}\n\nexport * from \"./canonicalize.js\";\nexport * from \"./printable.js\";\nexport * from \"./secret-scan.js\";\n","// The one RPC URL redactor. A keyed RPC URL is a secret, never logged, and its key can sit\n// in the userinfo, a path segment, a query value or a subdomain. RPC clients quote the request URL\n// as written (fetch refuses a URL with userinfo by quoting it) or normalised (a slash before the\n// query, a lowercased host), and a provider's error body can echo a part alone, so each part is\n// removed on its own too. Root entry: no runtime web3.\nimport { PUBLIC_RPC_URLS } from \"./config.js\";\n\n// Shorter usernames, path segments and query values (`v1`, a `?v=1` value) are routing, not keys,\n// and would blank common text. A password, a host and the query as a whole go at any length.\nconst MIN_SECRET_LENGTH = 8;\n\n// Computed per call, not at module scope: every bundle of the root entry would run a top-level one.\nconst isPublicOrigin = (origin: string): boolean =>\n Object.values(PUBLIC_RPC_URLS).some((u) => new URL(u).origin === origin);\n\n/** `part` percent-decoded, or null when it does not decode. */\nfunction decoded(part: string): string | null {\n try {\n return decodeURIComponent(part);\n } catch {\n return null;\n }\n}\n\n/** `part` percent-encoded, or null when it holds a lone surrogate. */\nfunction encoded(part: string): string | null {\n try {\n return encodeURIComponent(part);\n } catch {\n return null;\n }\n}\n\n/**\n * A loopback host carries no key, and an operator needs it to see which local node failed. The\n * WHATWG parser normalises the hostname, so the check is on it exactly: `localhost`, an IPv4\n * address in 127.0.0.0/8 or `[::1]`, never a prefix or suffix of one.\n */\nfunction isLoopback(hostname: string): boolean {\n return (\n hostname === \"localhost\" ||\n hostname === \"[::1]\" ||\n /^127\\.(?:\\d{1,3})\\.(?:\\d{1,3})\\.(?:\\d{1,3})$/.test(hostname)\n );\n}\n\n/** The forms of `rpcUrl`, and of each part of it that can hold a key, that text may quote. */\nfunction secretsOf(rpcUrl: string): string[] {\n const secrets = [rpcUrl];\n let url: URL;\n try {\n url = new URL(rpcUrl);\n } catch {\n // An unparseable URL is removed as written.\n return secrets;\n }\n const long = (part: string | null): string[] =>\n part !== null && part.length >= MIN_SECRET_LENGTH ? [part] : [];\n secrets.push(url.href, url.password, decoded(url.password) ?? \"\", url.search.slice(1));\n secrets.push(...long(url.username), ...long(decoded(url.username)));\n for (const segment of url.pathname.split(\"/\")) {\n secrets.push(...long(segment), ...long(decoded(segment)));\n }\n for (const pair of url.search.slice(1).split(\"&\")) {\n secrets.push(...long(pair.slice(pair.indexOf(\"=\") + 1)));\n }\n for (const value of url.searchParams.values()) {\n secrets.push(...long(value), ...long(encoded(value)));\n }\n if (!isPublicOrigin(url.origin) && !isLoopback(url.hostname)) {\n secrets.push(url.host, url.hostname, ...long(url.hostname.split(\".\")[0] ?? \"\"));\n }\n return secrets;\n}\n\nconst escapeRegExp = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * `text` with each RPC URL, and each of its key-bearing parts, replaced by `replacement`: the URL\n * as written and as its href (loopback included); the password at any length, as written and\n * decoded; the username, path segments and query values of 8 characters or more, as written and\n * decoded; the query as a whole; and a private host (not a public RPC origin, not loopback) with\n * and without its port, and its first label. One pass, longest match first, so a replacement is\n * never itself rewritten. It never throws: an error path that throws can fall through to an\n * unredacted print.\n */\nexport function redactRpcUrl(\n text: string,\n rpcUrls: readonly (string | undefined)[],\n replacement = \"<rpcUrl>\",\n): string {\n const secrets = new Set<string>();\n for (const rpcUrl of rpcUrls) {\n if (rpcUrl === undefined || rpcUrl === \"\") continue;\n for (const secret of secretsOf(rpcUrl)) if (secret !== \"\") secrets.add(secret);\n }\n if (secrets.size === 0) return text;\n const pattern = [...secrets]\n .sort((a, b) => b.length - a.length)\n .map(escapeRegExp)\n .join(\"|\");\n return text.replace(new RegExp(pattern, \"g\"), () => replacement);\n}\n","import { createHash } from \"node:crypto\";\nimport nacl from \"tweetnacl\";\nimport bs58 from \"bs58\";\nimport type { Keypair } from \"@solana/web3.js\";\n\n/** Lowercase hex SHA-256 of a UTF-8 string. Use \"\" for no-body requests. */\nexport function hashBody(rawBody: string): string {\n return createHash(\"sha256\").update(rawBody, \"utf8\").digest(\"hex\");\n}\n\n/** Canonical signed message format shared by SDK (signing) and API (verification). */\nexport function buildSignedMessage(\n timestamp: number | string,\n method: string,\n fullPath: string,\n bodyHash: string,\n): string {\n return `escro:${String(timestamp)}:${method}:${fullPath}:${bodyHash}`;\n}\n\n/**\n * Build all auth headers from a raw Ed25519 secret key and its base58 wallet\n * address. This is the web3.js-free core of {@link signRequest}: callers that\n * cannot depend on `@solana/web3.js` (the Bot Kit CLI keeps its runtime light)\n * sign with the raw keyfile bytes here, so the header names and the `escro:`\n * message format live in exactly ONE place and cannot drift from the API's\n * verifier. `rawBody` is the raw UTF-8 request body; pass \"\" when there is none.\n */\nexport function signRequestRaw(\n secretKey: Uint8Array,\n walletAddress: string,\n method: string,\n fullPath: string,\n rawBody: string,\n): Record<string, string> {\n const timestamp = Date.now();\n const bodyHash = hashBody(rawBody);\n const message = buildSignedMessage(timestamp, method, fullPath, bodyHash);\n const sigBytes = nacl.sign.detached(new TextEncoder().encode(message), secretKey);\n return {\n \"x-wallet-address\": walletAddress,\n \"x-signature\": bs58.encode(sigBytes),\n \"x-timestamp\": String(timestamp),\n \"x-content-sha256\": bodyHash,\n };\n}\n\n/**\n * Build all auth headers needed for an authenticated request.\n * `rawBody` is the raw UTF-8 request body string; pass \"\" when there is no body.\n */\nexport function signRequest(\n wallet: Keypair,\n method: string,\n fullPath: string,\n rawBody: string,\n): Record<string, string> {\n return signRequestRaw(wallet.secretKey, wallet.publicKey.toBase58(), method, fullPath, rawBody);\n}\n","import nacl from \"tweetnacl\";\nimport bs58 from \"bs58\";\nimport { canonicalize } from \"./utils/canonicalize.js\";\nimport type { BotDescriptor, UnsignedBotDescriptor } from \"./types/bots.js\";\n\n/**\n * Canonical, deterministic byte-string a bot signs to prove authorship of its\n * capability descriptor, so anyone can verify the signature independently.\n * Excludes `signature` itself. Shared by the SDK/kit (signing)\n * and the API (verification) so both sides agree byte-for-byte.\n */\nexport function canonicalBotDescriptorMessage(descriptor: UnsignedBotDescriptor): string {\n // `canonicalize` sorts keys and drops undefined values, so an absent\n // `endpoint` is naturally excluded and signing is order-independent.\n return canonicalize({\n wallet: descriptor.wallet,\n role: descriptor.role,\n capabilities: descriptor.capabilities,\n serviceRef: descriptor.serviceRef,\n pricingHint: descriptor.pricingHint,\n endpoint: descriptor.endpoint,\n signedAt: descriptor.signedAt,\n });\n}\n\n/**\n * Sign an unsigned descriptor with the bot's Ed25519 secret key, returning the\n * base58 detached signature to attach as `BotDescriptor.signature`.\n */\nexport function signBotDescriptor(\n secretKey: Uint8Array,\n descriptor: UnsignedBotDescriptor,\n): string {\n const message = new TextEncoder().encode(canonicalBotDescriptorMessage(descriptor));\n return bs58.encode(nacl.sign.detached(message, secretKey));\n}\n\n/**\n * Verify a descriptor's `signature` against its own `wallet`. Returns false on a\n * wrong signer, a tampered field, or malformed encoding - never throws. This is\n * the document-level check any third party can run; the API also enforces it.\n */\nexport function verifyBotDescriptorSignature(descriptor: BotDescriptor): boolean {\n try {\n const { signature, ...unsigned } = descriptor;\n const message = new TextEncoder().encode(canonicalBotDescriptorMessage(unsigned));\n const signatureBytes = bs58.decode(signature);\n if (signatureBytes.length !== 64) return false;\n const pubkeyBytes = bs58.decode(descriptor.wallet);\n if (pubkeyBytes.length !== 32) return false;\n return nacl.sign.detached.verify(message, signatureBytes, pubkeyBytes);\n } catch {\n return false;\n }\n}\n","import type { VersionedTransactionResponse } from \"@solana/web3.js\";\n\nimport type { SettlementCause } from \"./types/escrow.js\";\n\n/**\n * The single escrow-instruction table: every instruction that acts on one\n * escrow account, with its Anchor discriminator, the account indices of the\n * escrow PDA and the signing actor, and the settlement cause for the settling\n * instructions (null for the lifecycle ones). A test locks it to the program's\n * committed IDL. Remaining per-package copies migrate here.\n */\nexport const ESCROW_INSTRUCTION_NAMES = [\n \"create_escrow\",\n \"claim_task\",\n \"submit_deliverable\",\n \"raise_dispute\",\n \"cancel_escrow\",\n \"release_payment\",\n \"timeout_release\",\n \"refund_buyer\",\n \"arbitration_release\",\n \"arbitration_refund\",\n] as const;\n\nexport type EscrowInstructionName = (typeof ESCROW_INSTRUCTION_NAMES)[number];\n\nexport interface EscrowInstructionSpec {\n readonly discriminator: Uint8Array;\n readonly escrowAccountIndex: number;\n readonly signerAccountIndex: number;\n readonly cause: SettlementCause | null;\n}\n\nfunction spec(\n discriminator: number[],\n escrowAccountIndex: number,\n cause: SettlementCause | null,\n): EscrowInstructionSpec {\n return {\n discriminator: Uint8Array.from(discriminator),\n escrowAccountIndex,\n signerAccountIndex: 0,\n cause,\n };\n}\n\nexport const ESCROW_INSTRUCTIONS: Readonly<Record<EscrowInstructionName, EscrowInstructionSpec>> = {\n create_escrow: spec([253, 215, 165, 116, 36, 108, 68, 80], 4, null),\n claim_task: spec([49, 222, 219, 238, 155, 68, 221, 136], 1, null),\n submit_deliverable: spec([38, 137, 64, 44, 237, 11, 125, 101], 1, null),\n raise_dispute: spec([41, 243, 1, 51, 150, 95, 246, 73], 1, null),\n cancel_escrow: spec([156, 203, 54, 179, 38, 72, 33, 21], 3, \"CANCELLED\"),\n release_payment: spec([24, 34, 191, 86, 145, 160, 183, 233], 3, \"EXPLICIT_RELEASE\"),\n timeout_release: spec([98, 176, 26, 12, 83, 105, 154, 68], 3, \"TIMEOUT_RELEASE\"),\n refund_buyer: spec([199, 139, 203, 146, 192, 150, 53, 218], 3, \"DEADLINE_REFUND\"),\n arbitration_release: spec([118, 157, 141, 26, 104, 117, 94, 229], 4, \"ARBITRATION_RELEASE\"),\n arbitration_refund: spec([255, 194, 84, 248, 185, 249, 120, 122], 4, \"ARBITRATION_REFUND\"),\n};\n\n/** A landed transaction reduced to what instruction matching needs. */\nexport interface TransactionView {\n /** Static keys, then loaded writable, then loaded readonly addresses (base58). */\n readonly accountKeys: readonly string[];\n readonly instructions: readonly {\n readonly programIdIndex: number;\n readonly accountKeyIndexes: readonly number[];\n readonly data: Uint8Array;\n }[];\n}\n\nexport interface EscrowInstructionMatch {\n name: EscrowInstructionName;\n /** The account at the instruction's signer index (base58). */\n signer: string;\n data: Uint8Array;\n}\n\n/** The table's entry whose discriminator opens `data`, of any program or escrow; null for none. */\nexport function escrowInstructionName(data: Uint8Array): EscrowInstructionName | null {\n for (const name of ESCROW_INSTRUCTION_NAMES) {\n const disc = ESCROW_INSTRUCTIONS[name].discriminator;\n if (disc.every((b, i) => data[i] === b)) return name;\n }\n return null;\n}\n\n/**\n * Every TOP-LEVEL instruction of `programId` in the transaction whose\n * discriminator is in the table and whose escrow account is `escrowPda`.\n * Instructions reached by CPI are not matched: settlement is classified from\n * top-level instructions only.\n */\nexport function findEscrowInstructions(\n view: TransactionView,\n opts: { programId: string; escrowPda: string },\n): EscrowInstructionMatch[] {\n const matches: EscrowInstructionMatch[] = [];\n for (const ix of view.instructions) {\n if (view.accountKeys[ix.programIdIndex] !== opts.programId) continue;\n const name = escrowInstructionName(ix.data);\n if (name === null) continue;\n const entry = ESCROW_INSTRUCTIONS[name];\n const escrowKeyIndex = ix.accountKeyIndexes[entry.escrowAccountIndex];\n const signerKeyIndex = ix.accountKeyIndexes[entry.signerAccountIndex];\n if (escrowKeyIndex === undefined || signerKeyIndex === undefined) continue;\n if (view.accountKeys[escrowKeyIndex] !== opts.escrowPda) continue;\n const signer = view.accountKeys[signerKeyIndex];\n if (signer === undefined) continue;\n matches.push({ name, signer, data: ix.data });\n }\n return matches;\n}\n\ninterface Base58Key {\n toBase58(): string;\n}\n\n/** The fields of a `getTransaction` response that {@link toTransactionView} reads. */\nexport interface TransactionResponseLike {\n transaction: {\n message: {\n staticAccountKeys: readonly Base58Key[];\n compiledInstructions: readonly {\n programIdIndex: number;\n accountKeyIndexes: readonly number[];\n data: Uint8Array;\n }[];\n };\n };\n meta: {\n loadedAddresses?: { writable: readonly Base58Key[]; readonly: readonly Base58Key[] };\n } | null;\n}\n\n// A web3 VersionedTransactionResponse is accepted as-is.\ntype _AcceptsWeb3Response = VersionedTransactionResponse extends TransactionResponseLike\n ? true\n : never;\nconst _acceptsWeb3Response: _AcceptsWeb3Response = true;\nvoid _acceptsWeb3Response;\n\n/** Adapt a landed (legacy or v0, lookup-table-aware) transaction to a {@link TransactionView}. */\nexport function toTransactionView(response: TransactionResponseLike): TransactionView {\n const { message } = response.transaction;\n const loaded = response.meta?.loadedAddresses;\n const accountKeys = [\n ...message.staticAccountKeys,\n ...(loaded?.writable ?? []),\n ...(loaded?.readonly ?? []),\n ].map((k) => k.toBase58());\n return { accountKeys, instructions: message.compiledInstructions };\n}\n","import bs58 from \"bs58\";\nimport { ESCROW_INSTRUCTIONS } from \"./instructions.js\";\n\n// The decoders invert the encoders: the SDK checks a server-built instruction through them\n// before signing.\n\nfunction borshString(s: string): Buffer {\n const bytes = Buffer.from(s, \"utf8\");\n const len = Buffer.allocUnsafe(4);\n len.writeUInt32LE(bytes.length, 0);\n return Buffer.concat([len, bytes]);\n}\n\nfunction borshU64(n: bigint): Buffer {\n const buf = Buffer.allocUnsafe(8);\n buf.writeBigUInt64LE(n, 0);\n return buf;\n}\n\nfunction borshI64(n: bigint): Buffer {\n const buf = Buffer.allocUnsafe(8);\n buf.writeBigInt64LE(n, 0);\n return buf;\n}\n\nfunction borshOption(payload: Buffer | null): Buffer {\n if (payload === null) return Buffer.from([0]);\n return Buffer.concat([Buffer.from([1]), payload]);\n}\n\nfunction disc(name: \"create_escrow\" | \"submit_deliverable\" | \"raise_dispute\"): Buffer {\n return Buffer.from(ESCROW_INSTRUCTIONS[name].discriminator);\n}\n\nexport interface CreateEscrowArgs {\n taskId: string;\n amount: bigint;\n deadline: bigint;\n specHash: string;\n /** base58 on decode; raw 32 bytes on encode. */\n assignedWorker: string | null;\n}\n\nexport function encodeCreateEscrowArgs(\n args: Omit<CreateEscrowArgs, \"assignedWorker\"> & { assignedWorker: Uint8Array | null },\n): Buffer {\n return Buffer.concat([\n disc(\"create_escrow\"),\n borshString(args.taskId),\n borshU64(args.amount),\n borshI64(args.deadline),\n borshString(args.specHash),\n borshOption(args.assignedWorker === null ? null : Buffer.from(args.assignedWorker)),\n ]);\n}\n\nexport function encodeSubmitDeliverableArgs(args: {\n deliverableHash: string;\n proofUri: string | null;\n}): Buffer {\n return Buffer.concat([\n disc(\"submit_deliverable\"),\n borshString(args.deliverableHash),\n borshOption(args.proofUri === null ? null : borshString(args.proofUri)),\n ]);\n}\n\nexport function encodeRaiseDisputeArgs(reason: string): Buffer {\n return Buffer.concat([disc(\"raise_dispute\"), borshString(reason)]);\n}\n\n/** Sequential Borsh reader over instruction data, past the 8-byte discriminator. */\nclass Reader {\n private offset = 8;\n constructor(private readonly buf: Buffer) {}\n\n private take(n: number): Buffer {\n if (this.offset + n > this.buf.length) {\n throw new Error(\n `instruction data truncated: need ${String(n)} bytes at offset ${String(this.offset)}, have ${String(this.buf.length)}`,\n );\n }\n const out = this.buf.subarray(this.offset, this.offset + n);\n this.offset += n;\n return out;\n }\n\n u8(): number {\n return this.take(1).readUInt8(0);\n }\n u64(): bigint {\n return this.take(8).readBigUInt64LE(0);\n }\n i64(): bigint {\n return this.take(8).readBigInt64LE(0);\n }\n string(): string {\n const len = this.take(4).readUInt32LE(0);\n return this.take(len).toString(\"utf8\");\n }\n option<T>(read: () => T): T | null {\n return this.u8() === 0 ? null : read();\n }\n bytes(n: number): Buffer {\n return this.take(n);\n }\n}\n\nexport function decodeCreateEscrowArgs(data: Uint8Array): CreateEscrowArgs {\n const r = new Reader(Buffer.from(data));\n return {\n taskId: r.string(),\n amount: r.u64(),\n deadline: r.i64(),\n specHash: r.string(),\n assignedWorker: r.option(() => bs58.encode(r.bytes(32))),\n };\n}\n\nexport function decodeSubmitDeliverableArgs(data: Uint8Array): {\n deliverableHash: string;\n proofUri: string | null;\n} {\n const r = new Reader(Buffer.from(data));\n return { deliverableHash: r.string(), proofUri: r.option(() => r.string()) };\n}\n\nexport function decodeRaiseDisputeArgs(data: Uint8Array): { reason: string } {\n return { reason: new Reader(Buffer.from(data)).string() };\n}\n\n/** `amount_usdc` is numeric whole-USDC; the chain carries u64 micro-USDC. */\nexport function microToUsdcString(micro: bigint): string {\n const whole = micro / 1_000_000n;\n const frac = (micro % 1_000_000n).toString().padStart(6, \"0\");\n return `${whole.toString()}.${frac}`;\n}\n","// Program-derived addresses, the one off-chain copy of the program's seeds. Each takes the\n// program id, so localnet and ad hoc ids derive the same way as the pinned clusters.\nimport { PublicKey } from \"@solana/web3.js\";\n\nconst utf8 = (s: string): Uint8Array => new TextEncoder().encode(s);\n\n/** EscrowAccount: seeds `[b\"escrow\", buyer, task_id]` (create_escrow.rs); `taskId` is at most 32 bytes. */\nexport function deriveEscrowPda(programId: PublicKey, buyer: PublicKey, taskId: string): PublicKey {\n return PublicKey.findProgramAddressSync(\n [utf8(\"escrow\"), buyer.toBytes(), utf8(taskId)],\n programId,\n )[0];\n}\n\n/** PlatformConfig: seeds `[b\"config\"]`, with the canonical bump the account stores. */\nexport function findPlatformConfigPda(programId: PublicKey): [PublicKey, number] {\n return PublicKey.findProgramAddressSync([utf8(\"config\")], programId);\n}\n\nexport function derivePlatformConfigPda(programId: PublicKey): PublicKey {\n return findPlatformConfigPda(programId)[0];\n}\n\n/** AdminConfig: seeds `[b\"admin\"]`. */\nexport function deriveAdminConfigPda(programId: PublicKey): PublicKey {\n return PublicKey.findProgramAddressSync([utf8(\"admin\")], programId)[0];\n}\n\n/**\n * ProgramData: seeds `[program id]` under the upgradeable loader. The loader key is built here, not\n * at module scope: a top-level `PublicKey` would run in every bundle that takes `./solana`.\n */\nexport function deriveProgramDataPda(programId: PublicKey): PublicKey {\n const loader = new PublicKey(\"BPFLoaderUpgradeab1e11111111111111111111111\");\n return PublicKey.findProgramAddressSync([programId.toBuffer()], loader)[0];\n}\n\n/** The base-58 of 32 bytes is at most 44 characters (32 bytes of 0xff), so no longer string is a key. */\nconst MAX_PUBKEY_CHARS = 44;\n\n/**\n * A base58 public key exactly as web3.js prints it, untrimmed: the form wallets compare in. It\n * shares this module's web3 import: in a module of its own, esbuild keeps that module's import\n * in every `./solana` bundle (a bundle of ./solana gains a web3 require it never calls), used or not.\n * The length is checked before the decode, whose cost grows with the square of the length.\n */\nexport function isCanonicalPubkey(s: string): boolean {\n try {\n // Inside the try: an untyped caller's undefined or null is refused, not thrown.\n if (s.length > MAX_PUBKEY_CHARS) return false;\n return new PublicKey(s).toBase58() === s;\n } catch {\n return false;\n }\n}\n","// The PlatformConfig account layout, the one off-chain copy; a test locks it to the program's\n// committed IDL.\nimport bs58 from \"bs58\";\n\n/** Byte offsets after the 8-byte discriminator, and the account length. */\nexport const PLATFORM_CONFIG_LAYOUT = {\n version: 8,\n fee_bps: 9,\n oracle_authority: 11,\n usdc_mint: 43,\n treasury: 75,\n bump: 107,\n length: 108,\n} as const;\n\n/** `sha256(\"account:PlatformConfig\")[0..8]`. */\nexport const PLATFORM_CONFIG_DISCRIMINATOR: readonly number[] = [\n 160, 78, 128, 0, 248, 83, 230, 160,\n];\n\nexport interface PlatformConfigAccount {\n version: number;\n feeBps: number;\n oracleAuthority: string;\n usdcMint: string;\n treasury: string;\n bump: number;\n}\n\n/**\n * Decode PlatformConfig account data. Throws on a wrong length or discriminator; the\n * version is returned for the caller to check against `CURRENT_ACCOUNT_VERSION`.\n */\nexport function decodePlatformConfig(data: Uint8Array): PlatformConfigAccount {\n const L = PLATFORM_CONFIG_LAYOUT;\n if (data.length !== L.length) {\n throw new Error(\n `PlatformConfig account is ${String(data.length)} bytes, expected ${String(L.length)}`,\n );\n }\n if (PLATFORM_CONFIG_DISCRIMINATOR.some((byte, i) => data[i] !== byte)) {\n throw new Error(\"PlatformConfig discriminator mismatch: not a PlatformConfig account\");\n }\n const byte = (at: number): number => data[at] ?? 0;\n const key = (at: number): string => bs58.encode(data.subarray(at, at + 32));\n return {\n version: byte(L.version),\n feeBps: byte(L.fee_bps) | (byte(L.fee_bps + 1) << 8),\n oracleAuthority: key(L.oracle_authority),\n usdcMint: key(L.usdc_mint),\n treasury: key(L.treasury),\n bump: byte(L.bump),\n };\n}\n","import type { SettlementResponse } from \"@escro/shared\";\n\n/** Docs for the payment rails, linked from the rail-not-enabled error and the kit config's rejection\n * message so both point to the same place. Re-exported from `payments.ts`. */\nexport const RAILS_DOCS_URL = \"https://escro.ai/rails\";\n\n/**\n * Base class for all errors thrown by the @escro/sdk. `retryAfterMs` is the\n * server's Retry-After delay, when it sent one in seconds; `options.cause` is the\n * failure this error reports.\n */\nexport class EscroError extends Error {\n constructor(\n message: string,\n public readonly code = \"ESCRO_ERROR\",\n public readonly retryAfterMs?: number,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = \"EscroError\";\n }\n}\n\n/** The requested escrow was not found (HTTP 404). */\nexport class EscrowNotFoundError extends EscroError {\n constructor(address: string) {\n super(`Escrow not found: ${address}`, \"ESCROW_NOT_FOUND\");\n this.name = \"EscrowNotFoundError\";\n }\n}\n\n/**\n * The reputation endpoint is not available on this deployment (HTTP 404). A 404\n * from `GET /rep` means no `ReputationSource` is mounted (the surface is\n * unmounted), NOT that a wallet is unknown - unknown wallets return zeroed raw\n * components, never a 404. Kept distinct from {@link EscrowNotFoundError}, whose\n * 404 is about a missing escrow.\n */\nexport class ReputationUnavailableError extends EscroError {\n constructor() {\n super(\n \"Reputation endpoint is unavailable (HTTP 404): this deployment has no reputation source mounted.\",\n \"REPUTATION_UNAVAILABLE\",\n );\n this.name = \"ReputationUnavailableError\";\n }\n}\n\n/** The operation is not valid for the escrow's current state (HTTP 409). */\nexport class EscrowStateError extends EscroError {\n constructor(message: string) {\n super(message, \"ESCROW_INVALID_STATE\");\n this.name = \"EscrowStateError\";\n }\n}\n\n/** Polling timed out after 24 hours without reaching the expected state. */\nexport class EscrowTimeoutError extends EscroError {\n constructor(address: string) {\n super(`Polling timed out after 24h for escrow: ${address}`, \"ESCROW_TIMEOUT\");\n this.name = \"EscrowTimeoutError\";\n }\n}\n\n/**\n * A transaction landed (or was sent) but the API did not record it. `code` is the\n * server's code (e.g. TX_MISMATCH, TX_FAILED, or TX_NOT_FOUND after the retry\n * window), `NETWORK_ERROR` when the last attempt never reached the API, or\n * `HTTP_<status>` when the answer carried no code. Call {@link Escro.confirm} again\n * with `address` and `signature` to retry, no sooner than `retryAfterMs` when the\n * API sent one.\n */\nexport class EscroConfirmError extends EscroError {\n constructor(\n public readonly address: string,\n public readonly signature: string,\n code: string,\n message: string,\n retryAfterMs?: number,\n ) {\n super(\n `Confirm failed for escrow ${address} (signature ${signature}): ${message}`,\n code,\n retryAfterMs,\n );\n this.name = \"EscroConfirmError\";\n }\n}\n\n/** The caller is not authorized to perform this action (HTTP 401/403). */\nexport class UnauthorizedError extends EscroError {\n constructor(message = \"Unauthorized\") {\n super(message, \"UNAUTHORIZED\");\n this.name = \"UnauthorizedError\";\n }\n}\n\n/**\n * A payment rail is not available. {@link Escro.pay} throws this for the `x402` rail when its\n * packages fail to load (`cause` is the load failure); nothing was signed and nothing is counted.\n * `rail` names the unavailable rail.\n */\nexport class EscroRailNotEnabledError extends EscroError {\n constructor(\n public readonly rail: string,\n options?: { cause?: unknown },\n ) {\n super(\n `Payment rail \"${rail}\" is not available in this installation. See ${RAILS_DOCS_URL}`,\n \"ESCRO_RAIL_NOT_ENABLED\",\n undefined,\n options,\n );\n this.name = \"EscroRailNotEnabledError\";\n }\n}\n\n/**\n * Sets an own property on a thrown value and leaves the value itself alone: its class, name and\n * message stay what a classifier reads. A non-object, or a frozen one, is left as it is.\n */\nexport function attachToError(err: unknown, field: string, value: string): void {\n if (typeof err !== \"object\" || err === null) return;\n Reflect.defineProperty(err, field, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n}\n\n/** Why {@link Escro.pay} refused a payment; see {@link EscroPayError}. */\nexport type PayRefusal =\n | \"no_offer\"\n | \"both_offers\"\n | \"url\"\n | \"request_header\"\n | \"request\"\n | \"redirect\"\n | \"not_402\"\n | \"resource_mismatch\"\n | \"no_eligible_entry\"\n | \"timeout_ceiling\"\n | \"policy_choice\"\n | \"unsupported_scheme\"\n | \"scheme_conflict\"\n | \"presentation\"\n | \"settlement\"\n | \"timeout\"\n | \"requirements\"\n | \"transaction\"\n | \"host\";\n\n/**\n * {@link Escro.pay} refused, or the payment router refused a scheme; `reason` names the check and\n * `detail` the offending value where there is one. Once the escrow is created, `escrowPda` and\n * `createSignature` are set: the escrow is funded, and `cancelEscrow(escrowPda)` recovers the\n * deposit while it is Funded. `status` is the paid request's HTTP status when it answered. On the\n * x402 rail a failure after the payment left the process carries `payment`, and no `escrowPda`. A\n * paid request answered with an error status carries `settlement` when the answer's\n * `PAYMENT-RESPONSE` decodes with a boolean `success` and a string `transaction` and `network`:\n * the worker's own unverified report, whatever its `success`.\n */\nexport class EscroPayError extends EscroError {\n readonly reason: PayRefusal;\n readonly detail?: string;\n readonly escrowPda?: string;\n readonly createSignature?: string;\n readonly status?: number;\n /**\n * What a failed x402 settlement can be matched by against the wallet's token-account history, in\n * case the resource server still lands the transfer: the Memo instruction's text (byte-exact),\n * the amount and `payTo`. Never the partially signed transaction.\n */\n readonly payment?: {\n readonly memo: string;\n readonly amountMicroUsdc: number;\n readonly payTo: string;\n };\n /** The `PAYMENT-RESPONSE` a worker sent beside an error status: its unverified word, as sent. */\n readonly settlement?: SettlementResponse;\n\n constructor(\n reason: PayRefusal,\n message: string,\n options: {\n detail?: string;\n escrowPda?: string;\n createSignature?: string;\n status?: number;\n payment?: EscroPayError[\"payment\"];\n settlement?: SettlementResponse;\n cause?: unknown;\n } = {},\n ) {\n super(\n message,\n \"PAY_REFUSED\",\n undefined,\n \"cause\" in options ? { cause: options.cause } : undefined,\n );\n this.name = \"EscroPayError\";\n this.reason = reason;\n if (options.detail !== undefined) this.detail = options.detail;\n if (options.escrowPda !== undefined) this.escrowPda = options.escrowPda;\n if (options.createSignature !== undefined) this.createSignature = options.createSignature;\n if (options.status !== undefined) this.status = options.status;\n if (options.payment !== undefined) this.payment = options.payment;\n if (options.settlement !== undefined) this.settlement = options.settlement;\n }\n}\n","import { isCanonicalPubkey } from \"@escro/shared/solana\";\nimport { EscroError } from \"./errors.js\";\n\n/** Why an address argument was refused; the refusal names the parameter, never the value. */\nexport const PUBLIC_KEY_ISSUE = \"must be a base-58 public key\";\n\n/**\n * Throws an {@link EscroError} with code `VALIDATION_ERROR` unless `value` is a public key exactly\n * as web3.js prints it. Every address the SDK puts in a request path or query passes here first,\n * so a malformed one reaches no such request. The message leaves the\n * value out: it is caller input, and may be anything.\n */\nexport function assertPublicKey(param: string, value: unknown): asserts value is string {\n if (typeof value !== \"string\" || !isCanonicalPubkey(value)) {\n throw new EscroError(`${param} ${PUBLIC_KEY_ISSUE}`, \"VALIDATION_ERROR\");\n }\n}\n","import { signRequest } from \"@escro/shared\";\nimport type { Keypair } from \"@solana/web3.js\";\nimport type {\n BotDescriptor,\n EscrowAccount,\n EscrowErrorCode,\n EscrowState,\n OutstandingDeposits,\n} from \"@escro/shared\";\nimport type { ReputationExport, ServedWalletReputation } from \"@escro/reputation\";\nimport type {\n CreateEscrowParams,\n ListBotsParams,\n PaginatedResult,\n RaiseDisputeParams,\n SerializedEscrow,\n SubmitDeliverableParams,\n} from \"./types.js\";\nimport {\n EscroError,\n EscrowNotFoundError,\n EscrowStateError,\n ReputationUnavailableError,\n UnauthorizedError,\n} from \"./errors.js\";\nimport { assertPublicKey } from \"./public-key.js\";\n\nfunction authHeaders(\n wallet: Keypair,\n method: string,\n path: string,\n rawBody = \"\",\n): Record<string, string> {\n return signRequest(wallet, method, path, rawBody);\n}\n\nfunction deserialize(raw: SerializedEscrow): EscrowAccount {\n return { ...raw, amount: BigInt(raw.amount) };\n}\n\nasync function handleError(res: Response, address?: string): Promise<never> {\n const body = (await res.json().catch(() => ({}))) as {\n error?: string;\n code?: string;\n };\n const msg = body.error ?? `HTTP ${String(res.status)}`;\n if (res.status === 404) throw new EscrowNotFoundError(address ?? msg);\n if (res.status === 409) throw new EscrowStateError(msg);\n if (res.status === 401 || res.status === 403) throw new UnauthorizedError(msg);\n throw new EscroError(msg, body.code ?? \"UNKNOWN\", retryAfterMs(res.headers.get(\"retry-after\")));\n}\n\n/** Retry-After in whole seconds, as milliseconds; an HTTP-date is ignored. */\nfunction retryAfterMs(header: string | null): number | undefined {\n return header !== null && /^\\d+$/.test(header.trim()) ? Number(header.trim()) * 1000 : undefined;\n}\n\n/**\n * How long the outstanding-deposits read and the create POST may take, body included, before\n * they are abandoned with code `API_TIMEOUT`. A spend-capped create holds its wallet's admission\n * across both, so a stalled API would otherwise block every later create of that wallet.\n */\nexport const API_REQUEST_TIMEOUT_MS = 15_000;\n\n/** Runs `request` with a signal that aborts it after {@link API_REQUEST_TIMEOUT_MS}. */\nasync function bounded<T>(what: string, request: (signal: AbortSignal) => Promise<T>): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort();\n }, API_REQUEST_TIMEOUT_MS);\n try {\n return await request(controller.signal);\n } catch (err) {\n if (!controller.signal.aborted) throw err;\n throw new EscroError(\n `${what} did not answer within ${String(API_REQUEST_TIMEOUT_MS / 1000)} s`,\n \"API_TIMEOUT\",\n undefined,\n { cause: err },\n );\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport class ApiClient {\n constructor(\n private readonly baseUrl: string,\n private readonly wallet: Keypair,\n ) {\n const url = new URL(baseUrl);\n const isLocalhost = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\";\n if (url.protocol !== \"https:\" && !isLocalhost) {\n throw new Error(\"apiUrl must use HTTPS in production\");\n }\n }\n\n private url(path: string): string {\n return `${this.baseUrl}${path}`;\n }\n\n /** GET /v1/escrows/:address */\n async getEscrow(address: string): Promise<EscrowAccount> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res, address);\n return deserialize((await res.json()) as SerializedEscrow);\n }\n\n /** GET /v1/escrows?assignedTo=...&maker=...&taker=...&state=... */\n async listEscrows(params: {\n assignedTo?: string;\n maker?: string;\n taker?: string;\n state?: EscrowState;\n limit?: number;\n offset?: number;\n }): Promise<PaginatedResult<EscrowAccount>> {\n const qs = new URLSearchParams();\n for (const filter of [\"assignedTo\", \"maker\", \"taker\"] as const) {\n const value = params[filter];\n if (value === undefined) continue;\n assertPublicKey(filter, value);\n qs.set(filter, value);\n }\n if (params.state) qs.set(\"state\", params.state);\n if (params.limit != null) qs.set(\"limit\", String(params.limit));\n if (params.offset != null) qs.set(\"offset\", String(params.offset));\n\n const path = `/v1/escrows?${qs.toString()}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n const body = (await res.json()) as {\n items: SerializedEscrow[];\n total: number;\n limit: number;\n offset: number;\n };\n return {\n items: body.items.map(deserialize),\n total: body.total,\n limit: body.limit,\n offset: body.offset,\n };\n }\n\n /**\n * GET /v1/bots?capability=...&role=...&limit=...&offset= : EscroBots registry\n * read. Unauthenticated public read (no auth headers). Returns descriptors in\n * registry order (newest first); descriptors are self-reported claims.\n */\n async listBots(params: ListBotsParams): Promise<PaginatedResult<BotDescriptor>> {\n const qs = new URLSearchParams();\n if (params.capability != null) qs.set(\"capability\", params.capability);\n if (params.role != null) qs.set(\"role\", params.role);\n if (params.limit != null) qs.set(\"limit\", String(params.limit));\n if (params.offset != null) qs.set(\"offset\", String(params.offset));\n\n const path = `/v1/bots?${qs.toString()}`;\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n const body = (await res.json()) as {\n items: BotDescriptor[];\n total: number;\n limit: number;\n offset: number;\n };\n return { items: body.items, total: body.total, limit: body.limit, offset: body.offset };\n }\n\n /**\n * GET /rep : EscroRep bulk export. Unauthenticated public\n * read (no auth headers). Returns every indexed wallet's RAW components exactly\n * once (no composite score). Ranking layers join against this ONE bulk fetch:\n * the per-wallet endpoint shares a 10/min public-metrics budget, so a\n * per-candidate fan-out would rate-limit itself. A 404 means the deployment\n * mounted no reputation source (unknown wallets return zeroed rep, never 404),\n * so it surfaces as {@link ReputationUnavailableError}, not EscrowNotFoundError.\n */\n async listReputations(): Promise<ServedWalletReputation[]> {\n const res = await fetch(this.url(\"/rep\"));\n if (!res.ok) {\n if (res.status === 404) throw new ReputationUnavailableError();\n await handleError(res);\n }\n const body = (await res.json()) as ReputationExport;\n return body.wallets;\n }\n\n /**\n * GET /rep/:wallet : one wallet's EscroRep RAW components.\n * Unauthenticated public read (no auth headers). Unknown wallets return zeroed\n * components, never 404; a 404 means the deployment mounted no reputation\n * source and surfaces as {@link ReputationUnavailableError}. Shares the public\n * per-wallet rate budget with every other caller, so fan-outs should use\n * {@link listReputations} instead.\n */\n async getReputation(wallet: string): Promise<ServedWalletReputation> {\n assertPublicKey(\"wallet\", wallet);\n const res = await fetch(this.url(`/rep/${encodeURIComponent(wallet)}`));\n if (!res.ok) {\n if (res.status === 404) throw new ReputationUnavailableError();\n await handleError(res);\n }\n return (await res.json()) as ServedWalletReputation;\n }\n\n /**\n * GET /v1/escrows/outstanding?maker=: the maker's open deposits (FUNDED, IN_PROGRESS,\n * SUBMITTED, DISPUTED; never CREATED). Unauthenticated. Abandoned with code `API_TIMEOUT`\n * after {@link API_REQUEST_TIMEOUT_MS}.\n */\n async getOutstandingDeposits(maker: string): Promise<OutstandingDeposits> {\n assertPublicKey(\"maker\", maker);\n const path = `/v1/escrows/outstanding?${new URLSearchParams({ maker }).toString()}`;\n return bounded(`GET ${path}`, async (signal) => {\n const res = await fetch(this.url(path), { signal });\n if (!res.ok) await handleError(res);\n return (await res.json()) as OutstandingDeposits;\n });\n }\n\n /**\n * POST /v1/escrows: registers the escrow and returns its ids and the unsigned\n * `create_escrow`. Requires auth. Abandoned with code `API_TIMEOUT` after\n * {@link API_REQUEST_TIMEOUT_MS}.\n */\n async createEscrow(params: CreateEscrowParams): Promise<{\n escrowId: string;\n escrowPda: string;\n unsignedTx: string;\n }> {\n const path = \"/v1/escrows\";\n const bodyObj: Record<string, unknown> = {\n taskSpec: params.taskSpec,\n amountUsdc: params.amountUsdc,\n deadlineUnix: params.deadlineUnix,\n assignedWorker: params.assignedWorker,\n };\n\n const rawBody = JSON.stringify(bodyObj);\n return bounded(`POST ${path}`, async (signal) => {\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n signal,\n });\n if (!res.ok) await handleError(res);\n return (await res.json()) as { escrowId: string; escrowPda: string; unsignedTx: string };\n });\n }\n\n /**\n * POST /v1/escrows/:address/claim: returns unsigned tx.\n * Requires auth (worker).\n */\n async claimTask(address: string): Promise<{ unsignedTx: string }> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/claim`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/submit: returns unsigned tx.\n * Requires auth (worker).\n */\n async submitDeliverable(\n address: string,\n params: SubmitDeliverableParams,\n ): Promise<{ unsignedTx: string }> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/submit`;\n const rawBody = JSON.stringify({\n contentHash: params.contentHash,\n proofUri: params.proofUri,\n });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/release: records the landed release once the API's RPC shows\n * the escrow closed. Requires auth (buyer). No on-chain tx returned. A 409\n * `ESCROW_NOT_SETTLED`, a 5xx or a 429 throws an {@link EscroError} with the server's code,\n * or `HTTP_<status>` when the answer carries none; {@link Escro.releasePaymentWithOutcome}\n * decides which to retry. Other refusals throw as every route does.\n */\n async releasePaymentDb(address: string): Promise<void> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/release`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (res.ok) return;\n if (res.status !== 409 && res.status !== 429 && res.status < 500) {\n await handleError(res, address);\n }\n const body = (await res.json().catch(() => ({}))) as { error?: string; code?: string };\n if (res.status === 409 && body.code !== (\"ESCROW_NOT_SETTLED\" satisfies EscrowErrorCode)) {\n throw new EscrowStateError(body.error ?? `HTTP ${String(res.status)}`);\n }\n throw new EscroError(\n body.error ?? `HTTP ${String(res.status)}`,\n body.code ?? `HTTP_${String(res.status)}`,\n retryAfterMs(res.headers.get(\"retry-after\")),\n );\n }\n\n /**\n * POST /v1/escrows/:address/cancel: returns unsigned tx.\n * Requires auth (buyer). Only valid when state is FUNDED.\n */\n async cancelEscrow(address: string): Promise<{ unsignedTx: string }> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/cancel`;\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: authHeaders(this.wallet, \"POST\", path),\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/dispute: returns unsigned tx.\n * Requires auth (buyer or worker).\n */\n async raiseDispute(\n address: string,\n params: Pick<RaiseDisputeParams, \"reason\">,\n ): Promise<{ unsignedTx: string }> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/dispute`;\n const rawBody = JSON.stringify({ reason: params.reason });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) await handleError(res, address);\n return res.json() as Promise<{ unsignedTx: string }>;\n }\n\n /**\n * POST /v1/escrows/:address/confirm: the API records the create, claim, submit,\n * cancel or dispute the landed `signature` carries, after verifying it on chain.\n * A non-2xx answer throws an {@link EscroError} with the server's code, or\n * `HTTP_<status>` when the answer carries none; a network failure rejects with\n * fetch's own error. {@link Escro.confirm} decides which to retry.\n */\n async confirm(address: string, signature: string, evidence?: string): Promise<EscrowAccount> {\n assertPublicKey(\"address\", address);\n const path = `/v1/escrows/${encodeURIComponent(address)}/confirm`;\n const rawBody = JSON.stringify({ signature, evidence });\n const res = await fetch(this.url(path), {\n method: \"POST\",\n headers: {\n ...authHeaders(this.wallet, \"POST\", path, rawBody),\n \"content-type\": \"application/json\",\n },\n body: rawBody,\n });\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as { error?: string; code?: string };\n throw new EscroError(\n body.error ?? `HTTP ${String(res.status)}`,\n body.code ?? `HTTP_${String(res.status)}`,\n retryAfterMs(res.headers.get(\"retry-after\")),\n );\n }\n const body = (await res.json()) as { escrow: SerializedEscrow };\n return deserialize(body.escrow);\n }\n\n /**\n * GET /v1/stats: public protocol-wide stats.\n * No auth required. Upstream typing in {@link Escro.getStats} narrows the\n * return shape.\n */\n async getStats(): Promise<unknown> {\n const path = \"/v1/stats\";\n const res = await fetch(this.url(path));\n if (!res.ok) await handleError(res);\n return res.json();\n }\n}\n","/**\n * The dual-path payment surface: the escrow rail and the x402 rail behind one `pay()`.\n *\n * `pay()` reaches the escrow rail from a 402's `on-delivery` or `job-escrow` entry and\n * the x402 rail from an `exact` entry. Every name here is a FREEZE CONTRACT: a new rail\n * or field must not be a breaking change for any kit-generated bot.\n * The shapes below are pinned by a type-level test; fields are added only as\n * OPTIONAL fields.\n */\nimport type {\n Acceptance,\n PaymentRequired,\n PaymentRequirements,\n ResourceInfo,\n SettlementResponse,\n} from \"@escro/shared\";\n\nimport { EscroPayError, EscroRailNotEnabledError } from \"./errors.js\";\n\nexport { RAILS_DOCS_URL } from \"./errors.js\";\n\n/** Single source for the rail identifiers. The {@link Rail} type is derived from\n * this list (drift-safe, mirroring the BOT_ROLES pattern in @escro/shared). */\nexport const RAILS = [\"escrow\", \"x402\"] as const;\n\n/** The payment rails Escro can route across. */\nexport type Rail = (typeof RAILS)[number];\n\n/** The rails enabled in this build. Typed `readonly Rail[]` (not the literal tuple) so\n * runtime membership checks stay honest: `ENABLED_RAILS.includes(rail)` narrows nothing\n * away. */\nexport const ENABLED_RAILS: readonly Rail[] = [\"escrow\", \"x402\"];\n\n/** The minimal payment shape a {@link PaymentRouter} inspects to choose a rail.\n * FROZEN; the x402 rail may add only optional fields. */\nexport interface TxShape {\n /** Recipient wallet address (base58). */\n readonly to: string;\n /** Amount to move, in USDC micro-units (integer, 6 decimals). */\n readonly amountMicroUsdc: number;\n /** `async` (verification-needed) work routes to escrow; `sync` work is x402's territory. */\n readonly mode: \"async\" | \"sync\";\n /** The 402 entry being paid; its `scheme` routes when `scheme` is absent. */\n readonly accept?: PaymentRequirements;\n /** The x402 scheme being paid; given with `accept`, the two must be equal. */\n readonly scheme?: string;\n}\n\n/** Chooses the rail for a payment, throwing rather than return a rail that is not\n * enabled. FROZEN signature. */\nexport interface PaymentRouter {\n selectRail(tx: TxShape): Rail;\n}\n\n/** The rail an x402 scheme routes to, or undefined for a scheme Escro does not route (exact match:\n * no case folding or trimming). */\nexport function railOfScheme(scheme: string): Rail | undefined {\n if (scheme === \"on-delivery\" || scheme === \"job-escrow\") return \"escrow\";\n if (scheme === \"exact\" || scheme === \"upto\") return \"x402\";\n return undefined;\n}\n\n/** The mode each rail serves: escrow is asynchronous work, x402 a synchronous payment. */\nconst RAIL_MODE: Readonly<Record<Rail, TxShape[\"mode\"]>> = { escrow: \"async\", x402: \"sync\" };\n\n/**\n * The router. With no scheme, async work routes to escrow and sync work prefers x402, falling back\n * to escrow when x402 is not enabled. With a scheme (`tx.scheme`, else `tx.accept.scheme`),\n * `on-delivery` and `job-escrow` route to escrow under `async`, `exact` and `upto` to x402 under\n * `sync`. It throws {@link EscroPayError} `scheme_conflict` when `scheme` and `accept.scheme`\n * differ or the mode is not the scheme's, `unsupported_scheme` for any other scheme, and\n * {@link EscroRailNotEnabledError} for a scheme whose rail is not enabled: a scheme's rail is never\n * swapped for another.\n */\nexport class EscrowPaymentRouter implements PaymentRouter {\n selectRail(tx: TxShape): Rail {\n const { scheme, accept } = tx;\n if (scheme !== undefined && accept !== undefined && scheme !== accept.scheme) {\n throw new EscroPayError(\n \"scheme_conflict\",\n `scheme \"${scheme}\" is not the accepted entry's scheme \"${accept.scheme}\"`,\n { detail: scheme },\n );\n }\n const named = scheme ?? accept?.scheme;\n if (named === undefined) {\n const preferred: Rail = tx.mode === \"sync\" ? \"x402\" : \"escrow\";\n return ENABLED_RAILS.includes(preferred) ? preferred : \"escrow\";\n }\n const rail = railOfScheme(named);\n if (rail === undefined) {\n throw new EscroPayError(\"unsupported_scheme\", `Unsupported x402 scheme \"${named}\"`, {\n detail: named,\n });\n }\n if (tx.mode !== RAIL_MODE[rail]) {\n throw new EscroPayError(\n \"scheme_conflict\",\n `Scheme \"${named}\" is paid in ${RAIL_MODE[rail]} mode, not ${tx.mode}`,\n { detail: named },\n );\n }\n if (!ENABLED_RAILS.includes(rail)) throw new EscroRailNotEnabledError(rail);\n return rail;\n }\n}\n\n/** The longest an entry's `maxTimeoutSeconds` may be for {@link Escro.pay} to wait on its paid\n * request: one hour. An entry over it is not paid. */\nexport const PAY_MAX_TIMEOUT_SECONDS = 3600;\n\n/** The HTTP request {@link Escro.pay} pays for: sent as given, plus `PAYMENT-SIGNATURE` once paid. */\nexport interface PayRequest {\n /** Default `GET`. */\n readonly method?: string;\n readonly headers?: Readonly<Record<string, string>>;\n readonly body?: string;\n}\n\n/** What a {@link PayPolicy} sees of the 402 beside its entries. */\nexport interface PayOffer {\n readonly resource: ResourceInfo;\n readonly extensions?: Readonly<Record<string, unknown>>;\n}\n\n/** Chooses the entry to pay from a deep-frozen copy of the 402's `accepts`; it returns one of those\n * elements. It can only narrow: the entry must still match the caller's `to` and amount. */\nexport type PayPolicy = (\n accepts: readonly PaymentRequirements[],\n offer: PayOffer,\n) => PaymentRequirements;\n\n/** Parameters for {@link Escro.pay}. FROZEN: `to` and `amountMicroUsdc` stay\n * required and every other field optional; a required field added later would break\n * every kit-generated bot. Exactly one of `paymentRequired` and `url` is given. */\nexport interface PayParams {\n /** Recipient wallet address (base58): the only worker paid. */\n readonly to: string;\n /** Amount to pay, in USDC micro-units (integer, 6 decimals): the only amount paid. */\n readonly amountMicroUsdc: number;\n /** A 402 the caller already decoded; the paid request goes to its `resource.url`. */\n readonly paymentRequired?: PaymentRequired;\n /**\n * An absolute http: or https: URL without credentials, requested for its 402. A `url`, or with\n * `paymentRequired` the 402's `resource.url`, on a port `fetch` blocks is refused before any\n * lookup or request.\n */\n readonly url?: string;\n /** The request being paid for; default a bare `GET`. */\n readonly request?: PayRequest;\n /**\n * Chooses among the entries. Absent, the escrow rail wins: when an `on-delivery` or `job-escrow`\n * entry matches the caller's terms an `exact` entry is never paid, whatever the 402's order, and\n * the 402's order decides only within a rail. A policy overrides that.\n */\n readonly policy?: PayPolicy;\n /** Decides an `acceptance` predicate the 402 carries; absent, such a 402 is refused. */\n readonly admitAcceptance?: (acceptance: Acceptance) => boolean;\n /**\n * Decides each address pay() may connect to. Given, pay() resolves each host it requests (the 402's resource, and on\n * the escrow rail the job specification's host) once per call with lookup(host, { all: true }), passes every answer\n * (or the literal address) here with the request's target, and connects only to those answers; an address is admitted\n * only when this returns true, and one refused answer refuses the call.\n */\n readonly admitAddress?: (address: string, target: \"resource\" | \"spec\") => boolean;\n}\n\n/** Result of a completed payment. FROZEN and rail-generic: `reference` is the\n * rail-native settlement id (a Solana signature for escrow, an x402 receipt for\n * x402), so the shape describes either rail without change. */\nexport interface PaymentResult {\n /** Which rail settled the payment. */\n readonly rail: Rail;\n /** Rail-native settlement reference: on the escrow rail, the `create_escrow` signature; on the\n * x402 rail, the settlement's transaction. */\n readonly reference: string;\n /** Escrow rail: the escrow's PDA, the handle for `cancelEscrow` and every later call. */\n readonly escrow?: string;\n /** The paid request's `PAYMENT-RESPONSE`, decoded. */\n readonly settlement?: SettlementResponse;\n /** The paid request's response, its body unread. */\n readonly response?: Response;\n}\n","import { EscroError, EscrowTimeoutError } from \"./errors.js\";\n\nconst MS_5_MIN = 5 * 60 * 1_000;\nconst MS_30_MIN = 30 * 60 * 1_000;\nconst MS_24_H = 24 * 60 * 60 * 1_000;\n\n/**\n * Returns the next polling interval in ms based on total elapsed time.\n * 0 – 5 min → 15 s\n * 5 – 30 min → 30 s\n * 30 min – ∞ → 60 s\n */\nexport function backoffInterval(elapsedMs: number): number {\n if (elapsedMs < MS_5_MIN) return 15_000;\n if (elapsedMs < MS_30_MIN) return 30_000;\n return 60_000;\n}\n\n/** Resolves after `ms` milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Polls `fetcher` with exponential backoff until `predicate` returns true,\n * then returns the result. Throws {@link EscrowTimeoutError} after 24 hours. A read the API\n * refuses with `RATE_LIMITED` waits its `retryAfterMs` (else the poll interval) and polls again;\n * any other error is thrown.\n *\n * @param address - Escrow address used in the timeout error message.\n * @param fetcher - Async function that returns a value or null.\n * @param predicate - Returns true when polling should stop.\n * @param timeoutMs - Maximum total wait time in ms (default: 24 h).\n */\nexport async function pollUntil<T>(\n address: string,\n fetcher: () => Promise<T | null>,\n predicate: (result: T | null) => result is T,\n timeoutMs = MS_24_H,\n): Promise<T> {\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n let result: T | null = null;\n let rateLimited = false;\n let retryAfter: number | undefined;\n try {\n result = await fetcher();\n } catch (err) {\n if (!(err instanceof EscroError) || err.code !== \"RATE_LIMITED\") throw err;\n rateLimited = true;\n retryAfter = err.retryAfterMs;\n }\n if (!rateLimited && predicate(result)) return result;\n\n const elapsed = Date.now() - (deadline - timeoutMs);\n if (Date.now() >= deadline) {\n throw new EscrowTimeoutError(address);\n }\n\n const interval = (rateLimited ? retryAfter : undefined) ?? backoffInterval(elapsed);\n // Clamp to remaining time so we don't sleep past the deadline\n const remaining = deadline - Date.now();\n await sleep(Math.min(interval, remaining));\n\n if (Date.now() >= deadline) {\n throw new EscrowTimeoutError(address);\n }\n }\n}\n","import type { OutstandingDeposits, SolanaCluster } from \"@escro/shared\";\nimport { API_REQUEST_TIMEOUT_MS } from \"./api.js\";\nimport { EscroError } from \"./errors.js\";\nimport type { X402SpendCap } from \"./types.js\";\n\n/**\n * One wallet's spend-capped creates on one cluster, shared by every `Escro` in the process.\n * Admissions run one at a time; `pending` holds each admitted create's deposit by escrow address\n * from its POST until evidence shows the API counts it or that its transaction never landed.\n */\nexport interface WalletLedger {\n admissions: Promise<unknown>;\n readonly pending: Map<string, PendingCreate>;\n}\n\n/** An admitted create's deposit, and the signature its send returned once the send resolved. */\nexport interface PendingCreate {\n readonly deposit: bigint;\n signature?: string;\n}\n\n/** The `code` of each {@link EscroError} the spend cap throws. */\nexport const SPEND_CAP_ERROR_CODES = {\n /** A mainnet `createEscrow` on a client constructed without the `spendCap` option. */\n required: \"SPEND_CAP_REQUIRED\",\n /** The create's deposit would pass the cap. */\n exceeded: \"SPEND_CAP_EXCEEDED\",\n /** The outstanding deposits could not be read. */\n unreadable: \"SPEND_CAP_UNREADABLE\",\n} as const;\n\nconst ledgers = new Map<string, WalletLedger>();\n\nfunction ledgerKey(cluster: SolanaCluster, wallet: string): string {\n return `${cluster}:${wallet}`;\n}\n\n/** The process's ledger for `wallet` on `cluster`. */\nexport function walletLedger(cluster: SolanaCluster, wallet: string): WalletLedger {\n const key = ledgerKey(cluster, wallet);\n let ledger = ledgers.get(key);\n if (ledger === undefined) {\n ledger = { admissions: Promise.resolve(), pending: new Map() };\n ledgers.set(key, ledger);\n }\n return ledger;\n}\n\n/**\n * One wallet's x402 spending on one cluster, shared by every `Escro` in the process. It is a\n * monotonic total, not {@link WalletLedger.pending}'s in-flight set: a signed payment cannot be\n * shown not to have landed, so it never leaves the total. A restart starts it again at zero.\n */\nexport interface X402Ledger {\n admissions: Promise<unknown>;\n spentMicroUsdc: bigint;\n}\n\nconst x402Ledgers = new Map<string, X402Ledger>();\n\n/** The process's x402 ledger for `wallet` on `cluster`. */\nexport function x402Ledger(cluster: SolanaCluster, wallet: string): X402Ledger {\n const key = ledgerKey(cluster, wallet);\n let ledger = x402Ledgers.get(key);\n if (ledger === undefined) {\n ledger = { admissions: Promise.resolve(), spentMicroUsdc: 0n };\n x402Ledgers.set(key, ledger);\n }\n return ledger;\n}\n\n/** Forgets the in-flight deposit of `address`, if the wallet's ledger holds one. */\nexport function dropPending(cluster: SolanaCluster, wallet: string, address: string): void {\n ledgers.get(ledgerKey(cluster, wallet))?.pending.delete(address);\n}\n\n/** Records the signature the send of the in-flight create at `address` returned. */\nexport function recordSent(\n cluster: SolanaCluster,\n wallet: string,\n address: string,\n signature: string,\n): void {\n const entry = ledgers.get(ledgerKey(cluster, wallet))?.pending.get(address);\n if (entry !== undefined) entry.signature = signature;\n}\n\n/**\n * Forgets the in-flight deposit of `address` on evidence that `signature` landed and failed, only\n * when `signature` is the one its send returned: another transaction for the same address failing\n * says nothing about the create that holds the deposit.\n */\nexport function dropFailed(\n cluster: SolanaCluster,\n wallet: string,\n address: string,\n signature: string,\n): void {\n const pending = ledgers.get(ledgerKey(cluster, wallet))?.pending;\n if (pending?.get(address)?.signature === signature) pending.delete(address);\n}\n\n/** Runs `step` after every earlier admission on the ledger has settled, passed or not. */\nexport function admit<T>(\n ledger: Pick<WalletLedger, \"admissions\">,\n step: () => Promise<T>,\n): Promise<T> {\n const run = ledger.admissions.then(step);\n ledger.admissions = run.catch(() => undefined);\n return run;\n}\n\n/**\n * Runs `read`, abandoning it (it takes no signal, so it is not cancelled) if it has not answered\n * within the API read's bound, so a read inside an admission holds the admission no longer.\n */\nexport async function boundedRead<T>(what: string, read: () => Promise<T>): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`${what} did not answer within ${String(API_REQUEST_TIMEOUT_MS / 1000)} s`));\n }, API_REQUEST_TIMEOUT_MS);\n });\n try {\n return await Promise.race([read(), timeout]);\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function readX402Spent(cap: Readonly<X402SpendCap>): Promise<bigint> {\n if (cap.spent === undefined) return 0n;\n let value: number;\n try {\n value = await boundedRead(\"x402SpendCap.spent()\", cap.spent);\n } catch (err) {\n throw new EscroError(\n `The x402 spend could not be read: ${err instanceof Error ? err.message : String(err)}`,\n SPEND_CAP_ERROR_CODES.unreadable,\n undefined,\n { cause: err },\n );\n }\n if (!isMicroUsdc(value)) {\n throw unreadable(`x402SpendCap.spent() answered ${String(value)}, not whole micro-USDC`);\n }\n return BigInt(value);\n}\n\n/**\n * Admits one x402 payment against `cap`, counting its full amount, and returns the function that\n * credits it back: call it only for a payment refused before its signature exists. Without a cap\n * off mainnet nothing is counted.\n */\nexport async function admitX402Payment(\n cap: Readonly<X402SpendCap> | undefined,\n cluster: SolanaCluster,\n wallet: string,\n amountMicroUsdc: number,\n): Promise<() => void> {\n if (cap === undefined) {\n if (cluster === \"mainnet\") {\n throw new EscroError(\n \"pay() over x402 on mainnet needs a spend cap: construct Escro with the x402SpendCap option.\",\n SPEND_CAP_ERROR_CODES.required,\n );\n }\n return () => undefined;\n }\n const ledger = x402Ledger(cluster, wallet);\n const amount = BigInt(amountMicroUsdc);\n return admit(ledger, async () => {\n const recorded = await readX402Spent(cap);\n const total = recorded + ledger.spentMicroUsdc + amount;\n if (total > BigInt(cap.maxMicroUsdc)) {\n throw new EscroError(\n `Spend cap exceeded: spent ${String(recorded + ledger.spentMicroUsdc)} + proposed ` +\n `${String(amount)} micro-USDC would pass the x402SpendCap of ` +\n `${String(cap.maxMicroUsdc)} micro-USDC.`,\n SPEND_CAP_ERROR_CODES.exceeded,\n );\n }\n ledger.spentMicroUsdc += amount;\n return () => {\n ledger.spentMicroUsdc -= amount;\n };\n });\n}\n\n/** The sum of the ledger's in-flight deposits. */\nexport function pendingMicroUsdc(ledger: WalletLedger): bigint {\n let total = 0n;\n for (const { deposit } of ledger.pending.values()) total += deposit;\n return total;\n}\n\n/**\n * The micro-USDC in the outstanding-deposits answer for `maker`. An answer for another maker, or\n * whose total is not a decimal string, throws `SPEND_CAP_UNREADABLE`; the caller refuses a total\n * a `number` cannot hold exactly.\n */\nexport function outstandingFromAnswer(answer: OutstandingDeposits, maker: string): number {\n if (answer.maker !== maker) {\n throw unreadable(\n `the outstanding deposits answer is for ${JSON.stringify(answer.maker)}, not ${maker}`,\n );\n }\n const text: unknown = answer.depositsMicroUsdc;\n if (typeof text !== \"string\" || !/^\\d+$/.test(text)) {\n throw unreadable(`the outstanding deposits total ${JSON.stringify(text)} is not a decimal`);\n }\n return Number(text);\n}\n\n/**\n * Throws an {@link EscroError} with code `SPEND_CAP_EXCEEDED` when the outstanding deposits plus\n * the proposed one would pass the cap. All three are integer micro-USDC; reaching the cap exactly\n * is allowed.\n */\nexport function assertWithinSpendCap(check: {\n maxOutstandingMicroUsdc: number;\n outstandingMicroUsdc: number;\n proposedMicroUsdc: number;\n}): void {\n const total = BigInt(check.outstandingMicroUsdc) + BigInt(check.proposedMicroUsdc);\n if (total > BigInt(check.maxOutstandingMicroUsdc)) {\n throw new EscroError(\n `Spend cap exceeded: outstanding ${String(check.outstandingMicroUsdc)} + proposed ` +\n `${String(check.proposedMicroUsdc)} micro-USDC would pass the spendCap of ` +\n `${String(check.maxOutstandingMicroUsdc)} micro-USDC.`,\n SPEND_CAP_ERROR_CODES.exceeded,\n );\n }\n}\n\n/** Whether `n` is a whole, non-negative micro-USDC amount a `number` holds exactly. */\nexport function isMicroUsdc(n: number): boolean {\n return Number.isSafeInteger(n) && n >= 0;\n}\n\nfunction unreadable(message: string): EscroError {\n return new EscroError(message, SPEND_CAP_ERROR_CODES.unreadable);\n}\n\n/**\n * A plain decimal USDC amount (`\"12.5\"`, at most six decimals, no sign or exponent) as integer\n * micro-USDC. Throws an {@link EscroError} with code `VALIDATION_ERROR` otherwise.\n */\nexport function parseUsdc(text: string): number {\n const match = /^(\\d+)(?:\\.(\\d{1,6}))?$/.exec(text);\n const micro =\n match === null\n ? undefined\n : Number(BigInt(match[1] ?? \"\") * 1_000_000n + BigInt((match[2] ?? \"\").padEnd(6, \"0\")));\n if (micro === undefined || !Number.isSafeInteger(micro)) {\n throw new EscroError(\n `Not a USDC amount (digits, at most six decimals): ${JSON.stringify(text)}`,\n \"VALIDATION_ERROR\",\n );\n }\n return micro;\n}\n","// The buyer's side of an `on-delivery` 402 (docs/specs/scheme_on_delivery_svm.md, \"Client, before\n// funding\"), and the worker's builder of the entry it advertises.\nimport { PublicKey, type Connection } from \"@solana/web3.js\";\nimport {\n CURRENT_ACCOUNT_VERSION,\n MIN_ESCROW_AMOUNT,\n ONCHAIN_TIMEOUT_SECONDS,\n escrowFee,\n getCaip2Network,\n getPlatformConfigPda,\n getProgramId,\n getUsdcMint,\n isRecord,\n type Acceptance,\n type EscroExtensionInfo,\n type OnDeliveryAccept,\n type OnDeliveryScheme,\n type PaymentRequired,\n type PlatformConfigAccount,\n type ResourceInfo,\n type SettlementMode,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport { decodePlatformConfig, isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { ChainReadError } from \"../chain-read.js\";\nimport { EscroError } from \"../errors.js\";\nimport {\n OnDeliveryAcceptError,\n PlatformConfigNotFoundError,\n type OnDeliveryAcceptRefusal,\n} from \"./errors.js\";\nimport { hasMembers, isEscroExtensionInfo } from \"./extension.js\";\n\nexport type PlatformConfigTerms = Pick<PlatformConfigAccount, \"usdcMint\" | \"feeBps\">;\n\n/**\n * The cluster's PlatformConfig, read at its PDA and decoded by the shared decoder. Throws\n * {@link PlatformConfigNotFoundError} when no account is there, and {@link ChainReadError}\n * `CHAIN_ACCOUNT_INVALID` (reason `version`) on a version this SDK does not read.\n */\nexport async function readPlatformConfig(\n rpc: Pick<Connection, \"getAccountInfo\">,\n cluster: SolanaCluster,\n): Promise<PlatformConfigTerms & { treasury: string }> {\n const address = getPlatformConfigPda(cluster);\n let account: Awaited<ReturnType<Connection[\"getAccountInfo\"]>>;\n try {\n account = await rpc.getAccountInfo(new PublicKey(address), { commitment: \"confirmed\" });\n } catch (cause) {\n throw new ChainReadError(\"CHAIN_RPC_FAILED\", \"The RPC's getAccountInfo call failed.\", {\n cause,\n });\n }\n if (account === null) throw new PlatformConfigNotFoundError(address);\n const config = decodePlatformConfig(account.data);\n if (config.version !== CURRENT_ACCOUNT_VERSION) {\n throw new ChainReadError(\n \"CHAIN_ACCOUNT_INVALID\",\n `The PlatformConfig at ${address} is version ${String(config.version)}; this SDK reads version ${String(CURRENT_ACCOUNT_VERSION)}`,\n { reason: \"version\" },\n );\n }\n return { usdcMint: config.usdcMint, feeBps: config.feeBps, treasury: config.treasury };\n}\n\n/**\n * The settlement modes this client funds. The version-1 account layout has no refund on silence\n * (the binding: `refund` is offered from a future account layout), so `release` only.\n */\nexport const SUPPORTED_SETTLEMENT_MODES: readonly SettlementMode[] = [\"release\"];\n\n/** Whether the entry's `extra.settlementMode` is one of {@link SUPPORTED_SETTLEMENT_MODES}. */\nexport function settlementModeSupported(entry: { extra: { settlementMode: unknown } }): boolean {\n return SUPPORTED_SETTLEMENT_MODES.some((mode) => mode === entry.extra.settlementMode);\n}\n\nexport interface ParseEscrowAcceptContext {\n cluster: SolanaCluster;\n /** From {@link readPlatformConfig}: the entry's mint and fee must equal these. */\n platformConfig: PlatformConfigTerms;\n /** The buyer's own bound on what it deposits: `amount` plus the fee at `platformConfig.feeBps`. */\n maxDepositMicroUsdc: bigint;\n /** When given, the only worker the buyer funds. */\n payTo?: string;\n /** Decides an `acceptance` predicate the 402 carries; absent, such an entry is refused. */\n admitAcceptance?: (acceptance: Acceptance) => boolean;\n /** Unix milliseconds. */\n now?: () => number;\n}\n\nexport interface EscrowAcceptSelection {\n readonly cluster: SolanaCluster;\n readonly resource: ResourceInfo;\n readonly entry: OnDeliveryAccept;\n readonly extension: EscroExtensionInfo | undefined;\n readonly extensions: Record<string, unknown> | undefined;\n}\n\n// The selections parseEscrowAccept returned, each funded at most once. Module-level: a selection\n// parsed by one copy of the SDK and funded by another is unknown to the second, and refused.\nconst SELECTIONS = new WeakMap<EscrowAcceptSelection, \"fresh\" | \"spent\">();\n\n/** The selection's state before this call, marking it spent: undefined when parse did not return it. */\nexport function spendSelection(selection: EscrowAcceptSelection): \"fresh\" | \"spent\" | undefined {\n const state = SELECTIONS.get(selection);\n if (state !== undefined) SELECTIONS.set(selection, \"spent\");\n return state;\n}\n\nconst EXTRA_MEMBERS = [\n \"program\",\n \"specHash\",\n \"specUri\",\n \"deadline\",\n \"reviewWindowSeconds\",\n \"feeBps\",\n \"feePayer\",\n \"settlementMode\",\n \"paymentFlow\",\n];\n\nexport const isOnDeliveryScheme = (value: unknown): value is OnDeliveryScheme =>\n value === \"on-delivery\" || value === \"job-escrow\";\n\nconst SPEC_HASH = /^[0-9a-f]{64}$/;\n\nexport const isSpecHash = (value: unknown): value is string =>\n typeof value === \"string\" && SPEC_HASH.test(value);\n\nfunction isSpecUri(value: unknown): boolean {\n if (typeof value !== \"string\") return false;\n try {\n const { protocol } = new URL(value);\n return protocol === \"https:\" || protocol === \"ipfs:\";\n } catch {\n return false;\n }\n}\n\nconst isPositiveSafeInteger = (value: unknown): boolean =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n\n/**\n * An entry's `amount` as micro-USDC: a canonical decimal string (no sign, exponent, fraction,\n * whitespace or leading zero) from the minimum escrow to the largest safe integer; else undefined.\n */\nexport function amountOf(value: unknown): bigint | undefined {\n if (typeof value !== \"string\" || !/^[1-9][0-9]*$/.test(value)) return undefined;\n const amount = BigInt(value);\n const inRange = amount >= BigInt(MIN_ESCROW_AMOUNT) && amount <= BigInt(Number.MAX_SAFE_INTEGER);\n return inRange ? amount : undefined;\n}\n\ntype Extension =\n | { kind: \"none\" }\n | { kind: \"invalid\" }\n | { kind: \"info\"; info: EscroExtensionInfo };\n\nfunction escroExtension(extensions: unknown): Extension {\n if (extensions === undefined) return { kind: \"none\" };\n // A present `extensions` that is not an object is malformed; echoed into the payment, it would\n // make that payment invalid V2 after the escrow is funded.\n if (!isRecord(extensions)) return { kind: \"invalid\" };\n if (!(\"escro\" in extensions)) return { kind: \"none\" };\n const escro = extensions.escro;\n if (!isRecord(escro) || !isEscroExtensionInfo(escro.info)) return { kind: \"invalid\" };\n return { kind: \"info\", info: escro.info };\n}\n\nexport function deepFreeze(value: unknown): void {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return;\n Object.freeze(value);\n for (const member of Object.values(value)) deepFreeze(member);\n}\n\n/** A deep-frozen structured clone of the 402; throws when it is not plain data. */\nfunction frozenCopy(required: PaymentRequired): PaymentRequired {\n let copy: PaymentRequired;\n try {\n copy = structuredClone(required);\n } catch (cause) {\n throw new EscroError(\n \"The 402 is not plain data and cannot be copied\",\n \"VALIDATION_ERROR\",\n undefined,\n {\n cause,\n },\n );\n }\n deepFreeze(copy);\n return copy;\n}\n\n/** The entry's first failed client check, in the binding's order; undefined when it passes all. */\nfunction refusalOf(\n entry: Record<string, unknown>,\n ctx: ParseEscrowAcceptContext,\n nowMs: number,\n extension: Extension,\n): OnDeliveryAcceptRefusal | undefined {\n const { cluster, platformConfig } = ctx;\n const extra = entry.extra;\n if (!isRecord(extra)) return \"extra_shape\";\n if (entry.network !== getCaip2Network(cluster)) return \"network\";\n if (extra.program !== getProgramId(cluster)) return \"program\";\n if (entry.asset !== getUsdcMint(cluster) || entry.asset !== platformConfig.usdcMint) {\n return \"asset\";\n }\n if (extra.feeBps !== platformConfig.feeBps) return \"fee_bps\";\n if (!settlementModeSupported({ extra: { settlementMode: extra.settlementMode } })) {\n return \"settlement_mode\";\n }\n if (extra.reviewWindowSeconds !== ONCHAIN_TIMEOUT_SECONDS) return \"review_window\";\n if (extra.feePayer !== \"client\") return \"fee_payer\";\n if (extra.paymentFlow !== \"upfront\" && extra.paymentFlow !== \"escrow\") return \"payment_flow\";\n const amount = amountOf(entry.amount);\n if (amount === undefined) return \"amount\";\n if (amount + escrowFee(amount, platformConfig.feeBps) > ctx.maxDepositMicroUsdc) {\n return \"over_limit\";\n }\n const payTo = entry.payTo;\n if (typeof payTo !== \"string\" || !isCanonicalPubkey(payTo)) return \"pay_to\";\n if (ctx.payTo !== undefined && payTo !== ctx.payTo) return \"pay_to\";\n if (!isSpecHash(extra.specHash)) return \"spec_hash\";\n if (!isSpecUri(extra.specUri)) return \"spec_uri\";\n const deadline = extra.deadline;\n if (\n typeof deadline !== \"number\" ||\n !Number.isSafeInteger(deadline) ||\n deadline * 1_000 <= nowMs\n ) {\n return \"deadline\";\n }\n if (!isPositiveSafeInteger(entry.maxTimeoutSeconds)) return \"max_timeout\";\n if (!hasMembers(extra, EXTRA_MEMBERS)) return \"extra_shape\";\n if (extension.kind === \"invalid\") return \"extension_invalid\";\n if (extension.kind === \"info\") {\n const { settlement, acceptance } = extension.info;\n if (\n settlement !== undefined &&\n (settlement.reviewWindowSeconds !== extra.reviewWindowSeconds ||\n settlement.settlementMode !== extra.settlementMode ||\n settlement.feePayer !== extra.feePayer)\n ) {\n return \"extension_terms\";\n }\n if (acceptance !== undefined && ctx.admitAcceptance?.(acceptance) !== true) return \"acceptance\";\n }\n return undefined;\n}\n\n/**\n * The first `on-delivery` (or `job-escrow`) entry of the 402 that passes every client check of the\n * binding, against the cluster's pinned values, `ctx.platformConfig` and the buyer's own deposit\n * bound; entries of other schemes are ignored. The selection holds a deep-frozen copy of the 402's\n * resource, entry and extensions taken before the checks, and is the only input\n * {@link fundFromAccept} funds, once. Throws {@link OnDeliveryAcceptError} listing each candidate's\n * first refusal when none passes, and {@link EscroError} `VALIDATION_ERROR` when\n * `ctx.maxDepositMicroUsdc` is not a bigint or the 402 is not plain data.\n */\nexport function parseEscrowAccept(\n required: PaymentRequired,\n ctx: ParseEscrowAcceptContext,\n): EscrowAcceptSelection {\n const bound: unknown = ctx.maxDepositMicroUsdc;\n if (typeof bound !== \"bigint\") {\n throw new EscroError(\n \"parseEscrowAccept needs ctx.maxDepositMicroUsdc: the buyer's bigint bound on its deposit\",\n \"VALIDATION_ERROR\",\n );\n }\n // The terms are checked and funded from one deep-frozen copy, so nothing holding the caller's\n // 402 can change them between the check and the create.\n const offer = frozenCopy(required);\n const nowMs = ctx.now?.() ?? Date.now();\n const extension = escroExtension(offer.extensions);\n const refusals: { index: number; reason: OnDeliveryAcceptRefusal }[] = [];\n for (const [index, offered] of offer.accepts.entries()) {\n const candidate: unknown = offered;\n if (!isRecord(candidate) || !isOnDeliveryScheme(candidate.scheme)) continue;\n const reason = refusalOf(candidate, ctx, nowMs, extension);\n if (reason !== undefined) {\n refusals.push({ index, reason });\n continue;\n }\n const selection: EscrowAcceptSelection = Object.freeze({\n cluster: ctx.cluster,\n resource: offer.resource,\n entry: offered as OnDeliveryAccept,\n extension: extension.kind === \"info\" ? extension.info : undefined,\n extensions: offer.extensions,\n });\n SELECTIONS.set(selection, \"fresh\");\n return selection;\n }\n throw new OnDeliveryAcceptError(\n refusals.length > 0 ? refusals : [{ index: -1, reason: \"no_entry\" }],\n );\n}\n\nexport interface BuildEscrowAcceptOptions {\n cluster: SolanaCluster;\n amountMicroUsdc: bigint;\n payTo: string;\n specHash: string;\n specUri: string;\n /** Unix seconds. */\n deadline: number;\n /** PlatformConfig's `fee_bps`, read by {@link readPlatformConfig}. */\n feeBps: number;\n maxTimeoutSeconds: number;\n /** Default `upfront`. */\n paymentFlow?: \"upfront\" | \"escrow\";\n}\n\nfunction buildRefusal(options: BuildEscrowAcceptOptions): OnDeliveryAcceptRefusal | undefined {\n if (amountOf(options.amountMicroUsdc.toString()) === undefined) return \"amount\";\n const { feeBps } = options;\n if (!Number.isSafeInteger(feeBps) || feeBps < 0 || feeBps > 10_000) return \"fee_bps\";\n if (!isCanonicalPubkey(options.payTo)) return \"pay_to\";\n if (!isSpecHash(options.specHash)) return \"spec_hash\";\n if (!isSpecUri(options.specUri)) return \"spec_uri\";\n if (!Number.isSafeInteger(options.deadline)) return \"deadline\";\n if (!isPositiveSafeInteger(options.maxTimeoutSeconds)) return \"max_timeout\";\n return undefined;\n}\n\n/**\n * The `on-delivery` entry a worker advertises: network, asset, program, review window, settlement\n * mode and fee payer from the cluster's pinned values, the fee from `options.feeBps`. Throws\n * {@link OnDeliveryAcceptError} for an entry the client side would refuse on its own terms (an\n * amount under the minimum escrow, a malformed key, hash, URI or bound).\n */\nexport function buildEscrowAccept(options: BuildEscrowAcceptOptions): OnDeliveryAccept {\n const refusal = buildRefusal(options);\n if (refusal !== undefined) throw new OnDeliveryAcceptError([{ index: -1, reason: refusal }]);\n const { cluster } = options;\n return {\n scheme: \"on-delivery\",\n network: getCaip2Network(cluster),\n amount: options.amountMicroUsdc.toString(),\n asset: getUsdcMint(cluster),\n payTo: options.payTo,\n maxTimeoutSeconds: options.maxTimeoutSeconds,\n extra: {\n program: getProgramId(cluster),\n specHash: options.specHash,\n specUri: options.specUri,\n deadline: options.deadline,\n reviewWindowSeconds: ONCHAIN_TIMEOUT_SECONDS,\n feeBps: options.feeBps,\n feePayer: \"client\",\n settlementMode: \"release\",\n paymentFlow: options.paymentFlow ?? \"upfront\",\n },\n };\n}\n","// Reads what the program recorded for one escrow straight from a Solana RPC, with no Escro service\n// in the path: an open escrow from its account, a closed one (every settlement closes the account)\n// from the program's events in the address's transaction history. Nothing signs, nothing writes.\nimport bs58 from \"bs58\";\nimport { Connection, PublicKey, SolanaJSONRPCErrorCode, SystemProgram } from \"@solana/web3.js\";\nimport {\n CURRENT_ACCOUNT_VERSION,\n EscrowState,\n assertProgramIdNotPlaceholder,\n escrowFee,\n getProgramId,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport { deriveEscrowPda } from \"@escro/shared/solana\";\nimport {\n LogTruncatedError,\n MAX_SUPPORTED_TRANSACTION_VERSION,\n decodeEscroEvent,\n transactionVersionFetch,\n walkProgramLogs,\n type EscroEvent,\n} from \"@escro/shared/chain\";\nimport { EscroError } from \"./errors.js\";\n\n/**\n * The RPC methods the reader calls; a web3.js Connection satisfies it. A history holding a\n * version-1 transaction reads only through a connection {@link chainReadConnection} builds; a\n * custom transport (headers, a proxy, a test double) goes in as its `fetchFn`. A connection built\n * any other way fails a version-1 history with `CHAIN_RPC_FAILED`, whose archival advice does not\n * apply to that failure.\n */\nexport type ChainReadRpc = Pick<\n Connection,\n \"getAccountInfo\" | \"getSignaturesForAddress\" | \"getTransaction\"\n>;\n\nexport type ChainReadTarget = { address: string } | { buyer: string; taskId: string };\n\nexport interface ReadEscrowFromChainOptions {\n /** Selects the program id through `getProgramId`; a localnet run of the devnet build is \"devnet\". */\n cluster: SolanaCluster;\n /**\n * The RPC read. A history holding a version-1 transaction reads only through a connection\n * {@link chainReadConnection} builds; a custom transport (headers, a proxy, a test double) goes\n * in as its `fetchFn`. A connection built any other way fails a version-1 history with\n * `CHAIN_RPC_FAILED`, whose archival advice does not apply to that failure.\n */\n rpc: ChainReadRpc;\n /** The most getTransaction calls one read makes; default {@link CHAIN_READ_MAX_TRANSACTIONS}. */\n maxTransactions?: number;\n}\n\n/** Every EscrowAccount field by its IDL name (snake_case), u64 as bigint, i64 as number, pubkeys base58. */\nexport type DecodedEscrowAccount = Record<string, string | number | bigint | null>;\n\nexport interface ChainEscrowFigures {\n address: string;\n buyer: string;\n worker: string | null;\n taskId: string;\n amountMicro: bigint;\n feeBps: number;\n /** `escrowFee(amountMicro, feeBps)`, the escrow's own stored rate. */\n feeMicro: bigint;\n /** What the buyer deposited: amount plus fee. */\n depositMicro: bigint;\n deadline: number;\n specHash: string;\n createdAt: number;\n deliverableHash: string | null;\n proofUri: string | null;\n submittedAt: number | null;\n}\n\nexport interface ChainSettlement {\n kind: \"released\" | \"refunded\" | \"cancelled\";\n /** PaymentReleased.worker_amount. */\n workerAmountMicro: bigint | null;\n /** PaymentReleased.fee_amount. */\n feeAmountMicro: bigint | null;\n /** BuyerRefunded or EscrowCancelled refund_amount. */\n refundAmountMicro: bigint | null;\n /** The event's resolved_at, or cancelled_at for a cancel. */\n resolvedAt: number;\n /** The settling transaction. */\n signature: string;\n}\n\nexport interface ChainEscrowReading {\n source: \"account\" | \"history\";\n cluster: SolanaCluster;\n programId: string;\n /** FUNDED to DISPUTED while open; COMPLETED, REFUNDED or CANCELLED once closed. */\n state: EscrowState;\n /** From an account, the state is DISPUTED; from history, a DisputeRaised is in the lifecycle. */\n disputed: boolean;\n figures: ChainEscrowFigures;\n /** Null while open. */\n settlement: ChainSettlement | null;\n /** From history, the lifecycle's successful transactions, oldest first; from an account, none. */\n signatures: string[];\n}\n\nexport type ChainReadErrorCode =\n | \"CHAIN_ESCROW_NOT_FOUND\"\n | \"CHAIN_HISTORY_INCOMPLETE\"\n | \"CHAIN_HISTORY_BUDGET\"\n | \"CHAIN_LOGS_TRUNCATED\"\n | \"CHAIN_ACCOUNT_INVALID\"\n | \"CHAIN_RPC_FAILED\"\n | \"CHAIN_TRANSACTION_VERSION\"\n | \"INVALID_INPUT\";\n\nexport type ChainAccountInvalidReason = \"owner\" | \"discriminator\" | \"version\" | \"layout\" | \"pda\";\n\n/**\n * A chain read that gave no reading. `reason` names the failed account check on\n * `CHAIN_ACCOUNT_INVALID`. A `CHAIN_RPC_FAILED` message is fixed text naming the RPC method, a\n * `CHAIN_TRANSACTION_VERSION` one the transaction and the address; the transport's own error, which\n * may echo the RPC URL, is only the `cause`.\n */\nexport class ChainReadError extends EscroError {\n readonly reason: ChainAccountInvalidReason | undefined;\n\n constructor(\n code: ChainReadErrorCode,\n message: string,\n options: { reason?: ChainAccountInvalidReason; cause?: unknown } = {},\n ) {\n super(message, code, undefined, \"cause\" in options ? { cause: options.cause } : undefined);\n this.name = \"ChainReadError\";\n this.reason = options.reason;\n }\n}\n\nexport const ARCHIVAL_RPC_NOTE =\n \"A settled escrow is closed on chain and survives only in transaction history; if it is older than this RPC's history, read it through an archival RPC.\";\n\n/** getTransaction calls per read: one lifecycle takes at most five, so about ten reuses or spam. */\nexport const CHAIN_READ_MAX_TRANSACTIONS = 50;\n/** getSignaturesForAddress pages per read, of {@link SIGNATURE_PAGE} signatures each. */\nexport const CHAIN_READ_MAX_SIGNATURE_PAGES = 5;\nconst SIGNATURE_PAGE = 1000;\n\nexport const ESCROW_ACCOUNT_DISCRIMINATOR: readonly number[] = [36, 69, 48, 18, 128, 225, 125, 135];\n\ntype FieldKind =\n | \"pubkey\"\n | \"u8\"\n | \"u16\"\n | \"u64\"\n | \"i64\"\n | \"string\"\n | \"option<pubkey>\"\n | \"option<string>\"\n | \"option<i64>\"\n | \"enum\";\n\n/** The EscrowAccount fields in on-chain order (escrow_account.rs, the committed IDL). */\nexport const ESCROW_ACCOUNT_LAYOUT: readonly { name: string; kind: FieldKind }[] = [\n { name: \"version\", kind: \"u8\" },\n { name: \"buyer\", kind: \"pubkey\" },\n { name: \"assigned_worker\", kind: \"option<pubkey>\" },\n { name: \"task_id\", kind: \"string\" },\n { name: \"amount_usdc\", kind: \"u64\" },\n { name: \"fee_bps\", kind: \"u16\" },\n { name: \"deadline\", kind: \"i64\" },\n { name: \"spec_hash\", kind: \"string\" },\n { name: \"deliverable_hash\", kind: \"option<string>\" },\n { name: \"proof_uri\", kind: \"option<string>\" },\n { name: \"state\", kind: \"enum\" },\n { name: \"created_at\", kind: \"i64\" },\n { name: \"updated_at\", kind: \"i64\" },\n { name: \"submitted_at\", kind: \"option<i64>\" },\n { name: \"min_amount\", kind: \"u64\" },\n { name: \"bump\", kind: \"u8\" },\n { name: \"marketplace_id\", kind: \"option<string>\" },\n { name: \"referrer_wallet\", kind: \"option<pubkey>\" },\n { name: \"referrer_bps\", kind: \"u16\" },\n];\n\n/** The program's allocation: 8 + EscrowAccount::INIT_SPACE. The tail past the content is zero. */\nexport const ESCROW_ACCOUNT_SIZE = 537;\n\n/** The IDL's EscrowState variants, in discriminant order. */\nconst STATE_VARIANTS = [\n \"Created\",\n \"Funded\",\n \"InProgress\",\n \"Submitted\",\n \"Completed\",\n \"Disputed\",\n \"Refunded\",\n] as const;\n\nconst STATE_OF: Record<(typeof STATE_VARIANTS)[number], EscrowState> = {\n Created: EscrowState.CREATED,\n Funded: EscrowState.FUNDED,\n InProgress: EscrowState.IN_PROGRESS,\n Submitted: EscrowState.SUBMITTED,\n Completed: EscrowState.COMPLETED,\n Disputed: EscrowState.DISPUTED,\n Refunded: EscrowState.REFUNDED,\n};\n\nconst MAX_TASK_ID_BYTES = 32;\n\nclass AccountProblem extends Error {\n constructor(\n readonly reason: ChainAccountInvalidReason,\n readonly detail: string,\n ) {\n super(detail);\n }\n}\n\nclass AccountReader {\n private at = 0;\n constructor(private readonly data: Uint8Array) {}\n\n private take(n: number): Uint8Array {\n if (this.at + n > this.data.length) {\n throw new AccountProblem(\"layout\", \"a field reads past the content\");\n }\n const bytes = this.data.subarray(this.at, this.at + n);\n this.at += n;\n return bytes;\n }\n\n private view(n: number): DataView {\n const bytes = this.take(n);\n return new DataView(bytes.buffer, bytes.byteOffset, n);\n }\n\n skip(n: number): void {\n this.take(n);\n }\n\n private scalar(kind: \"pubkey\" | \"string\" | \"i64\"): string | number {\n if (kind === \"pubkey\") return bs58.encode(this.take(32));\n if (kind === \"string\") {\n const length = this.view(4).getUint32(0, true);\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(this.take(length));\n } catch (err) {\n if (err instanceof AccountProblem) throw err;\n throw new AccountProblem(\"layout\", \"a string field is not UTF-8\");\n }\n }\n const value = this.view(8).getBigInt64(0, true);\n if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {\n throw new AccountProblem(\"layout\", \"an i64 field is outside the safe integer range\");\n }\n return Number(value);\n }\n\n read(kind: FieldKind): string | number | bigint | null {\n switch (kind) {\n case \"u8\":\n return this.view(1).getUint8(0);\n case \"u16\":\n return this.view(2).getUint16(0, true);\n case \"u64\":\n return this.view(8).getBigUint64(0, true);\n case \"pubkey\":\n case \"string\":\n case \"i64\":\n return this.scalar(kind);\n case \"enum\": {\n const index = this.view(1).getUint8(0);\n const variant = STATE_VARIANTS[index];\n if (variant === undefined) {\n throw new AccountProblem(\"layout\", `state ${String(index)} is no EscrowState variant`);\n }\n return variant;\n }\n case \"option<pubkey>\":\n case \"option<string>\":\n case \"option<i64>\": {\n const tag = this.view(1).getUint8(0);\n if (tag === 0) return null;\n if (tag !== 1) throw new AccountProblem(\"layout\", `an option tag is ${String(tag)}`);\n return this.scalar(\n kind === \"option<pubkey>\" ? \"pubkey\" : kind === \"option<string>\" ? \"string\" : \"i64\",\n );\n }\n }\n }\n}\n\n/** Checks run in order: discriminator, version, layout. */\nfunction decodeAccount(data: Uint8Array): DecodedEscrowAccount {\n if (\n data.length < ESCROW_ACCOUNT_DISCRIMINATOR.length ||\n ESCROW_ACCOUNT_DISCRIMINATOR.some((byte, i) => data[i] !== byte)\n ) {\n throw new AccountProblem(\"discriminator\", \"its discriminator is not EscrowAccount's\");\n }\n const version = data[ESCROW_ACCOUNT_DISCRIMINATOR.length];\n if (version !== undefined && version !== CURRENT_ACCOUNT_VERSION) {\n throw new AccountProblem(\n \"version\",\n `its version is ${String(version)}; this reader reads version ${String(CURRENT_ACCOUNT_VERSION)}`,\n );\n }\n if (data.length !== ESCROW_ACCOUNT_SIZE) {\n throw new AccountProblem(\n \"layout\",\n `it is ${String(data.length)} bytes; an EscrowAccount is ${String(ESCROW_ACCOUNT_SIZE)}`,\n );\n }\n const reader = new AccountReader(data);\n reader.skip(ESCROW_ACCOUNT_DISCRIMINATOR.length);\n const decoded: DecodedEscrowAccount = {};\n for (const field of ESCROW_ACCOUNT_LAYOUT) decoded[field.name] = reader.read(field.kind);\n return decoded;\n}\n\n/**\n * Decode EscrowAccount bytes as the program allocates them. Throws {@link ChainReadError}\n * `CHAIN_ACCOUNT_INVALID` (reason `discriminator`, `version` or `layout`) on anything else.\n * `state` is the IDL variant name (`Funded`, `InProgress`, ...).\n */\nexport function decodeEscrowAccount(data: Uint8Array): DecodedEscrowAccount {\n try {\n return decodeAccount(data);\n } catch (err) {\n if (!(err instanceof AccountProblem)) throw err;\n throw new ChainReadError(\n \"CHAIN_ACCOUNT_INVALID\",\n `Not a current EscrowAccount: ${err.detail}`,\n { reason: err.reason },\n );\n }\n}\n\n// ── Targets ───────────────────────────────────────────────────────────────────\n\nfunction invalidInput(message: string): ChainReadError {\n return new ChainReadError(\"INVALID_INPUT\", message);\n}\n\n/** A canonical base58 key; the refusal never repeats the input, which may be hostile text. */\nfunction parsedKey(value: unknown, what: string): PublicKey {\n let key: PublicKey | null = null;\n if (typeof value === \"string\") {\n try {\n key = new PublicKey(value);\n } catch {\n key = null;\n }\n }\n if (key === null || key.toBase58() !== value) {\n throw invalidInput(`The ${what} is not a base58 public key`);\n }\n return key;\n}\n\n/** Validated before any RPC call: exactly one target form, canonical keys, a seed-sized task id. */\nfunction resolveTarget(target: ChainReadTarget, programId: PublicKey): PublicKey {\n const t = target as Partial<Record<\"address\" | \"buyer\" | \"taskId\", unknown>>;\n const byAddress = t.address !== undefined;\n const byTask = t.buyer !== undefined || t.taskId !== undefined;\n if (byAddress === byTask || (byTask && (t.buyer === undefined || t.taskId === undefined))) {\n throw invalidInput(\"Give either an address or a buyer with a task id\");\n }\n if (byAddress) return parsedKey(t.address, \"address\");\n const buyer = parsedKey(t.buyer, \"buyer\");\n if (typeof t.taskId !== \"string\") throw invalidInput(\"The task id is not a string\");\n const bytes = new TextEncoder().encode(t.taskId).length;\n if (bytes > MAX_TASK_ID_BYTES) {\n throw invalidInput(\n `The task id is ${String(bytes)} bytes in UTF-8; an escrow's task id is at most ${String(MAX_TASK_ID_BYTES)}`,\n );\n }\n return deriveEscrowPda(programId, buyer, t.taskId);\n}\n\n// ── RPC ───────────────────────────────────────────────────────────────────────\n\ntype ReadMethod = keyof ChainReadRpc;\n\n/**\n * A connection at `rpcUrl` and `confirmed` through which a history holding version-1 transactions\n * reads, a custom transport (headers, a proxy, a test double) going in as `fetchFn` (default\n * `globalThis.fetch`, resolved when called); a connection built any other way fails a version-1\n * history with `CHAIN_RPC_FAILED`, whose archival advice does not apply to that failure.\n */\nexport function chainReadConnection(rpcUrl: string, fetchFn?: typeof globalThis.fetch): Connection {\n return new Connection(rpcUrl, {\n commitment: \"confirmed\",\n fetch: transactionVersionFetch(fetchFn ?? globalThis.fetch),\n });\n}\n\nfunction rpcFailed(method: ReadMethod, cause: unknown): ChainReadError {\n const note = method === \"getAccountInfo\" ? \"\" : ` ${ARCHIVAL_RPC_NOTE}`;\n return new ChainReadError(\"CHAIN_RPC_FAILED\", `The RPC's ${method} call failed.${note}`, {\n cause,\n });\n}\n\nasync function call<T>(method: ReadMethod, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause) {\n throw rpcFailed(method, cause);\n }\n}\n\n/** Whether the RPC refused a transaction above the version the read asked. */\nconst isVersionRefusal = (cause: unknown): boolean =>\n typeof cause === \"object\" &&\n cause !== null &&\n \"code\" in cause &&\n cause.code === SolanaJSONRPCErrorCode.JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION;\n\n/** Transaction `signature` in the history of `at`, at every version the reader reads. */\nasync function readTransaction(rpc: ChainReadRpc, signature: string, at: string) {\n try {\n return await rpc.getTransaction(signature, {\n commitment: \"confirmed\",\n maxSupportedTransactionVersion: MAX_SUPPORTED_TRANSACTION_VERSION,\n });\n } catch (cause) {\n if (isVersionRefusal(cause)) {\n throw new ChainReadError(\n \"CHAIN_TRANSACTION_VERSION\",\n `Transaction ${signature} in the history of ${at} is of a transaction version this reader does not read (it reads legacy, 0 and 1); its events cannot be read`,\n { cause },\n );\n }\n throw rpcFailed(\"getTransaction\", cause);\n }\n}\n\n// ── The open path ─────────────────────────────────────────────────────────────\n\nfunction stringOf(decoded: DecodedEscrowAccount, name: string): string {\n const value = decoded[name];\n if (typeof value !== \"string\") throw new Error(`EscrowAccount.${name} is not a string`);\n return value;\n}\n\nfunction optionalString(decoded: DecodedEscrowAccount, name: string): string | null {\n return decoded[name] === null ? null : stringOf(decoded, name);\n}\n\nfunction numberOf(decoded: DecodedEscrowAccount, name: string): number {\n const value = decoded[name];\n if (typeof value !== \"number\") throw new Error(`EscrowAccount.${name} is not a number`);\n return value;\n}\n\nfunction bigintOf(decoded: DecodedEscrowAccount, name: string): bigint {\n const value = decoded[name];\n if (typeof value !== \"bigint\") throw new Error(`EscrowAccount.${name} is not a u64`);\n return value;\n}\n\nfunction figures(base: Omit<ChainEscrowFigures, \"feeMicro\" | \"depositMicro\">): ChainEscrowFigures {\n const feeMicro = escrowFee(base.amountMicro, base.feeBps);\n return { ...base, feeMicro, depositMicro: base.amountMicro + feeMicro };\n}\n\nfunction readAccount(\n address: PublicKey,\n owner: PublicKey,\n data: Uint8Array,\n programId: PublicKey,\n cluster: SolanaCluster,\n): ChainEscrowReading {\n const at = address.toBase58();\n const refuse = (problem: AccountProblem): ChainReadError =>\n new ChainReadError(\n \"CHAIN_ACCOUNT_INVALID\",\n `The account at ${at} is not a current EscrowAccount: ${problem.detail}`,\n { reason: problem.reason },\n );\n if (!owner.equals(programId)) {\n throw refuse(\n new AccountProblem(\n \"owner\",\n `it is owned by ${owner.toBase58()}, not the program ${programId.toBase58()}`,\n ),\n );\n }\n let decoded: DecodedEscrowAccount;\n try {\n decoded = decodeAccount(data);\n } catch (err) {\n if (err instanceof AccountProblem) throw refuse(err);\n throw err;\n }\n const buyer = stringOf(decoded, \"buyer\");\n const taskId = stringOf(decoded, \"task_id\");\n const derived =\n new TextEncoder().encode(taskId).length <= MAX_TASK_ID_BYTES\n ? deriveEscrowPda(programId, new PublicKey(buyer), taskId)\n : null;\n if (!derived?.equals(address)) {\n throw refuse(new AccountProblem(\"pda\", \"its buyer and task id do not derive this address\"));\n }\n const variant = stringOf(decoded, \"state\") as (typeof STATE_VARIANTS)[number];\n const state = STATE_OF[variant];\n return {\n source: \"account\",\n cluster,\n programId: programId.toBase58(),\n state,\n disputed: state === EscrowState.DISPUTED,\n figures: figures({\n address: at,\n buyer,\n worker: optionalString(decoded, \"assigned_worker\"),\n taskId,\n amountMicro: bigintOf(decoded, \"amount_usdc\"),\n feeBps: numberOf(decoded, \"fee_bps\"),\n deadline: numberOf(decoded, \"deadline\"),\n specHash: stringOf(decoded, \"spec_hash\"),\n createdAt: numberOf(decoded, \"created_at\"),\n deliverableHash: optionalString(decoded, \"deliverable_hash\"),\n proofUri: optionalString(decoded, \"proof_uri\"),\n submittedAt: decoded.submitted_at === null ? null : numberOf(decoded, \"submitted_at\"),\n }),\n settlement: null,\n signatures: [],\n };\n}\n\n// ── The closed path ───────────────────────────────────────────────────────────\n\ninterface LifecycleTransaction {\n signature: string;\n events: EscroEvent[];\n}\n\nfunction base64Bytes(text: string): Uint8Array {\n return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));\n}\n\n/** The program's events for `address` in one transaction's logs, in log order. */\nfunction eventsFor(\n logs: readonly string[],\n programId: string,\n address: string,\n signature: string,\n): EscroEvent[] {\n const unreadable = (detail: string): ChainReadError =>\n new ChainReadError(\n \"CHAIN_LOGS_TRUNCATED\",\n `Transaction ${signature} in the history of ${address} ${detail}; its events cannot be read`,\n );\n let walked;\n try {\n walked = walkProgramLogs(logs, programId);\n } catch (err) {\n if (err instanceof LogTruncatedError) throw unreadable(\"has truncated logs\");\n throw unreadable(\"has logs whose frames do not nest\");\n }\n const events: EscroEvent[] = [];\n for (const line of walked.events) {\n let event: EscroEvent | null;\n try {\n event = decodeEscroEvent(base64Bytes(line.data));\n } catch {\n throw unreadable(\"logs an event that does not decode\");\n }\n if (event !== null && event.escrow === address) events.push(event);\n }\n return events;\n}\n\n/**\n * The newest lifecycle at `address`: the listing newest first (block order, never re-sorted),\n * failed entries skipped unfetched, back to the transaction holding the newest EscrowCreated.\n */\nasync function readLifecycle(\n rpc: ChainReadRpc,\n address: PublicKey,\n programId: string,\n maxTransactions: number,\n): Promise<LifecycleTransaction[]> {\n const at = address.toBase58();\n const newestFirst: LifecycleTransaction[] = [];\n let pages = 0;\n let fetched = 0;\n let listed = false;\n let before: string | undefined;\n for (;;) {\n if (pages === CHAIN_READ_MAX_SIGNATURE_PAGES) {\n throw new ChainReadError(\n \"CHAIN_HISTORY_BUDGET\",\n `Reading the history of ${at} needs more than ${String(CHAIN_READ_MAX_SIGNATURE_PAGES)} pages of ${String(SIGNATURE_PAGE)} signatures`,\n );\n }\n const page = await call(\"getSignaturesForAddress\", () =>\n rpc.getSignaturesForAddress(\n address,\n { limit: SIGNATURE_PAGE, ...(before !== undefined && { before }) },\n \"confirmed\",\n ),\n );\n pages += 1;\n if (page.length > 0) listed = true;\n for (const entry of page) {\n if (entry.err !== null) continue;\n if (fetched === maxTransactions) {\n throw new ChainReadError(\n \"CHAIN_HISTORY_BUDGET\",\n `Reading the history of ${at} needs more than ${String(maxTransactions)} transactions`,\n );\n }\n const tx = await readTransaction(rpc, entry.signature, at);\n fetched += 1;\n if (tx === null) {\n throw new ChainReadError(\n \"CHAIN_HISTORY_INCOMPLETE\",\n `This RPC does not serve transaction ${entry.signature} in the history of ${at}. ${ARCHIVAL_RPC_NOTE}`,\n );\n }\n if (tx.meta === null) {\n throw new ChainReadError(\n \"CHAIN_HISTORY_INCOMPLETE\",\n `This RPC serves transaction ${entry.signature} in the history of ${at} without its logs. ${ARCHIVAL_RPC_NOTE}`,\n );\n }\n if (tx.meta.err !== null) continue;\n const logs = tx.meta.logMessages;\n if (logs === null || logs === undefined) {\n throw new ChainReadError(\n \"CHAIN_HISTORY_INCOMPLETE\",\n `This RPC serves transaction ${entry.signature} in the history of ${at} without its logs. ${ARCHIVAL_RPC_NOTE}`,\n );\n }\n const events = eventsFor(logs, programId, at, entry.signature);\n const created = events.map((e) => e.name).lastIndexOf(\"EscrowCreated\");\n if (created !== -1) {\n newestFirst.push({ signature: entry.signature, events: events.slice(created) });\n return newestFirst.reverse();\n }\n if (events.length > 0) newestFirst.push({ signature: entry.signature, events });\n }\n const last = page.at(-1);\n if (page.length < SIGNATURE_PAGE || last === undefined) break;\n before = last.signature;\n }\n if (!listed) {\n throw new ChainReadError(\n \"CHAIN_ESCROW_NOT_FOUND\",\n `No account and no transaction at ${at} on this RPC. ${ARCHIVAL_RPC_NOTE}`,\n );\n }\n throw new ChainReadError(\n \"CHAIN_HISTORY_INCOMPLETE\",\n `The history of ${at} on this RPC does not reach the EscrowCreated of its latest lifecycle. ${ARCHIVAL_RPC_NOTE}`,\n );\n}\n\nfunction readHistory(\n lifecycle: LifecycleTransaction[],\n address: string,\n programId: string,\n cluster: SolanaCluster,\n): ChainEscrowReading {\n const events = lifecycle.flatMap((t) =>\n t.events.map((event) => ({ event, signature: t.signature })),\n );\n const create = events[0]?.event;\n const last = events.at(-1);\n if (create?.name !== \"EscrowCreated\" || last === undefined) {\n throw new Error(`the lifecycle of ${address} does not open with EscrowCreated`);\n }\n let settlement: ChainSettlement;\n let state: EscrowState;\n const settled = last.event;\n if (settled.name === \"PaymentReleased\") {\n state = EscrowState.COMPLETED;\n settlement = {\n kind: \"released\",\n workerAmountMicro: settled.workerAmount,\n feeAmountMicro: settled.feeAmount,\n refundAmountMicro: null,\n resolvedAt: settled.resolvedAt,\n signature: last.signature,\n };\n } else if (settled.name === \"BuyerRefunded\" || settled.name === \"EscrowCancelled\") {\n const cancelled = settled.name === \"EscrowCancelled\";\n state = cancelled ? EscrowState.CANCELLED : EscrowState.REFUNDED;\n settlement = {\n kind: cancelled ? \"cancelled\" : \"refunded\",\n workerAmountMicro: null,\n feeAmountMicro: null,\n refundAmountMicro: settled.refundAmount,\n resolvedAt: cancelled ? settled.cancelledAt : settled.resolvedAt,\n signature: last.signature,\n };\n } else {\n throw new ChainReadError(\n \"CHAIN_HISTORY_INCOMPLETE\",\n `The latest lifecycle at ${address} is not settled in its history and has no account. ${ARCHIVAL_RPC_NOTE}`,\n );\n }\n let claimedBy: string | null = null;\n let submitted: { deliverableHash: string; proofUri: string | null; submittedAt: number } | null =\n null;\n let disputed = false;\n for (const { event } of events) {\n if (event.name === \"TaskClaimed\") claimedBy = event.worker;\n if (event.name === \"DeliverableSubmitted\") submitted = event;\n if (event.name === \"DisputeRaised\") disputed = true;\n }\n return {\n source: \"history\",\n cluster,\n programId,\n state,\n disputed,\n figures: figures({\n address,\n buyer: create.buyer,\n worker: create.assignedWorker ?? claimedBy,\n taskId: create.taskId,\n amountMicro: create.amountUsdc,\n feeBps: create.feeBps,\n deadline: create.deadline,\n specHash: create.specHash,\n createdAt: create.createdAt,\n deliverableHash: submitted?.deliverableHash ?? null,\n proofUri: submitted?.proofUri ?? null,\n submittedAt: submitted?.submittedAt ?? null,\n }),\n settlement,\n signatures: lifecycle.map((t) => t.signature),\n };\n}\n\n/**\n * What the program recorded for one escrow, read from `options.rpc` alone. An open escrow reads\n * from its account and makes no history call; a closed one is rebuilt from the program's events\n * in the address's history, its newest lifecycle only. Throws {@link ChainReadError}.\n */\nexport async function readEscrowFromChain(\n target: ChainReadTarget,\n options: ReadEscrowFromChainOptions,\n): Promise<ChainEscrowReading> {\n const maxTransactions = options.maxTransactions ?? CHAIN_READ_MAX_TRANSACTIONS;\n if (!Number.isSafeInteger(maxTransactions) || maxTransactions < 1) {\n throw invalidInput(\"maxTransactions must be a positive integer\");\n }\n const id = getProgramId(options.cluster);\n assertProgramIdNotPlaceholder(id, options.cluster);\n const programId = new PublicKey(id);\n const address = resolveTarget(target, programId);\n const rpc = options.rpc;\n const account = await call(\"getAccountInfo\", () =>\n rpc.getAccountInfo(address, { commitment: \"confirmed\" }),\n );\n // Anyone can send lamports to a closed escrow's address; the System-owned, empty account that\n // leaves is no escrow, and the escrow's record is its history.\n const closedButFunded =\n account !== null && account.owner.equals(SystemProgram.programId) && account.data.length === 0;\n if (account !== null && !closedButFunded) {\n return readAccount(address, account.owner, account.data, programId, options.cluster);\n }\n const lifecycle = await readLifecycle(rpc, address, id, maxTransactions);\n return readHistory(lifecycle, address.toBase58(), id, options.cluster);\n}\n","// The program's event layouts and their decoder, the off-chain copy this package's chain readers\n// (the SDK's among them) decode with; the layouts are locked to the program's committed IDL by a\n// test, and Anchor's BorshEventCoder decodes the same payloads as an independent second decoder.\nimport bs58 from \"bs58\";\n\nimport { escrowFee } from \"../config.js\";\n\ntype Scalar = \"pubkey\" | \"string\" | \"u64\" | \"i64\" | \"u16\" | \"bool\";\nexport type EventFieldType = Scalar | { readonly option: \"pubkey\" | \"string\" };\n\n/** Each event's discriminator and Borsh fields, in IDL order with IDL names and types. */\nexport const ESCRO_EVENT_LAYOUTS = {\n EscrowCreated: {\n discriminator: [70, 127, 105, 102, 92, 97, 7, 173],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"buyer\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"amount_usdc\", \"u64\"],\n [\"fee_bps\", \"u16\"],\n [\"deadline\", \"i64\"],\n [\"spec_hash\", \"string\"],\n [\"created_at\", \"i64\"],\n [\"assigned_worker\", { option: \"pubkey\" }],\n [\"marketplace_id\", { option: \"string\" }],\n [\"referrer_wallet\", { option: \"pubkey\" }],\n [\"referrer_bps\", \"u16\"],\n ],\n },\n TaskClaimed: {\n discriminator: [208, 90, 243, 116, 80, 15, 228, 202],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"worker\", \"pubkey\"],\n [\"claimed_at\", \"i64\"],\n [\"assigned_at_creation\", \"bool\"],\n [\"marketplace_id\", { option: \"string\" }],\n ],\n },\n DeliverableSubmitted: {\n discriminator: [128, 198, 110, 44, 67, 73, 255, 99],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"worker\", \"pubkey\"],\n [\"deliverable_hash\", \"string\"],\n [\"proof_uri\", { option: \"string\" }],\n [\"submitted_at\", \"i64\"],\n ],\n },\n DisputeRaised: {\n discriminator: [246, 167, 109, 37, 142, 45, 38, 176],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"disputant\", \"pubkey\"],\n [\"reason\", \"string\"],\n [\"raised_at\", \"i64\"],\n ],\n },\n EscrowCancelled: {\n discriminator: [98, 241, 195, 122, 213, 0, 162, 161],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"buyer\", \"pubkey\"],\n [\"refund_amount\", \"u64\"],\n [\"marketplace_id\", { option: \"string\" }],\n [\"cancelled_at\", \"i64\"],\n ],\n },\n PaymentReleased: {\n discriminator: [160, 132, 155, 232, 46, 254, 69, 219],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"worker\", \"pubkey\"],\n [\"worker_amount\", \"u64\"],\n [\"fee_amount\", \"u64\"],\n [\"referrer_amount\", \"u64\"],\n [\"referrer\", { option: \"pubkey\" }],\n [\"marketplace_id\", { option: \"string\" }],\n [\"resolved_at\", \"i64\"],\n ],\n },\n BuyerRefunded: {\n discriminator: [146, 238, 116, 115, 63, 254, 107, 176],\n fields: [\n [\"escrow\", \"pubkey\"],\n [\"task_id\", \"string\"],\n [\"buyer\", \"pubkey\"],\n [\"refund_amount\", \"u64\"],\n [\"marketplace_id\", { option: \"string\" }],\n [\"resolved_at\", \"i64\"],\n ],\n },\n} as const satisfies Record<\n string,\n {\n discriminator: readonly number[];\n fields: readonly (readonly [string, EventFieldType])[];\n }\n>;\n\nexport type EscroEventName = keyof typeof ESCRO_EVENT_LAYOUTS;\n\nexport const ESCRO_EVENT_NAMES = Object.keys(ESCRO_EVENT_LAYOUTS) as readonly EscroEventName[];\n\nexport interface EscrowCreatedEvent {\n name: \"EscrowCreated\";\n escrow: string;\n buyer: string;\n taskId: string;\n amountUsdc: bigint;\n feeBps: number;\n deadline: number;\n specHash: string;\n createdAt: number;\n assignedWorker: string | null;\n}\n\nexport interface TaskClaimedEvent {\n name: \"TaskClaimed\";\n escrow: string;\n taskId: string;\n worker: string;\n claimedAt: number;\n}\n\nexport interface DeliverableSubmittedEvent {\n name: \"DeliverableSubmitted\";\n escrow: string;\n taskId: string;\n worker: string;\n deliverableHash: string;\n proofUri: string | null;\n submittedAt: number;\n}\n\nexport interface DisputeRaisedEvent {\n name: \"DisputeRaised\";\n escrow: string;\n taskId: string;\n disputant: string;\n reason: string;\n raisedAt: number;\n}\n\nexport interface EscrowCancelledEvent {\n name: \"EscrowCancelled\";\n escrow: string;\n taskId: string;\n buyer: string;\n refundAmount: bigint;\n cancelledAt: number;\n}\n\nexport interface PaymentReleasedEvent {\n name: \"PaymentReleased\";\n escrow: string;\n taskId: string;\n worker: string;\n workerAmount: bigint;\n feeAmount: bigint;\n resolvedAt: number;\n}\n\nexport interface BuyerRefundedEvent {\n name: \"BuyerRefunded\";\n escrow: string;\n taskId: string;\n buyer: string;\n refundAmount: bigint;\n resolvedAt: number;\n}\n\nexport type EscroEvent =\n | EscrowCreatedEvent\n | TaskClaimedEvent\n | DeliverableSubmittedEvent\n | DisputeRaisedEvent\n | EscrowCancelledEvent\n | PaymentReleasedEvent\n | BuyerRefundedEvent;\n\n/** The amount fields of a settle event. */\nexport type SettleAmounts =\n | Pick<PaymentReleasedEvent, \"name\" | \"workerAmount\" | \"feeAmount\">\n | Pick<EscrowCancelledEvent, \"name\" | \"refundAmount\">\n | Pick<BuyerRefundedEvent, \"name\" | \"refundAmount\">;\n\n/**\n * Whether a settle event carries the amounts the program computes for an escrow of `amount` at\n * `feeBps`: a release pays the worker `amount` and the treasury the fee, a cancel or refund\n * returns `amount` plus the fee. Exact bigint arithmetic.\n */\nexport function settleAmountsMatch(event: SettleAmounts, amount: bigint, feeBps: number): boolean {\n const fee = escrowFee(amount, feeBps);\n return event.name === \"PaymentReleased\"\n ? event.workerAmount === amount && event.feeAmount === fee\n : event.refundAmount === amount + fee;\n}\n\ntype FieldValue = string | bigint | number | boolean | null;\n\nclass Reader {\n private at = 0;\n constructor(\n private readonly data: Uint8Array,\n private readonly event: string,\n ) {}\n\n private take(n: number): Uint8Array {\n if (this.at + n > this.data.length) {\n throw new Error(\n `${this.event} payload of ${String(this.data.length)} bytes is truncated at byte ${String(this.at)}`,\n );\n }\n const bytes = this.data.subarray(this.at, this.at + n);\n this.at += n;\n return bytes;\n }\n\n private view(n: number): DataView {\n const bytes = this.take(n);\n return new DataView(bytes.buffer, bytes.byteOffset, n);\n }\n\n read(type: EventFieldType): FieldValue {\n if (typeof type !== \"string\") {\n const tag = this.view(1).getUint8(0);\n if (tag === 0) return null;\n if (tag !== 1) throw new Error(`${this.event}: option tag ${String(tag)} is neither 0 nor 1`);\n return this.read(type.option);\n }\n switch (type) {\n case \"pubkey\":\n return bs58.encode(this.take(32));\n case \"string\": {\n const length = this.view(4).getUint32(0, true);\n return new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(this.take(length));\n }\n case \"u64\":\n return this.view(8).getBigUint64(0, true);\n case \"i64\": {\n const value = this.view(8).getBigInt64(0, true);\n if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {\n throw new Error(`${this.event}: i64 ${value.toString()} is outside the safe range`);\n }\n return Number(value);\n }\n case \"u16\":\n return this.view(2).getUint16(0, true);\n case \"bool\": {\n const byte = this.view(1).getUint8(0);\n if (byte > 1) throw new Error(`${this.event}: bool byte ${String(byte)}`);\n return byte === 1;\n }\n }\n }\n\n end(): void {\n if (this.at !== this.data.length) {\n throw new Error(\n `${this.event} payload has ${String(this.data.length - this.at)} trailing bytes`,\n );\n }\n }\n}\n\ntype Fields = ReadonlyMap<string, FieldValue>;\n\nfunction field(fields: Fields, name: string): FieldValue {\n if (!fields.has(name)) throw new Error(`event field ${name} is not in the layout`);\n return fields.get(name) ?? null;\n}\nfunction str(fields: Fields, name: string): string {\n const v = field(fields, name);\n if (typeof v !== \"string\") throw new Error(`event field ${name} is not a string`);\n return v;\n}\nfunction optStr(fields: Fields, name: string): string | null {\n const v = field(fields, name);\n return v === null ? null : str(fields, name);\n}\nfunction u64(fields: Fields, name: string): bigint {\n const v = field(fields, name);\n if (typeof v !== \"bigint\") throw new Error(`event field ${name} is not a u64`);\n return v;\n}\nfunction num(fields: Fields, name: string): number {\n const v = field(fields, name);\n if (typeof v !== \"number\") throw new Error(`event field ${name} is not a number`);\n return v;\n}\n\nfunction build(name: EscroEventName, f: Fields): EscroEvent {\n const escrow = str(f, \"escrow\");\n switch (name) {\n case \"EscrowCreated\":\n return {\n name,\n escrow,\n buyer: str(f, \"buyer\"),\n taskId: str(f, \"task_id\"),\n amountUsdc: u64(f, \"amount_usdc\"),\n feeBps: num(f, \"fee_bps\"),\n deadline: num(f, \"deadline\"),\n specHash: str(f, \"spec_hash\"),\n createdAt: num(f, \"created_at\"),\n assignedWorker: optStr(f, \"assigned_worker\"),\n };\n case \"TaskClaimed\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n worker: str(f, \"worker\"),\n claimedAt: num(f, \"claimed_at\"),\n };\n case \"DeliverableSubmitted\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n worker: str(f, \"worker\"),\n deliverableHash: str(f, \"deliverable_hash\"),\n proofUri: optStr(f, \"proof_uri\"),\n submittedAt: num(f, \"submitted_at\"),\n };\n case \"DisputeRaised\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n disputant: str(f, \"disputant\"),\n reason: str(f, \"reason\"),\n raisedAt: num(f, \"raised_at\"),\n };\n case \"EscrowCancelled\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n buyer: str(f, \"buyer\"),\n refundAmount: u64(f, \"refund_amount\"),\n cancelledAt: num(f, \"cancelled_at\"),\n };\n case \"PaymentReleased\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n worker: str(f, \"worker\"),\n workerAmount: u64(f, \"worker_amount\"),\n feeAmount: u64(f, \"fee_amount\"),\n resolvedAt: num(f, \"resolved_at\"),\n };\n case \"BuyerRefunded\":\n return {\n name,\n escrow,\n taskId: str(f, \"task_id\"),\n buyer: str(f, \"buyer\"),\n refundAmount: u64(f, \"refund_amount\"),\n resolvedAt: num(f, \"resolved_at\"),\n };\n }\n}\n\n/**\n * Decode one event payload (the bytes of a `Program data:` line). Null when the discriminator\n * is none of the program's events; a payload that opens with one but does not fill its layout\n * exactly throws.\n */\nexport function decodeEscroEvent(data: Uint8Array): EscroEvent | null {\n const name = ESCRO_EVENT_NAMES.find((n) =>\n ESCRO_EVENT_LAYOUTS[n].discriminator.every((byte, i) => data[i] === byte),\n );\n if (name === undefined) return null;\n const reader = new Reader(data.subarray(8), name);\n const fields = new Map<string, FieldValue>();\n for (const [fieldName, type] of ESCRO_EVENT_LAYOUTS[name].fields) {\n fields.set(fieldName, reader.read(type));\n }\n reader.end();\n return build(name, fields);\n}\n","// The devnet deploy tooling rewrites the devnet values after each devnet deploy; only the\n// mainnet deploy tooling or a human mainnet bootstrap changes the mainnet values. The two\n// clusters have distinct program ids and upgrade authorities, so a leaked devnet upgrade authority\n// cannot upgrade mainnet.\n\nexport type SolanaCluster = \"devnet\" | \"mainnet\";\n\nexport const PROGRAM_ID_DEVNET = \"EjLpJ3obUYk1f2KDensU7UdGBZTxSdxufm7CSnMA3H5C\" as const;\nexport const PLATFORM_CONFIG_PDA_DEVNET = \"5BYnq9YsCTaMxBLJhBn4TPnCQuxiHcG5eZ2ygLJBu9dc\" as const;\nexport const DEVNET_USDC_MINT = \"4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU\" as const;\nexport const DEPLOYED_AT_DEVNET = \"2026-08-15T17:24:37.149Z\" as const;\n\nexport const PROGRAM_ID_MAINNET = \"4CwLNRF4mFXutiBGjtMHQBxh8whW8T8EyvJXdRhY1rvr\" as const;\nexport const PLATFORM_CONFIG_PDA_MAINNET = \"7zPti535SmzvkdtmKaGR8w4niHLiEidWCqCaQXLbQvhn\" as const;\nexport const MAINNET_USDC_MINT = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\" as const;\n// Pinned mainnet PlatformConfig values: the treasury and oracle authority the program is\n// configured with.\nexport const MAINNET_TREASURY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\nexport const MAINNET_ORACLE_AUTHORITY = \"G2Cr4PAJ58ZSYX2ceCMt2DtP1KBFXA9oYDtJJKZaKKJT\" as const;\n// The 2-of-2 Squads vault: the treasury's address, named apart because the roles differ.\nexport const MAINNET_UPGRADE_AUTHORITY = \"GSNa5eHUkKUp3RQr8vYbQx471FzWztfMsvhNhW2MUBVq\" as const;\n// The AdminConfig PDA, seeds [b\"admin\"] under PROGRAM_ID_MAINNET (a test derives it).\nexport const ADMIN_CONFIG_PDA_MAINNET = \"9SoVXPDjKFKA6sEo5oVp1RHij2FKVR52SCvoD2ELDHgD\" as const;\n// MAINNET_TREASURY's associated token account for MAINNET_USDC_MINT (a test derives it).\nexport const MAINNET_TREASURY_USDC_ATA = \"DAQfw4T3MzzfrWjkVy3mbWtWuUYVoaZThvsEF1RdM2kg\" as const;\n\n// An RPC proves its cluster by its genesis hash; the ops CLIs refuse a mismatch.\nexport const DEVNET_GENESIS_HASH = \"EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG\" as const;\nexport const MAINNET_GENESIS_HASH = \"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d\" as const;\n\n// CAIP-2 ids: `solana:` plus the first 32 characters of the genesis hash (a test locks them to\n// the hashes above and to the binding's appendix, docs/specs/scheme_on_delivery_svm.md).\nexport const SOLANA_CAIP2_MAINNET = \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\" as const;\nexport const SOLANA_CAIP2_DEVNET = \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\" as const;\n\nexport function getCaip2Network(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? SOLANA_CAIP2_MAINNET : SOLANA_CAIP2_DEVNET;\n}\n\n/** The cluster a CAIP-2 id names, exactly; undefined for any other string. */\nexport function clusterOfCaip2(network: string): SolanaCluster | undefined {\n if (network === SOLANA_CAIP2_MAINNET) return \"mainnet\";\n if (network === SOLANA_CAIP2_DEVNET) return \"devnet\";\n return undefined;\n}\n\n// The default API base per cluster: a mirror of the hosted API's domain name per cluster.\nexport const API_URLS: Record<SolanaCluster, string> = {\n devnet: \"https://api-devnet.escro.ai\",\n mainnet: \"https://api.escro.ai\",\n};\n\nexport function getApiUrl(cluster: SolanaCluster): string {\n return API_URLS[cluster];\n}\n\n/** Solana's public RPC per cluster: the default where no keyed endpoint is configured. */\nexport const PUBLIC_RPC_URLS: Readonly<Record<SolanaCluster, string>> = {\n devnet: \"https://api.devnet.solana.com\",\n mainnet: \"https://api.mainnet-beta.solana.com\",\n};\n\nexport function getPublicRpcUrl(cluster: SolanaCluster): string {\n return PUBLIC_RPC_URLS[cluster];\n}\n\n/** Platform oracle fee rate in basis points (50 bps = 0.50%). */\nexport const PLATFORM_FEE_BPS = 50 as const;\n\n/**\n * The program's fee on an escrow `amount` at `feeBps`, in micro-USDC: `floor(amount * feeBps /\n * 10_000)`, as `create_escrow` computes it. The buyer deposits `amount` plus this fee.\n */\nexport function escrowFee(amount: bigint, feeBps: number): bigint {\n return (amount * BigInt(feeBps)) / 10_000n;\n}\n\n/**\n * The minimum escrow `amount` in micro-USDC ($5.00): the worker's net, not the buyer's deposit\n * (amount plus the additive fee). Mirrors `MIN_ESCROW_AMOUNT` in the program; a test reads the\n * program source and fails on drift.\n */\nexport const MIN_ESCROW_AMOUNT = 5_000_000 as const;\n\n/**\n * The account layout version the program writes and accepts. MIRROR of\n * `CURRENT_ACCOUNT_VERSION` in the program; a test reads the program source and fails on\n * drift.\n */\nexport const CURRENT_ACCOUNT_VERSION = 1 as const;\n\n/**\n * The most UTF-8 bytes `raise_dispute` accepts as a reason. MIRROR of the program's\n * `MAX_REASON_LEN` in its `raise_dispute` instruction; a test reads the program source and fails\n * on drift. Checked off chain by `disputeReasonError`.\n */\nexport const MAX_DISPUTE_REASON_BYTES = 200 as const;\n\n/**\n * The most UTF-8 bytes `create_escrow`'s `spec_hash` may hold. MIRROR of `#[max_len(64)]` on\n * `spec_hash` in the program's `EscrowAccount`; a test reads the program source and fails on\n * drift. The program bounds the field only by the account's allocation; the\n * API's create builder enforces this cap.\n */\nexport const MAX_SPEC_HASH_BYTES = 64 as const;\n\n/**\n * The most UTF-8 bytes `submit_deliverable`'s `proof_uri` may hold. MIRROR of the `#[max_len]` on\n * `proof_uri` in the program's `EscrowAccount`; a test reads the program source and fails on\n * drift. The program bounds the field only by the account's allocation; the\n * API's submit builder enforces this cap. Checked off chain by `proofUriError`.\n */\nexport const MAX_PROOF_URI_BYTES = 128 as const;\n\n/**\n * Indeterminate settlement reads one escrow may accrue before the oracle stops retrying it and\n * alerts once. Each one follows a read that found the escrow's account closed, so an escrow past\n * the bound has nothing left to sign. Every off-chain reader of the bound reads this one constant.\n */\nexport const RECONCILE_ATTEMPT_BOUND = 5;\n\n// Mirrors of refund_buyer.rs REFUND_GRACE_SECONDS and timeout_release.rs TIMEOUT_SECONDS (the\n// non-feature builds); a test reads the program source and fails on drift.\nexport const ONCHAIN_REFUND_GRACE_SECONDS = 900 as const;\nexport const ONCHAIN_TIMEOUT_SECONDS = 86_400 as const;\n\n/**\n * The cluster clock lags wall clock, so an off-chain gate that must clear an on-chain one runs\n * at the on-chain offset plus this margin; at the bare boundary the chain still rejects.\n */\nexport const CLOCK_SKEW_SECONDS = 60 as const;\n\nexport const SCANNER_REFUND_GRACE_SECONDS = (ONCHAIN_REFUND_GRACE_SECONDS +\n CLOCK_SKEW_SECONDS) as 960;\nexport const SCANNER_TIMEOUT_SECONDS = (ONCHAIN_TIMEOUT_SECONDS + CLOCK_SKEW_SECONDS) as 86_460;\n\n/**\n * The furthest escrow deadline, in seconds from now, an agent-driven pay surface accepts (7 days): the\n * ceiling and the default of the MCP's, SAK's and Eliza's pay bound.\n */\nexport const PAY_MAX_DEADLINE_SECONDS = 604_800 as const;\n\n/** The System Program address: no program deploys there, so it marks an unbootstrapped mainnet. */\nexport const MAINNET_PROGRAM_ID_PLACEHOLDER = \"11111111111111111111111111111111\" as const;\n\nexport function getProgramId(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PROGRAM_ID_MAINNET : PROGRAM_ID_DEVNET;\n}\n\nexport function getPlatformConfigPda(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? PLATFORM_CONFIG_PDA_MAINNET : PLATFORM_CONFIG_PDA_DEVNET;\n}\n\nexport function getUsdcMint(cluster: SolanaCluster): string {\n return cluster === \"mainnet\" ? MAINNET_USDC_MINT : DEVNET_USDC_MINT;\n}\n\nexport function isPlaceholderProgramId(id: string): boolean {\n return id === MAINNET_PROGRAM_ID_PLACEHOLDER;\n}\n\n/** Throws on mainnet while the program id is the placeholder; call at module init. */\nexport function assertProgramIdNotPlaceholder(id: string, cluster: SolanaCluster): void {\n if (cluster === \"mainnet\" && isPlaceholderProgramId(id)) {\n throw new Error(\n `PROGRAM_ID_MAINNET is still the System Program placeholder (${MAINNET_PROGRAM_ID_PLACEHOLDER}). ` +\n \"This build carries no deployed mainnet program id: use a release built after the \" +\n \"mainnet bootstrap.\",\n );\n }\n}\n\nexport function parseClusterEnv(raw: string | undefined): SolanaCluster {\n if (raw === \"mainnet\") return \"mainnet\";\n if (raw === \"devnet\" || raw === undefined || raw === \"\") return \"devnet\";\n throw new Error(`CLUSTER env var must be \"devnet\" or \"mainnet\", got \"${raw}\"`);\n}\n","// The one walk over a transaction's log messages that attributes `Program data:` lines to the\n// program's own invocations; no other source walks them.\nconst INVOKE = /^Program (\\w+) invoke \\[(\\d+)\\]$/;\nconst EXIT = /^Program (\\w+) (?:success|failed)/;\nconst DATA = \"Program data: \";\nconst TRUNCATED = \"Log truncated\";\n\n/** The logs end in `Log truncated`: what is left cannot say what the transaction did. */\nexport class LogTruncatedError extends Error {\n constructor() {\n super(\"the logs are truncated; their events cannot be trusted\");\n this.name = \"LogTruncatedError\";\n }\n}\n\nexport interface ProgramLogEvent {\n /** The line's index in the log messages. */\n logIndex: number;\n /** The top-level instruction under which the program's frame ran. */\n instructionIndex: number;\n /** The program frame's invocation depth: 1 at the top level, more when reached by CPI. */\n depth: number;\n /** The payload as logged (base64). */\n data: string;\n}\n\nexport interface ProgramLogWalk {\n /** The program id of each top-level invocation, in instruction order. */\n topLevelPrograms: string[];\n /** Every `Program data:` line logged while one of `programId`'s frames was innermost. */\n events: ProgramLogEvent[];\n /** The top-level instructions under which `programId` was invoked by CPI (depth above 1). */\n cpiInstructionIndexes: number[];\n}\n\n/**\n * Walk `logs` keeping the invocation stack. A `Program data:` line is attributed to `programId`\n * only while that program's frame is innermost; a line under any other program's frame, at any\n * depth, is not. Throws {@link LogTruncatedError} on `Log truncated`, and a plain Error on frames\n * that do not nest.\n */\nexport function walkProgramLogs(logs: readonly string[], programId: string): ProgramLogWalk {\n const stack: { program: string; depth: number }[] = [];\n const walk: ProgramLogWalk = { topLevelPrograms: [], events: [], cpiInstructionIndexes: [] };\n for (const [logIndex, line] of logs.entries()) {\n if (line === TRUNCATED) throw new LogTruncatedError();\n const invoke = INVOKE.exec(line);\n if (invoke) {\n const program = invoke[1] ?? \"\";\n const depth = Number(invoke[2]);\n if (depth !== stack.length + 1) {\n throw new Error(\n `log line ${String(logIndex)} invokes at depth ${String(depth)} inside ${String(stack.length)} frames`,\n );\n }\n if (depth === 1) walk.topLevelPrograms.push(program);\n const instructionIndex = walk.topLevelPrograms.length - 1;\n if (\n depth > 1 &&\n program === programId &&\n !walk.cpiInstructionIndexes.includes(instructionIndex)\n ) {\n walk.cpiInstructionIndexes.push(instructionIndex);\n }\n stack.push({ program, depth });\n continue;\n }\n const exit = EXIT.exec(line);\n if (exit) {\n if (stack.pop()?.program !== exit[1]) {\n throw new Error(`log line ${String(logIndex)} exits a frame it did not enter`);\n }\n continue;\n }\n const top = stack.at(-1);\n if (!line.startsWith(DATA) || top?.program !== programId) continue;\n walk.events.push({\n logIndex,\n instructionIndex: walk.topLevelPrograms.length - 1,\n depth: top.depth,\n data: line.slice(DATA.length),\n });\n }\n return walk;\n}\n","import type { VersionedTransactionResponse } from \"@solana/web3.js\";\nimport bs58 from \"bs58\";\n\nimport {\n ESCROW_INSTRUCTIONS,\n escrowInstructionName,\n type EscrowInstructionName,\n type TransactionView,\n} from \"../instructions.js\";\n\n/** The getSignaturesForAddress page size the hint's ordering gate reads (the RPC's maximum). */\nexport const HINT_LISTING_LIMIT = 1000;\n\n/**\n * Why the chain ingester ledgers a program transaction unclassified, and why the accuracy\n * harness leaves one out: one list for both.\n */\nexport const UNCLASSIFIED_REASONS = [\n \"cpi\",\n \"log_truncated\",\n \"log_mismatch\",\n \"event_mismatch\",\n \"orphan\",\n \"pda_reuse\",\n \"store_rejected\",\n] as const;\nexport type UnclassifiedReason = (typeof UNCLASSIFIED_REASONS)[number];\n\nexport interface TopLevelEscrowInstruction {\n /** The instruction's index in the message. */\n index: number;\n name: EscrowInstructionName;\n /** The account at the instruction's escrow index (base58). */\n escrow: string;\n /** The account at the instruction's signer index (base58). */\n signer: string;\n}\n\n/**\n * Every top-level instruction of `programId` whose discriminator is in the escrow-instruction\n * table, for any escrow. One naming fewer accounts than the table's indexes throws.\n */\nexport function topLevelEscrowInstructions(\n view: TransactionView,\n programId: string,\n): TopLevelEscrowInstruction[] {\n const out: TopLevelEscrowInstruction[] = [];\n for (const [index, ix] of view.instructions.entries()) {\n if (view.accountKeys[ix.programIdIndex] !== programId) continue;\n const name = escrowInstructionName(ix.data);\n if (name === null) continue;\n const entry = ESCROW_INSTRUCTIONS[name];\n const key = (at: number): string => {\n const k = view.accountKeys[ix.accountKeyIndexes[at] ?? -1];\n if (k === undefined) {\n throw new Error(`instruction ${String(index)} (${name}) names no account ${String(at)}`);\n }\n return k;\n };\n out.push({\n index,\n name,\n escrow: key(entry.escrowAccountIndex),\n signer: key(entry.signerAccountIndex),\n });\n }\n return out;\n}\n\n/** The fields of a getTransaction response's inner instructions {@link cpiInstructionIndexes} reads. */\nexport interface InnerInstructionsLike {\n readonly index: number;\n readonly instructions: readonly { readonly programIdIndex: number }[];\n}\n\n/** The top-level instructions under which `programId` ran as an inner (CPI) instruction. */\nexport function cpiInstructionIndexes(\n inner: readonly InnerInstructionsLike[] | null | undefined,\n accountKeys: readonly string[],\n programId: string,\n): number[] {\n return (inner ?? [])\n .filter((group) => group.instructions.some((i) => accountKeys[i.programIdIndex] === programId))\n .map((group) => group.index);\n}\n\n/**\n * The unclassified reasons that refuse a whole transaction rather than one escrow's effect: the\n * ingester quarantines the escrows such a transaction ends, and a recorded refusal of one replays\n * as unclassified.\n */\nexport const TRANSACTION_WIDE_REASONS = [\n \"cpi\",\n \"log_truncated\",\n \"log_mismatch\",\n \"event_mismatch\",\n \"store_rejected\",\n] as const satisfies readonly UnclassifiedReason[];\nexport type TransactionWideReason = (typeof TRANSACTION_WIDE_REASONS)[number];\n\nexport function isTransactionWideReason(reason: string): reason is TransactionWideReason {\n return (TRANSACTION_WIDE_REASONS as readonly string[]).includes(reason);\n}\n\n/** A settle (it closes the account) or a create (it opens a lifecycle): the PDA's lifecycle ends. */\nexport function endsLifecycle(name: EscrowInstructionName): boolean {\n return ESCROW_INSTRUCTIONS[name].cause !== null || name === \"create_escrow\";\n}\n\n/** The fields of a getTransaction response's inner instructions {@link namedEscrows} reads. */\nexport interface InnerInstructionGroupLike {\n readonly index: number;\n readonly instructions: readonly {\n readonly programIdIndex: number;\n readonly accounts: readonly number[];\n readonly data: string;\n }[];\n}\n\n// A web3 VersionedTransactionResponse's inner instructions are accepted as-is.\ntype _AcceptsWeb3InnerGroups = NonNullable<\n NonNullable<VersionedTransactionResponse[\"meta\"]>[\"innerInstructions\"]\n>[number] extends InnerInstructionGroupLike\n ? true\n : never;\nconst _acceptsWeb3InnerGroups: _AcceptsWeb3InnerGroups = true;\nvoid _acceptsWeb3InnerGroups;\n\nexport interface NamedEscrow {\n readonly name: EscrowInstructionName;\n readonly escrow: string;\n}\n\n/**\n * Every escrow instruction of `programId` in the transaction and the escrow it acts on: the top\n * level in message order, then the inner instructions in group and instruction order, a repeated\n * pair once. Read from the message and the inner instructions alone, before any log is trusted.\n * A malformed instruction (too few accounts, an index past the keys, inner data that is not\n * base58) names nothing: chain data never throws here.\n */\nexport function namedEscrows(\n view: TransactionView,\n inner: readonly InnerInstructionGroupLike[] | null | undefined,\n programId: string,\n): NamedEscrow[] {\n const out: NamedEscrow[] = [];\n const add = (programIdIndex: number, accounts: readonly number[], data: Uint8Array): void => {\n if (view.accountKeys[programIdIndex] !== programId) return;\n const name = escrowInstructionName(data);\n if (name === null) return;\n const at = accounts[ESCROW_INSTRUCTIONS[name].escrowAccountIndex];\n const escrow = at === undefined ? undefined : view.accountKeys[at];\n if (escrow === undefined) return;\n if (!out.some((p) => p.name === name && p.escrow === escrow)) out.push({ name, escrow });\n };\n for (const ix of view.instructions) add(ix.programIdIndex, ix.accountKeyIndexes, ix.data);\n for (const group of inner ?? []) {\n for (const ix of group.instructions) {\n let data: Uint8Array;\n try {\n data = bs58.decode(ix.data);\n } catch {\n // Not base58: no instruction the program ran, so it names no escrow.\n continue;\n }\n add(ix.programIdIndex, ix.accounts, data);\n }\n }\n return out;\n}\n","import type { VersionedTransactionResponse } from \"@solana/web3.js\";\n\nimport type { SettlementCause } from \"./types/escrow.js\";\n\n/**\n * The single escrow-instruction table: every instruction that acts on one\n * escrow account, with its Anchor discriminator, the account indices of the\n * escrow PDA and the signing actor, and the settlement cause for the settling\n * instructions (null for the lifecycle ones). A test locks it to the program's\n * committed IDL. Remaining per-package copies migrate here.\n */\nexport const ESCROW_INSTRUCTION_NAMES = [\n \"create_escrow\",\n \"claim_task\",\n \"submit_deliverable\",\n \"raise_dispute\",\n \"cancel_escrow\",\n \"release_payment\",\n \"timeout_release\",\n \"refund_buyer\",\n \"arbitration_release\",\n \"arbitration_refund\",\n] as const;\n\nexport type EscrowInstructionName = (typeof ESCROW_INSTRUCTION_NAMES)[number];\n\nexport interface EscrowInstructionSpec {\n readonly discriminator: Uint8Array;\n readonly escrowAccountIndex: number;\n readonly signerAccountIndex: number;\n readonly cause: SettlementCause | null;\n}\n\nfunction spec(\n discriminator: number[],\n escrowAccountIndex: number,\n cause: SettlementCause | null,\n): EscrowInstructionSpec {\n return {\n discriminator: Uint8Array.from(discriminator),\n escrowAccountIndex,\n signerAccountIndex: 0,\n cause,\n };\n}\n\nexport const ESCROW_INSTRUCTIONS: Readonly<Record<EscrowInstructionName, EscrowInstructionSpec>> = {\n create_escrow: spec([253, 215, 165, 116, 36, 108, 68, 80], 4, null),\n claim_task: spec([49, 222, 219, 238, 155, 68, 221, 136], 1, null),\n submit_deliverable: spec([38, 137, 64, 44, 237, 11, 125, 101], 1, null),\n raise_dispute: spec([41, 243, 1, 51, 150, 95, 246, 73], 1, null),\n cancel_escrow: spec([156, 203, 54, 179, 38, 72, 33, 21], 3, \"CANCELLED\"),\n release_payment: spec([24, 34, 191, 86, 145, 160, 183, 233], 3, \"EXPLICIT_RELEASE\"),\n timeout_release: spec([98, 176, 26, 12, 83, 105, 154, 68], 3, \"TIMEOUT_RELEASE\"),\n refund_buyer: spec([199, 139, 203, 146, 192, 150, 53, 218], 3, \"DEADLINE_REFUND\"),\n arbitration_release: spec([118, 157, 141, 26, 104, 117, 94, 229], 4, \"ARBITRATION_RELEASE\"),\n arbitration_refund: spec([255, 194, 84, 248, 185, 249, 120, 122], 4, \"ARBITRATION_REFUND\"),\n};\n\n/** A landed transaction reduced to what instruction matching needs. */\nexport interface TransactionView {\n /** Static keys, then loaded writable, then loaded readonly addresses (base58). */\n readonly accountKeys: readonly string[];\n readonly instructions: readonly {\n readonly programIdIndex: number;\n readonly accountKeyIndexes: readonly number[];\n readonly data: Uint8Array;\n }[];\n}\n\nexport interface EscrowInstructionMatch {\n name: EscrowInstructionName;\n /** The account at the instruction's signer index (base58). */\n signer: string;\n data: Uint8Array;\n}\n\n/** The table's entry whose discriminator opens `data`, of any program or escrow; null for none. */\nexport function escrowInstructionName(data: Uint8Array): EscrowInstructionName | null {\n for (const name of ESCROW_INSTRUCTION_NAMES) {\n const disc = ESCROW_INSTRUCTIONS[name].discriminator;\n if (disc.every((b, i) => data[i] === b)) return name;\n }\n return null;\n}\n\n/**\n * Every TOP-LEVEL instruction of `programId` in the transaction whose\n * discriminator is in the table and whose escrow account is `escrowPda`.\n * Instructions reached by CPI are not matched: settlement is classified from\n * top-level instructions only.\n */\nexport function findEscrowInstructions(\n view: TransactionView,\n opts: { programId: string; escrowPda: string },\n): EscrowInstructionMatch[] {\n const matches: EscrowInstructionMatch[] = [];\n for (const ix of view.instructions) {\n if (view.accountKeys[ix.programIdIndex] !== opts.programId) continue;\n const name = escrowInstructionName(ix.data);\n if (name === null) continue;\n const entry = ESCROW_INSTRUCTIONS[name];\n const escrowKeyIndex = ix.accountKeyIndexes[entry.escrowAccountIndex];\n const signerKeyIndex = ix.accountKeyIndexes[entry.signerAccountIndex];\n if (escrowKeyIndex === undefined || signerKeyIndex === undefined) continue;\n if (view.accountKeys[escrowKeyIndex] !== opts.escrowPda) continue;\n const signer = view.accountKeys[signerKeyIndex];\n if (signer === undefined) continue;\n matches.push({ name, signer, data: ix.data });\n }\n return matches;\n}\n\ninterface Base58Key {\n toBase58(): string;\n}\n\n/** The fields of a `getTransaction` response that {@link toTransactionView} reads. */\nexport interface TransactionResponseLike {\n transaction: {\n message: {\n staticAccountKeys: readonly Base58Key[];\n compiledInstructions: readonly {\n programIdIndex: number;\n accountKeyIndexes: readonly number[];\n data: Uint8Array;\n }[];\n };\n };\n meta: {\n loadedAddresses?: { writable: readonly Base58Key[]; readonly: readonly Base58Key[] };\n } | null;\n}\n\n// A web3 VersionedTransactionResponse is accepted as-is.\ntype _AcceptsWeb3Response = VersionedTransactionResponse extends TransactionResponseLike\n ? true\n : never;\nconst _acceptsWeb3Response: _AcceptsWeb3Response = true;\nvoid _acceptsWeb3Response;\n\n/** Adapt a landed (legacy or v0, lookup-table-aware) transaction to a {@link TransactionView}. */\nexport function toTransactionView(response: TransactionResponseLike): TransactionView {\n const { message } = response.transaction;\n const loaded = response.meta?.loadedAddresses;\n const accountKeys = [\n ...message.staticAccountKeys,\n ...(loaded?.writable ?? []),\n ...(loaded?.readonly ?? []),\n ].map((k) => k.toBase58());\n return { accountKeys, instructions: message.compiledInstructions };\n}\n","// The one U+0000 rule: a text column refuses U+0000, so no value the store keeps may hold it. The\n// request validators and the chain ingester's store rules both read it. A leaf: it imports nothing.\n\n/** False exactly when `value` holds U+0000, which a text column refuses. */\nexport function storableText(value: string): boolean {\n return !value.includes(\"\\u0000\");\n}\n","// The store's content rules for a decoded event: the chain ingester refuses an event breaking one\n// before any write, and the accuracy harness excludes it by the same rule, so the zero-diff\n// compares like with like. A store rule, not a decode rule: the decoders show what the program\n// recorded. It imports only types and the text rule's leaf, so a bundle that does not call it\n// drops it.\nimport type { EscroEventName } from \"./events.js\";\nimport { storableText } from \"../utils/text.js\";\n\nexport { storableText };\n\n/** The first second a written time may hold: the epoch. */\nexport const STORABLE_TIME_MIN_SECONDS = 0;\n/** The last second a written time may hold, 9999-12-31T23:59:59Z: below JavaScript's Date range. */\nexport const STORABLE_TIME_MAX_SECONDS = 253_402_300_799;\n\nexport interface StoredFields {\n readonly text: readonly string[];\n readonly time: readonly string[];\n}\n\nexport interface StorableRefusal {\n /** The field's IDL (snake_case) name. */\n field: string;\n rule: \"nul\" | \"time_range\";\n}\n\n/**\n * Per event, the IDL names of the fields the chain ingester writes into the store: strings and\n * i64 clock times. Base58 addresses are not listed (bs58 output holds no U+0000). Locked to\n * `ESCRO_EVENT_LAYOUTS` by a test, so a renamed field cannot go unchecked.\n */\nexport const STORED_EVENT_FIELDS: Readonly<Record<EscroEventName, StoredFields>> = {\n EscrowCreated: { text: [\"task_id\", \"spec_hash\"], time: [\"deadline\", \"created_at\"] },\n TaskClaimed: { text: [], time: [\"claimed_at\"] },\n DeliverableSubmitted: { text: [\"deliverable_hash\", \"proof_uri\"], time: [\"submitted_at\"] },\n DisputeRaised: { text: [\"reason\"], time: [\"raised_at\"] },\n EscrowCancelled: { text: [], time: [\"cancelled_at\"] },\n PaymentReleased: { text: [], time: [\"resolved_at\"] },\n BuyerRefunded: { text: [], time: [\"resolved_at\"] },\n};\n\n/** True exactly when `seconds` is an integer in the stored time range, compared exactly. */\nexport function storableTime(seconds: number | bigint): boolean {\n if (typeof seconds === \"number\") {\n return (\n Number.isInteger(seconds) &&\n seconds >= STORABLE_TIME_MIN_SECONDS &&\n seconds <= STORABLE_TIME_MAX_SECONDS\n );\n }\n return (\n seconds >= BigInt(STORABLE_TIME_MIN_SECONDS) && seconds <= BigInt(STORABLE_TIME_MAX_SECONDS)\n );\n}\n\nfunction camelCase(snake: string): string {\n return snake.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase());\n}\n\n/** The field's value under its snake-cased key, else its camel-cased one; absent under both throws. */\nfunction fieldValue(fields: object, event: EscroEventName, field: string): unknown {\n for (const key of [field, camelCase(field)]) {\n if (key in fields) {\n const value: unknown = Reflect.get(fields, key);\n return value;\n }\n }\n throw new Error(`${event}: the decoded event has no field ${field}`);\n}\n\n/** An exact integer from a time value: a number, a bigint, or a BN by its base-10 `toString()`. */\nfunction timeOf(value: unknown): number | bigint | null {\n if (typeof value === \"number\" || typeof value === \"bigint\") return value;\n if (typeof value !== \"object\" || value === null) return null;\n const toString: unknown = Reflect.get(value, \"toString\");\n if (typeof toString !== \"function\") return null;\n const digits: unknown = Reflect.apply(toString, value, []);\n if (typeof digits !== \"string\" || !/^-?\\d+$/.test(digits)) return null;\n return BigInt(digits);\n}\n\n/**\n * The first field of `name`'s stored fields whose value the store cannot hold, text fields before\n * time fields, or null. `fields` is a decoded event under snake- or camel-cased keys: the shared\n * decoder's `EscroEvent` or Anchor's decoded `data`. A null value (an absent option) is storable;\n * a value of any other type than its rule reads refuses. A listed field absent under both casings\n * throws: both decoders fill every layout field, so its absence is a decoder defect.\n */\nexport function unstorableField(fields: object, name: EscroEventName): StorableRefusal | null {\n const stored = STORED_EVENT_FIELDS[name];\n for (const field of stored.text) {\n const value = fieldValue(fields, name, field);\n if (value === null) continue;\n if (typeof value !== \"string\" || !storableText(value)) return { field, rule: \"nul\" };\n }\n for (const field of stored.time) {\n const value = fieldValue(fields, name, field);\n if (value === null) continue;\n const seconds = timeOf(value);\n if (seconds === null || !storableTime(seconds)) return { field, rule: \"time_range\" };\n }\n return null;\n}\n","// The transaction versions a chain reader asks for and decodes. web3 1.98's response struct\n// accepts only `\"legacy\"` and 0, while a version-1 message names static account keys only, the\n// legacy message shape; so a reader asks the RPC for version 1 and its Connection's fetch presents\n// an ok version-1 `getTransaction` result as legacy. A version-1 result naming an address lookup\n// or a loaded address keeps its version and web3 refuses it: a reader stops at a transaction it\n// cannot read rather than read it differently from the chain. A leaf with no runtime import, so\n// it reaches no bundle that does not import `./chain`.\n\n/** The `maxSupportedTransactionVersion` every reader built on {@link transactionVersionFetch} asks. */\nexport const MAX_SUPPORTED_TRANSACTION_VERSION = 1 as const;\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** The parsed JSON of `text`, or undefined when it is not JSON (the caller passes it on as is). */\nfunction parsedJson(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction isSingleGetTransaction(body: unknown): boolean {\n if (typeof body !== \"string\") return false;\n const request = parsedJson(body);\n return isObject(request) && request.method === \"getTransaction\";\n}\n\nconst isEmptyList = (value: unknown): boolean => Array.isArray(value) && value.length === 0;\n\n/** Whether `result` is a version-1 transaction whose message names only static account keys. */\nfunction isStaticVersionOne(result: unknown): result is Record<string, unknown> {\n if (!isObject(result) || result.version !== 1) return false;\n const transaction = result.transaction;\n const message = isObject(transaction) ? transaction.message : undefined;\n const lookups = isObject(message) ? message.addressTableLookups : undefined;\n if (lookups !== undefined && !isEmptyList(lookups)) return false;\n const meta = result.meta;\n if (meta === null) return true;\n if (!isObject(meta)) return false;\n const loaded = meta.loadedAddresses;\n if (loaded === undefined) return true;\n return isObject(loaded) && isEmptyList(loaded.writable) && isEmptyList(loaded.readonly);\n}\n\n/**\n * `fetchFn` with an ok `getTransaction` result of version 1 that names no address lookup and no\n * loaded address presented as `\"legacy\"`, nothing else of it changed. Every other request and\n * every non-ok response is `fetchFn`'s own `Response`; any other ok `getTransaction` response is\n * returned unchanged. One `fetchFn` call per call; its rejection propagates as is.\n */\nexport function transactionVersionFetch(fetchFn: typeof globalThis.fetch): typeof globalThis.fetch {\n return async (input, init) => {\n const response = await fetchFn(input, init);\n if (!response.ok || !isSingleGetTransaction(init?.body)) return response;\n const parsed = parsedJson(await response.clone().text());\n if (!isObject(parsed) || !isStaticVersionOne(parsed.result)) return response;\n const headers = new Headers();\n const contentType = response.headers.get(\"content-type\");\n if (contentType !== null) headers.set(\"content-type\", contentType);\n return new Response(\n JSON.stringify({ ...parsed, result: { ...parsed.result, version: \"legacy\" } }),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n };\n}\n","import { EscroError } from \"../errors.js\";\n\n/** A `PAYMENT-REQUIRED`, `PAYMENT-SIGNATURE` or `PAYMENT-RESPONSE` header that is not the x402 V2 encoding. */\nexport class X402CodecError extends EscroError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, \"X402_CODEC\", undefined, options);\n this.name = \"X402CodecError\";\n }\n}\n\n/** No PlatformConfig account at the cluster's PlatformConfig PDA. */\nexport class PlatformConfigNotFoundError extends EscroError {\n constructor(address: string) {\n super(`No PlatformConfig account at ${address}`, \"PLATFORM_CONFIG_NOT_FOUND\");\n this.name = \"PlatformConfigNotFoundError\";\n }\n}\n\n/** Why an `on-delivery` entry was not selected (docs/specs/scheme_on_delivery_svm.md, client checks). */\nexport type OnDeliveryAcceptRefusal =\n | \"no_entry\"\n | \"network\"\n | \"program\"\n | \"asset\"\n | \"fee_bps\"\n | \"settlement_mode\"\n | \"review_window\"\n | \"fee_payer\"\n | \"payment_flow\"\n | \"amount\"\n | \"over_limit\"\n | \"pay_to\"\n | \"spec_hash\"\n | \"spec_uri\"\n | \"deadline\"\n | \"max_timeout\"\n | \"extra_shape\"\n | \"extension_invalid\"\n | \"extension_terms\"\n | \"acceptance\";\n\n/**\n * No acceptable `on-delivery` entry. `refusals` lists each candidate's first refusal; `index` is the\n * entry's index in `accepts`, or -1 where no entry is concerned (`no_entry`, an `escro` extension\n * parsed alone, an entry `buildEscrowAccept` refused to build).\n */\nexport class OnDeliveryAcceptError extends EscroError {\n readonly refusals: readonly { index: number; reason: OnDeliveryAcceptRefusal }[];\n\n constructor(refusals: readonly { index: number; reason: OnDeliveryAcceptRefusal }[]) {\n const listed = refusals.map((r) => `${String(r.index)}: ${r.reason}`).join(\", \");\n super(`No acceptable on-delivery entry (${listed})`, \"ON_DELIVERY_ACCEPT_REFUSED\");\n this.name = \"OnDeliveryAcceptError\";\n this.refusals = refusals;\n }\n}\n\nexport type OnDeliveryFundRefusal =\n | \"selection_unknown\"\n | \"selection_spent\"\n | \"resource_url\"\n | \"resource_mismatch\"\n | \"spec_fetch\"\n | \"spec_host\"\n | \"spec_hash_mismatch\"\n | \"spec_refused\"\n | \"escrow_mismatch\";\n\n/** `fundFromAccept` or `fetchTaskSpec` refused; `reason` names the check. */\nexport class OnDeliveryFundError extends EscroError {\n readonly reason: OnDeliveryFundRefusal;\n /** Set on `escrow_mismatch` only: the create landed; recover with `Escro.cancelEscrow(escrowPda)`. */\n readonly escrowId?: string;\n readonly escrowPda?: string;\n readonly signature?: string;\n\n constructor(\n reason: OnDeliveryFundRefusal,\n message: string,\n options: { cause?: unknown; escrowId?: string; escrowPda?: string; signature?: string } = {},\n ) {\n super(\n message,\n \"ON_DELIVERY_FUND_REFUSED\",\n undefined,\n \"cause\" in options ? { cause: options.cause } : undefined,\n );\n this.name = \"OnDeliveryFundError\";\n this.reason = reason;\n if (options.escrowId !== undefined) this.escrowId = options.escrowId;\n if (options.escrowPda !== undefined) this.escrowPda = options.escrowPda;\n if (options.signature !== undefined) this.signature = options.signature;\n }\n}\n\n/** The facilitator operation an {@link EscroFacilitatorError} failed in. */\nexport type FacilitatorOperation = \"verify\" | \"settle\" | \"supported\";\n\n/**\n * A facilitator call that failed with no answer: unreachable, timed out, an unrecognised error, or its client not\n * loadable. `indeterminate` is set on every `settle` failure: the facilitator may still have sent the transfer. The\n * message holds no part of the facilitator URL, and the error carries no `cause`.\n */\nexport class EscroFacilitatorError extends EscroError {\n readonly operation: FacilitatorOperation;\n readonly indeterminate: boolean;\n\n constructor(operation: FacilitatorOperation, message: string) {\n super(message, \"FACILITATOR_UNAVAILABLE\");\n this.name = \"EscroFacilitatorError\";\n this.operation = operation;\n this.indeterminate = operation === \"settle\";\n }\n}\n\n/** Why {@link buildExactAccept} refused to build an `exact` entry. */\nexport type ExactAcceptRefusal = \"pay_to\" | \"fee_payer\" | \"amount\" | \"max_timeout\";\n\n/** The worker's `exact` entry would be one a buyer cannot pay or a facilitator cannot settle in time. */\nexport class ExactAcceptError extends EscroError {\n readonly reason: ExactAcceptRefusal;\n\n constructor(reason: ExactAcceptRefusal, message: string) {\n super(message, \"EXACT_ACCEPT_REFUSED\");\n this.name = \"ExactAcceptError\";\n this.reason = reason;\n }\n}\n","// The `escro` extension's `info` (docs/specs/escro-extension.md), validated by the rules this client\n// holds, as escro-extension.schema.json states them. The `schema` a 402 carries is never read: a\n// server can ship a laxer one (escro-extension.md, \"Where it travels\").\nimport { isRecord, type EscroExtensionInfo } from \"@escro/shared\";\n\nimport { OnDeliveryAcceptError } from \"./errors.js\";\n\n/** `value` is an object holding every `required` member and no member outside `allowed`. */\nexport function hasMembers(\n value: unknown,\n allowed: readonly string[],\n required: readonly string[] = allowed,\n): value is Record<string, unknown> {\n return (\n isRecord(value) &&\n Object.keys(value).every((key) => allowed.includes(key)) &&\n required.every((key) => key in value)\n );\n}\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\nconst PREDICATE_NAME = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst RECEIPT_SCHEMA = /^[!-~]{1,128}$/;\n// https:, then printable ASCII without `#` or `?`, not ending in `/`.\nconst VERIFIER_URL = /^https:\\/\\/[!\"$->@-~]*[!\"$-.0->@-~]$/;\nconst SERVER_URL = /^https:\\/\\/[!-~]+$/;\nconst CAIP2 = /^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$/;\nconst INSTRUCTION = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;\nconst ADDRESS = /^[A-Za-z0-9]{1,128}$/;\nconst MCP_SERVER = /^[!-~]{1,256}$/;\nconst MCP_TOOL = /^[A-Za-z0-9_-]{1,64}$/;\nconst MAX_URL_LENGTH = 2048;\n\nconst ACTIONS = [\"fund\", \"claim\", \"submit\", \"poll\", \"release\", \"dispute\", \"cancel\", \"refund\"];\nconst ACTORS = [\"buyer\", \"worker\", \"judge\", \"timekeeper\", \"arbitrator\", \"anyone\"];\n\nconst matches = (value: unknown, pattern: RegExp, maxLength = Infinity): boolean =>\n typeof value === \"string\" && value.length <= maxLength && pattern.test(value);\n\nconst oneOf = (value: unknown, allowed: readonly unknown[]): boolean => allowed.includes(value);\n\nconst isInteger = (value: unknown, minimum: number): boolean =>\n typeof value === \"number\" && Number.isInteger(value) && value >= minimum;\n\nconst optional = (value: unknown, check: (v: unknown) => boolean): boolean =>\n value === undefined || check(value);\n\nfunction validAcceptance(value: unknown): boolean {\n if (!hasMembers(value, [\"name\", \"paramsHash\", \"fixtureHashes\"], [\"name\", \"paramsHash\"])) {\n return false;\n }\n const hashes = value.fixtureHashes;\n return (\n matches(value.name, PREDICATE_NAME, 64) &&\n matches(value.paramsHash, SHA256_HEX) &&\n optional(\n hashes,\n (v) =>\n Array.isArray(v) && v.every((h) => matches(h, SHA256_HEX)) && new Set(v).size === v.length,\n )\n );\n}\n\nfunction validReceipt(value: unknown): boolean {\n return (\n hasMembers(value, [\"schema\", \"verifierUrl\"], [\"schema\"]) &&\n matches(value.schema, RECEIPT_SCHEMA) &&\n optional(value.verifierUrl, (v) => matches(v, VERIFIER_URL, MAX_URL_LENGTH))\n );\n}\n\nfunction validSettlement(value: unknown): boolean {\n return (\n hasMembers(value, [\"reviewWindowSeconds\", \"settlementMode\", \"feePayer\"]) &&\n isInteger(value.reviewWindowSeconds, 1) &&\n oneOf(value.settlementMode, [\"release\", \"refund\"]) &&\n oneOf(value.feePayer, [\"client\", \"worker\"])\n );\n}\n\nconst COMMON = [\"action\", \"actor\", \"channel\", \"notBefore\"];\n\nfunction validNextAction(value: unknown): boolean {\n if (!isRecord(value)) return false;\n const common =\n oneOf(value.action, ACTIONS) &&\n oneOf(value.actor, ACTORS) &&\n optional(value.notBefore, (v) => isInteger(v, 0));\n if (!common) return false;\n switch (value.channel) {\n case \"onchain\":\n return (\n hasMembers(\n value,\n [...COMMON, \"network\", \"instruction\", \"address\", \"args\"],\n [\"action\", \"actor\", \"channel\", \"network\", \"instruction\"],\n ) &&\n matches(value.network, CAIP2) &&\n matches(value.instruction, INSTRUCTION) &&\n optional(value.address, (v) => matches(v, ADDRESS)) &&\n optional(value.args, isRecord)\n );\n case \"server\":\n return (\n hasMembers(\n value,\n [...COMMON, \"method\", \"url\"],\n [\"action\", \"actor\", \"channel\", \"method\", \"url\"],\n ) &&\n oneOf(value.method, [\"GET\", \"POST\"]) &&\n matches(value.url, SERVER_URL, MAX_URL_LENGTH)\n );\n case \"mcp\":\n return (\n hasMembers(\n value,\n [...COMMON, \"server\", \"tool\", \"args\"],\n [\"action\", \"actor\", \"channel\", \"server\", \"tool\"],\n ) &&\n matches(value.server, MCP_SERVER) &&\n matches(value.tool, MCP_TOOL) &&\n optional(value.args, isRecord)\n );\n default:\n return false;\n }\n}\n\n/** `info` holds the extension document's rules. */\nexport function isEscroExtensionInfo(info: unknown): info is EscroExtensionInfo {\n return (\n hasMembers(info, [\"acceptance\", \"receipt\", \"settlement\", \"nextActions\"], []) &&\n optional(info.acceptance, validAcceptance) &&\n optional(info.receipt, validReceipt) &&\n optional(info.settlement, validSettlement) &&\n optional(info.nextActions, (v) => Array.isArray(v) && v.every(validNextAction))\n );\n}\n\n/**\n * The `escro` extension's `info`, validated by the rules this client holds (closed objects; `args`\n * free-form). Throws {@link OnDeliveryAcceptError} with reason `extension_invalid` otherwise.\n */\nexport function parseEscroExtension(info: unknown): EscroExtensionInfo {\n if (!isEscroExtensionInfo(info)) {\n throw new OnDeliveryAcceptError([{ index: -1, reason: \"extension_invalid\" }]);\n }\n return info;\n}\n","// The only signer the `exact` client ever holds. It decodes the one transaction it is asked to sign\n// and checks it against the chosen entry and the caller's own terms before the key runs. It\n// constrains what the official client can get signed; it is not an isolation boundary against a\n// compromised dependency in the same realm.\nimport {\n ComputeBudgetProgram,\n PublicKey,\n VersionedMessage,\n type Keypair,\n type MessageCompiledInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_2022_PROGRAM_ID,\n TOKEN_PROGRAM_ID,\n getAssociatedTokenAddressSync,\n} from \"@solana/spl-token\";\nimport nacl from \"tweetnacl\";\nimport { getUsdcMint, type PaymentRequirements, type SolanaCluster } from \"@escro/shared\";\nimport type {\n Address,\n SignatureBytes,\n SignatureDictionary,\n TransactionPartialSigner,\n} from \"@solana/kit\";\n\nimport { EscroPayError } from \"../errors.js\";\nimport { MEMO_PROGRAM_ID } from \"../solana.js\";\n\nconst SET_COMPUTE_UNIT_LIMIT = { tag: 2, length: 5 };\nconst SET_COMPUTE_UNIT_PRICE = { tag: 3, length: 9 };\n// The cap of the scheme spec pinned for @x402/svm 2.29.0. Conformance, not fund protection: the fee\n// payer is checked not to be the wallet.\nconst MAX_COMPUTE_UNIT_PRICE = 5_000_000n;\n\nconst TRANSFER_CHECKED = { tag: 12, length: 10, accounts: 4 };\nconst USDC_DECIMALS = 6;\n\n// The transaction is [SetComputeUnitLimit, SetComputeUnitPrice, TransferChecked, Memo]; the wallet's\n// one permitted account position is the authority of that transfer.\nconst TRANSFER_INDEX = 2;\nconst TRANSFER_AUTHORITY_POSITION = 3;\n\nfunction refuse(detail: string, why: string, cause?: unknown): never {\n throw new EscroPayError(\"transaction\", `Refusing to sign the x402 transaction: ${why}`, {\n detail,\n ...(cause === undefined ? {} : { cause }),\n });\n}\n\n/** The data as UTF-8 text, byte-exact (a leading BOM is kept), or undefined when it is not UTF-8. */\nfunction utf8Text(data: Uint8Array): string | undefined {\n try {\n return new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(data);\n } catch {\n return undefined;\n }\n}\n\nfunction decode(bytes: Uint8Array): VersionedMessage {\n try {\n return VersionedMessage.deserialize(bytes);\n } catch (cause) {\n return refuse(\"decode\", \"the message does not decode\", cause);\n }\n}\n\n/** Whether the decoded message writes back to exactly `bytes`: parsers disagree on anything else. */\nfunction isCanonical(message: VersionedMessage, bytes: Uint8Array): boolean {\n try {\n return Buffer.from(message.serialize()).equals(bytes);\n } catch {\n return false;\n }\n}\n\nfunction assertComputeBudget(\n ix: MessageCompiledInstruction,\n shape: { tag: number; length: number },\n name: string,\n): void {\n if (ix.data[0] !== shape.tag || ix.data.length !== shape.length) {\n refuse(\"compute_budget\", `the compute-budget instruction is not ${name}`);\n }\n}\n\n/** Checks `bytes` in the documented order and returns the Memo text. */\nfunction checkMessage(\n bytes: Uint8Array,\n entry: PaymentRequirements,\n wallet: PublicKey,\n cluster: SolanaCluster,\n): string {\n const message = decode(bytes);\n if (!isCanonical(message, bytes)) refuse(\"non_canonical\", \"the message is not canonical\");\n if (message.version !== 0) refuse(\"version\", \"the message is not version 0\");\n if (message.header.numRequiredSignatures !== 2) {\n refuse(\"header\", \"the message does not require exactly two signatures\");\n }\n\n const keys = message.staticAccountKeys;\n if (keys[0]?.toBase58() !== entry.extra?.feePayer) {\n refuse(\"fee_payer\", \"the fee payer is not the entry's feePayer\");\n }\n if (keys[1]?.equals(wallet) !== true) {\n refuse(\"wallet_position\", \"the second signer is not the wallet\");\n }\n message.compiledInstructions.forEach((ix, index) => {\n ix.accountKeyIndexes.forEach((keyIndex, position) => {\n const isAuthority = index === TRANSFER_INDEX && position === TRANSFER_AUTHORITY_POSITION;\n if (keys[keyIndex]?.equals(wallet) === true && !isAuthority) {\n refuse(\"wallet_position\", \"the wallet appears other than as the transfer's authority\");\n }\n });\n });\n if (message.addressTableLookups.length !== 0) {\n refuse(\"lookup_table\", \"the message has address table lookups\");\n }\n\n const [limit, price, transfer, memo, ...rest] = message.compiledInstructions;\n const programOf = (ix: MessageCompiledInstruction | undefined): PublicKey | undefined =>\n ix === undefined ? undefined : keys[ix.programIdIndex];\n const transferProgram = programOf(transfer);\n if (\n limit === undefined ||\n price === undefined ||\n transfer === undefined ||\n memo === undefined ||\n rest.length !== 0 ||\n programOf(limit)?.equals(ComputeBudgetProgram.programId) !== true ||\n programOf(price)?.equals(ComputeBudgetProgram.programId) !== true ||\n // Token-2022 passes here for the transfer check below to name it.\n (transferProgram?.equals(TOKEN_PROGRAM_ID) !== true &&\n transferProgram?.equals(TOKEN_2022_PROGRAM_ID) !== true) ||\n programOf(memo)?.toBase58() !== MEMO_PROGRAM_ID\n ) {\n return refuse(\"instruction_list\", \"the instructions are not the exact scheme's four\");\n }\n\n assertComputeBudget(limit, SET_COMPUTE_UNIT_LIMIT, \"SetComputeUnitLimit\");\n assertComputeBudget(price, SET_COMPUTE_UNIT_PRICE, \"SetComputeUnitPrice\");\n if (Buffer.from(price.data).readBigUInt64LE(1) > MAX_COMPUTE_UNIT_PRICE) {\n refuse(\"compute_price\", \"the compute-unit price is over the scheme's cap\");\n }\n\n if (\n !transferProgram.equals(TOKEN_PROGRAM_ID) ||\n transfer.data[0] !== TRANSFER_CHECKED.tag ||\n transfer.data.length !== TRANSFER_CHECKED.length ||\n transfer.accountKeyIndexes.length !== TRANSFER_CHECKED.accounts\n ) {\n refuse(\"transfer_shape\", \"the transfer is not a classic Token TransferChecked\");\n }\n const transferKey = (position: number): PublicKey | undefined => {\n const keyIndex = transfer.accountKeyIndexes[position];\n return keyIndex === undefined ? undefined : keys[keyIndex];\n };\n const mint = new PublicKey(getUsdcMint(cluster));\n if (transferKey(1)?.equals(mint) !== true) refuse(\"mint\", \"the mint is not the cluster's USDC\");\n if (transferKey(0)?.equals(getAssociatedTokenAddressSync(mint, wallet)) !== true) {\n refuse(\"source\", \"the source is not the wallet's token account\");\n }\n const destination = getAssociatedTokenAddressSync(mint, new PublicKey(entry.payTo), true);\n if (transferKey(2)?.equals(destination) !== true) {\n refuse(\"destination\", \"the destination is not payTo's token account\");\n }\n if (transferKey(TRANSFER_AUTHORITY_POSITION)?.equals(wallet) !== true) {\n refuse(\"authority\", \"the transfer's authority is not the wallet\");\n }\n if (Buffer.from(transfer.data).readBigUInt64LE(1) !== BigInt(entry.amount)) {\n refuse(\"amount\", \"the amount is not the entry's\");\n }\n if (transfer.data[9] !== USDC_DECIMALS) refuse(\"decimals\", \"the decimals are not USDC's\");\n\n if (memo.accountKeyIndexes.length !== 0) refuse(\"memo\", \"the Memo carries accounts\");\n const text = utf8Text(memo.data);\n if (text === undefined) return refuse(\"memo\", \"the Memo is not valid UTF-8\");\n const required = entry.extra?.memo;\n const matches = typeof required === \"string\" && Buffer.from(required, \"utf8\").equals(memo.data);\n if (required !== undefined && !matches) refuse(\"memo\", \"the Memo is not the entry's\");\n return text;\n}\n\n/**\n * A signer for one `exact` payment: one call, one transaction. `messageBytes` is copied once and\n * that copy is decoded, checked and signed synchronously. `onSigned` receives the Memo text before\n * the signature is computed, so the rail never credits back a payment whose signature may exist.\n */\nexport function guardedSigner(\n wallet: Keypair,\n requirements: PaymentRequirements,\n cluster: SolanaCluster,\n onSigned?: (memo: string) => void,\n): TransactionPartialSigner {\n const address = wallet.publicKey.toBase58() as Address;\n let called = false;\n const signOnce: (\n transactions: Parameters<TransactionPartialSigner[\"signTransactions\"]>[0],\n ) => readonly SignatureDictionary[] = (transactions) => {\n const again = called;\n called = true;\n const [transaction] = transactions;\n if (again || transaction === undefined || transactions.length !== 1) {\n return refuse(\"batch\", \"the signer signs one transaction, once\");\n }\n const bytes = Uint8Array.from(transaction.messageBytes);\n const memo = checkMessage(bytes, requirements, wallet.publicKey, cluster);\n onSigned?.(memo);\n const signature = nacl.sign.detached(bytes, wallet.secretKey) as SignatureBytes;\n return [Object.freeze({ [address]: signature })];\n };\n return Object.freeze({\n address,\n signTransactions: (transactions) =>\n new Promise<readonly SignatureDictionary[]>((resolve) => {\n resolve(signOnce(transactions));\n }),\n });\n}\n","import {\n Connection,\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport {\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n getAssociatedTokenAddressSync,\n createAssociatedTokenAccountIdempotentInstruction,\n} from \"@solana/spl-token\";\nimport bs58 from \"bs58\";\nimport {\n CURRENT_ACCOUNT_VERSION,\n ESCROW_INSTRUCTIONS,\n decodeCreateEscrowArgs,\n decodeRaiseDisputeArgs,\n decodeSubmitDeliverableArgs,\n escrowInstructionName,\n getProgramId,\n assertProgramIdNotPlaceholder,\n type EscrowErrorCode,\n type EscrowInstructionName,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport {\n decodePlatformConfig,\n deriveEscrowPda,\n derivePlatformConfigPda,\n} from \"@escro/shared/solana\";\nimport { EscroError, attachToError } from \"./errors.js\";\n\nexport function resolveProgramId(cluster: SolanaCluster): PublicKey {\n const id = getProgramId(cluster);\n assertProgramIdNotPlaceholder(id, cluster);\n return new PublicKey(id);\n}\n\nfunction allowedProgramIds(programId: PublicKey): Set<string> {\n return new Set([\n programId.toBase58(),\n TOKEN_PROGRAM_ID.toBase58(),\n ASSOCIATED_TOKEN_PROGRAM_ID.toBase58(),\n ]);\n}\n\nconst MAX_INSTRUCTIONS = 6;\n\n/** The SPL Memo program (the current one; the legacy `Memo1Uhk...` program is not admitted). */\nexport const MEMO_PROGRAM_ID = \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\";\n\n/**\n * SPL Token tags that move funds or change authority. Escro never has the wallet\n * sign one top-level (token movement is a CPI inside the program), so one in a\n * server-built transaction is a wallet drain (L2).\n */\nconst FORBIDDEN_TOKEN_IX_TAGS = new Set<number>([\n 3, // Transfer\n 4, // Approve\n 6, // SetAuthority\n 7, // MintTo\n 8, // Burn\n 9, // CloseAccount\n 12, // TransferChecked\n 13, // ApproveChecked\n 14, // MintToChecked\n 15, // BurnChecked\n]);\n\n/**\n * The mint, treasury and fee rate from the on-chain PlatformConfig. A wrong length,\n * discriminator or version throws rather than returning corrupted values.\n */\nexport async function fetchPlatformConfig(\n connection: Connection,\n cluster: SolanaCluster,\n): Promise<{ mint: PublicKey; treasury: PublicKey; feeBps: number }> {\n const pda = derivePlatformConfigPda(resolveProgramId(cluster));\n const info = await connection.getAccountInfo(pda);\n if (!info) throw new Error(\"PlatformConfig account not found on-chain\");\n const config = decodePlatformConfig(info.data);\n if (config.version !== CURRENT_ACCOUNT_VERSION) {\n throw new Error(\n `PlatformConfig version mismatch: expected ${String(CURRENT_ACCOUNT_VERSION)}, got ${String(config.version)}`,\n );\n }\n return {\n mint: new PublicKey(config.usdcMint),\n treasury: new PublicKey(config.treasury),\n feeBps: config.feeBps,\n };\n}\n\nfunction refuse(reason: string): never {\n throw new EscroError(\n `Refusing to sign a server-built transaction: ${reason}`,\n \"UNEXPECTED_TRANSACTION\",\n );\n}\n\nexport function validateTransaction(tx: Transaction, cluster: SolanaCluster): void {\n validateInstructions(tx.instructions, cluster);\n}\n\nfunction validateInstructions(\n instructions: TransactionInstruction[],\n cluster: SolanaCluster,\n): void {\n const programId = resolveProgramId(cluster);\n const allowed = allowedProgramIds(programId);\n const tokenProgram = TOKEN_PROGRAM_ID.toBase58();\n for (const ix of instructions) {\n const id = ix.programId.toBase58();\n if (!allowed.has(id)) {\n refuse(`Unexpected program in transaction: ${id}. Allowed: ${[...allowed].join(\", \")}`);\n }\n if (id === tokenProgram) {\n const tag = ix.data.length > 0 ? ix.data[0] : undefined;\n if (tag !== undefined && FORBIDDEN_TOKEN_IX_TAGS.has(tag)) {\n throw new EscroError(\n `Refusing to sign a fund-moving SPL Token instruction (tag ${String(tag)}) in a server-built transaction`,\n \"UNEXPECTED_TRANSACTION\",\n );\n }\n }\n }\n assertInstructionCount(instructions);\n}\n\nfunction assertInstructionCount(instructions: TransactionInstruction[]): void {\n if (instructions.length > MAX_INSTRUCTIONS) {\n refuse(\n `Too many instructions (${String(instructions.length)}). Max allowed: ${String(MAX_INSTRUCTIONS)}`,\n );\n }\n}\n\n/** The one escro instruction a transaction must carry before the SDK signs it. */\nexport type ExpectedTransaction =\n | {\n name: \"create_escrow\";\n escrowPda: string;\n taskId: string;\n amount: bigint;\n deadline: bigint;\n specHash: string;\n assignedWorker: string;\n }\n | { name: \"claim_task\" | \"cancel_escrow\"; escrowPda: string }\n | {\n name: \"release_payment\";\n escrowPda: string;\n worker: string;\n treasury: string;\n mint: string;\n /** The decision memo `releaseWithPredicate` computed; the release must end with exactly it. */\n memo?: string;\n }\n | {\n name: \"submit_deliverable\";\n escrowPda: string;\n deliverableHash: string;\n proofUri: string | null;\n }\n | { name: \"raise_dispute\"; escrowPda: string; reason: string };\n\n// The idempotent ATA creates the SDK's own release carries: the worker's and the treasury's, for\n// the PlatformConfig mint, paid by the wallet.\nfunction releaseAtaCreates(\n wallet: PublicKey,\n expected: Extract<ExpectedTransaction, { name: \"release_payment\" }>,\n): TransactionInstruction[] {\n const mint = new PublicKey(expected.mint);\n return [expected.worker, expected.treasury].map((key) => {\n const owner = new PublicKey(key);\n return createAssociatedTokenAccountIdempotentInstruction(\n wallet,\n getAssociatedTokenAddressSync(mint, owner, true),\n owner,\n mint,\n );\n });\n}\n\nfunction sameInstruction(a: TransactionInstruction, b: TransactionInstruction): boolean {\n return (\n a.programId.equals(b.programId) &&\n a.data.equals(b.data) &&\n a.keys.length === b.keys.length &&\n a.keys.every((key, i) => b.keys[i]?.pubkey.equals(key.pubkey) === true)\n );\n}\n\nfunction memoInstruction(memo: string): TransactionInstruction {\n return new TransactionInstruction({\n programId: new PublicKey(MEMO_PROGRAM_ID),\n keys: [],\n data: Buffer.from(memo, \"utf8\"),\n });\n}\n\n/**\n * The instructions before an expected release's decision memo. The whole transaction is held to\n * the instruction cap first; the memo must be the last instruction, under the current Memo\n * program, with no accounts and exactly the expected bytes. Any other Memo instruction stays in\n * the prefix, where the program allowlist refuses it.\n */\nfunction beforeExpectedMemo(tx: Transaction, memo: string): TransactionInstruction[] {\n assertInstructionCount(tx.instructions);\n const last = tx.instructions.at(-1);\n const exact =\n last?.programId.toBase58() === MEMO_PROGRAM_ID &&\n last.keys.length === 0 &&\n last.data.equals(Buffer.from(memo, \"utf8\"));\n if (!exact) refuse(\"the release does not end with exactly the expected decision memo\");\n return tx.instructions.slice(0, -1);\n}\n\n/**\n * Refuses a transaction that is not exactly the escro instruction the caller\n * requested: right instruction, escrow, actor, fee payer and arguments, and\n * nothing else beside it except, on a release, at most one idempotent ATA create\n * each for the worker and the treasury, for the expected mint, paid by the wallet,\n * and, on a release expected with a decision memo, that memo as the last instruction.\n * A compromised or impersonated API could otherwise have the wallet sign a\n * different escrow, a create paying another worker, or text it never chose.\n */\nexport function verifyServerTransaction(\n tx: Transaction,\n cluster: SolanaCluster,\n wallet: PublicKey,\n expected: ExpectedTransaction,\n): void {\n const instructions =\n expected.name === \"release_payment\" && expected.memo !== undefined\n ? beforeExpectedMemo(tx, expected.memo)\n : tx.instructions;\n validateInstructions(instructions, cluster);\n const programId = resolveProgramId(cluster);\n if (!tx.feePayer?.equals(wallet)) refuse(\"the fee payer is not the wallet\");\n\n const escro = instructions.filter((ix) => ix.programId.equals(programId));\n const others = instructions.filter((ix) => !ix.programId.equals(programId));\n const allowed = expected.name === \"release_payment\" ? releaseAtaCreates(wallet, expected) : [];\n for (const ix of others) {\n const match = allowed.findIndex((create) => sameInstruction(create, ix));\n if (match === -1) refuse(`unexpected ${ix.programId.toBase58()} instruction`);\n allowed.splice(match, 1);\n }\n if (escro.length !== 1) refuse(`${String(escro.length)} escro instructions, expected 1`);\n const [ix] = escro;\n if (ix === undefined) refuse(\"no escro instruction\");\n\n const name: EscrowInstructionName | null = escrowInstructionName(ix.data);\n if (name !== expected.name)\n refuse(`${name ?? \"an unknown instruction\"}, expected ${expected.name}`);\n const spec = ESCROW_INSTRUCTIONS[name];\n const actor = ix.keys[spec.signerAccountIndex];\n if (actor === undefined || !actor.pubkey.equals(wallet) || !actor.isSigner) {\n refuse(\"the acting signer is not the wallet\");\n }\n if (ix.keys[spec.escrowAccountIndex]?.pubkey.toBase58() !== expected.escrowPda) {\n refuse(`the escrow is not ${expected.escrowPda}`);\n }\n\n try {\n switch (expected.name) {\n case \"create_escrow\": {\n const args = decodeCreateEscrowArgs(ix.data);\n if (args.taskId !== expected.taskId) refuse(\"the task id differs\");\n if (deriveEscrowPda(programId, wallet, args.taskId).toBase58() !== expected.escrowPda) {\n refuse(\"the escrow is not derived from the wallet and task id\");\n }\n if (args.amount !== expected.amount) refuse(\"the amount differs\");\n if (args.deadline !== expected.deadline) refuse(\"the deadline differs\");\n if (args.specHash !== expected.specHash) refuse(\"the spec hash differs\");\n if (args.assignedWorker !== expected.assignedWorker) refuse(\"the assigned worker differs\");\n break;\n }\n case \"submit_deliverable\": {\n const args = decodeSubmitDeliverableArgs(ix.data);\n if (args.deliverableHash !== expected.deliverableHash)\n refuse(\"the deliverable hash differs\");\n if (args.proofUri !== expected.proofUri) refuse(\"the proof URI differs\");\n break;\n }\n case \"raise_dispute\":\n if (decodeRaiseDisputeArgs(ix.data).reason !== expected.reason)\n refuse(\"the reason differs\");\n break;\n default:\n if (ix.data.length !== ESCROW_INSTRUCTIONS[name].discriminator.length) {\n refuse(`${name} carries unexpected arguments`);\n }\n }\n } catch (err) {\n if (err instanceof EscroError) throw err;\n refuse(`malformed ${name} arguments`);\n }\n}\n\nconst NOT_AN_ERROR = \"The RPC rejected with a value that is not an Error\";\nconst TRANSACTION_ERROR_VARIANT = /^[A-Z][A-Za-z0-9]*$/;\n\n/** The Error a non-Error rejection becomes, keeping the value as its `cause`. */\nfunction notAnError(value: unknown): Error {\n return new Error(NOT_AN_ERROR, { cause: value });\n}\n\nfunction executionFailed(signature: string, transactionError: unknown): EscroError {\n return new EscroError(\n `Transaction ${signature} failed at execution: ${JSON.stringify(transactionError)}`,\n \"TX_FAILED\" satisfies EscrowErrorCode,\n );\n}\n\n/**\n * The JSON of `value` when it has the shape of a web3.js `TransactionError`: a unit-variant name, or a plain\n * object with one variant-named key; null for anything else, a value `JSON.stringify` cannot encode included.\n */\nfunction transactionErrorJson(value: unknown): string | null {\n if (typeof value === \"string\") {\n return TRANSACTION_ERROR_VARIANT.test(value) ? JSON.stringify(value) : null;\n }\n if (typeof value !== \"object\" || value === null) return null;\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return null;\n const keys = Reflect.ownKeys(value);\n const [key] = keys;\n if (keys.length !== 1 || typeof key !== \"string\" || !TRANSACTION_ERROR_VARIANT.test(key)) {\n return null;\n }\n try {\n return JSON.stringify(value);\n } catch {\n // A cycle or a BigInt: no RPC answers that, so it is not a transaction error.\n return null;\n }\n}\n\n/**\n * Settle a confirmation that rejected with a transaction error. web3.js rejects with the error a status check\n * saw at any commitment, so it is final only once a status read sees it at `confirmed` or deeper.\n */\nasync function settleByStatus(\n connection: Connection,\n signature: string,\n rejected: unknown,\n failure: string,\n): Promise<string> {\n const read = await connection\n .getSignatureStatuses([signature], { searchTransactionHistory: true })\n .then(\n ({ value }) => ({ entry: value[0] ?? null }),\n () => null,\n );\n // A failed read says nothing about the transaction: the confirmation's own value is the cause.\n if (read === null) throw notAnError(rejected);\n const { entry } = read;\n const level = entry?.confirmationStatus;\n if (entry !== null && (level === \"confirmed\" || level === \"finalized\")) {\n if (entry.err !== null) throw executionFailed(signature, entry.err);\n return signature;\n }\n throw new Error(\n `Transaction ${signature} failed at execution at processed level, not yet confirmed: ${failure}`,\n { cause: rejected },\n );\n}\n\n/**\n * Decode a base64 unsigned transaction, check it is exactly `expected`, sign it\n * with `wallet`, submit it, and return the signature once confirmed. A transaction\n * that landed but failed at execution, seen at `confirmed` or deeper, throws an {@link EscroError}\n * with code `TX_FAILED`. A failure the RPC's status check reports during confirmation is read once\n * more with `getSignatureStatuses`: `TX_FAILED` when that read sees it at `confirmed` or deeper,\n * success when it sees the transaction succeed there, and an `Error` with no code whose message\n * names the signature and the failure at processed level, the failure as its `cause`, when the read\n * sees it unseen or at processed. When that read itself fails, the rejection is the `Error` with\n * the fixed message that a non-Error value gets, its `cause` the confirmation's value; the read's\n * own error is not surfaced.\n * `onSend` runs immediately before the transaction is handed to the RPC: a failure before it\n * means the transaction was never sent. With `wait` false the signature is returned once the RPC\n * accepts the transaction, unconfirmed. Every rejection from the send onward is an `Error`: an\n * `Error` from the send or the confirmation is rethrown as itself, and any other value becomes an\n * `Error` whose `cause` is that value. It carries the transaction's own signature as an own `signature` property.\n */\nexport async function signAndSend(\n base64Tx: string,\n wallet: Keypair,\n connection: Connection,\n cluster: SolanaCluster,\n expected: ExpectedTransaction,\n onSend?: () => void,\n wait = true,\n): Promise<string> {\n const tx = Transaction.from(Buffer.from(base64Tx, \"base64\"));\n verifyServerTransaction(tx, cluster, wallet.publicKey, expected);\n tx.partialSign(wallet);\n const raw = tx.serialize();\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(\"confirmed\");\n onSend?.();\n try {\n const signature = await connection.sendRawTransaction(raw, {\n skipPreflight: false,\n });\n if (!wait) return signature;\n let value: { err: unknown };\n try {\n ({ value } = await connection.confirmTransaction(\n { signature, blockhash, lastValidBlockHeight },\n \"confirmed\",\n ));\n } catch (err) {\n const failure = err instanceof Error ? null : transactionErrorJson(err);\n if (failure === null) throw err;\n return await settleByStatus(connection, signature, err, failure);\n }\n if (value.err !== null) throw executionFailed(signature, value.err);\n return signature;\n } catch (err) {\n const thrown = err instanceof Error ? err : notAnError(err);\n if (tx.signature !== null) attachToError(thrown, \"signature\", bs58.encode(tx.signature));\n throw thrown;\n }\n}\n\n/** An unsigned `release_payment` the buyer signs; account order is the IDL's `ReleasePayment`. */\nexport async function buildReleasePaymentTx(params: {\n buyer: PublicKey;\n escrowPda: PublicKey;\n worker: PublicKey;\n mint: PublicKey;\n treasury: PublicKey;\n connection: Connection;\n cluster: SolanaCluster;\n /** The decision memo, appended as one SPL Memo instruction after `release_payment`. */\n memo?: string;\n}): Promise<string> {\n const { buyer, escrowPda, worker, mint, treasury, connection, cluster, memo } = params;\n const programId = resolveProgramId(cluster);\n\n const platformConfig = derivePlatformConfigPda(programId);\n const vault = getAssociatedTokenAddressSync(\n mint,\n escrowPda,\n true,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n const workerAta = getAssociatedTokenAddressSync(\n mint,\n worker,\n false,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n // The treasury is a Squads vault, a PDA: an off-curve owner must be allowed.\n const treasuryAta = getAssociatedTokenAddressSync(\n mint,\n treasury,\n true,\n TOKEN_PROGRAM_ID,\n ASSOCIATED_TOKEN_PROGRAM_ID,\n );\n\n const ix = new TransactionInstruction({\n programId: programId,\n keys: [\n { pubkey: buyer, isSigner: true, isWritable: true },\n { pubkey: platformConfig, isSigner: false, isWritable: false },\n { pubkey: mint, isSigner: false, isWritable: false },\n { pubkey: escrowPda, isSigner: false, isWritable: true },\n { pubkey: vault, isSigner: false, isWritable: true },\n { pubkey: workerAta, isSigner: false, isWritable: true },\n { pubkey: treasuryAta, isSigner: false, isWritable: true },\n { pubkey: worker, isSigner: false, isWritable: false },\n { pubkey: treasury, isSigner: false, isWritable: false },\n { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },\n ],\n data: Buffer.from(ESCROW_INSTRUCTIONS.release_payment.discriminator),\n });\n\n const { blockhash } = await connection.getLatestBlockhash(\"confirmed\");\n const tx = new Transaction();\n tx.recentBlockhash = blockhash;\n tx.feePayer = buyer;\n\n tx.add(createAssociatedTokenAccountIdempotentInstruction(buyer, workerAta, worker, mint));\n tx.add(createAssociatedTokenAccountIdempotentInstruction(buyer, treasuryAta, treasury, mint));\n tx.add(ix);\n if (memo !== undefined) tx.add(memoInstruction(memo));\n return tx.serialize({ requireAllSignatures: false }).toString(\"base64\");\n}\n","// The `exact` scheme over the official client. @x402/svm 2.29.0 is reached only\n// through the one lazy import below, so a process that never pays `exact` never executes it. The\n// transaction layout the signer holds it to is the scheme spec at commit\n// e4a086819f419e9395acbbdc1679fe6627029ff7 of x402-foundation/x402\n// (specs/schemes/exact/scheme_exact_svm.md), the release commit of 2.29.0, not main.\nimport type { Keypair, PublicKey } from \"@solana/web3.js\";\nimport {\n getUsdcMint,\n type PaymentPayload,\n type PaymentRequirements,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\nimport type {\n PaymentPayload as CorePaymentPayload,\n PaymentRequirements as CorePaymentRequirements,\n} from \"@x402/core/types\";\n\nimport { EscroPayError, EscroRailNotEnabledError } from \"../errors.js\";\nimport { guardedSigner } from \"./signer.js\";\n\n// The official client fixes the payment's compute budget at 20000 units and the Memo program's cost\n// depends on the character, so no byte count alone bounds what lands: one emoji does not fit. 32 is\n// the length of the client's own memo-less nonce and fits the costliest printable content measured.\nconst MAX_MEMO_BYTES = 32;\nconst PRINTABLE_ASCII = /^[\\x20-\\x7e]+$/;\n\n// Upstream drift in the wire types this module adapts is a red typecheck here, not a runtime\n// surprise. Upstream types x402Version as `number` and a resource without the shared type's index\n// signature; those two fields are the SDK's own to set.\ntype Assignable<From extends To, To> = From;\nexport type ExactWireTypes = [\n Assignable<CorePaymentRequirements, PaymentRequirements>,\n Assignable<\n Pick<CorePaymentPayload, \"accepted\" | \"payload\">,\n Pick<PaymentPayload, \"accepted\" | \"payload\">\n >,\n];\n\nfunction refuse(detail: string, message: string): never {\n throw new EscroPayError(\"requirements\", message, { detail });\n}\n\nfunction isMemoAllowed(memo: unknown): boolean {\n return typeof memo === \"string\" && memo.length <= MAX_MEMO_BYTES && PRINTABLE_ASCII.test(memo);\n}\n\nfunction isVersionListAllowed(versions: unknown): boolean {\n return (\n Array.isArray(versions) && versions.includes(0) && versions.every((v) => v === 0 || v === 1)\n );\n}\n\n/**\n * Refuses an `exact` entry the bot will not pay, before the cap is touched and before the package\n * is loaded. The network, `payTo` and amount are already bound to the caller's own terms.\n */\nexport function checkExactRequirements(\n entry: PaymentRequirements,\n wallet: PublicKey,\n cluster: SolanaCluster,\n): void {\n if (entry.asset !== getUsdcMint(cluster)) {\n refuse(\"mint\", \"The entry's asset is not the cluster's USDC\");\n }\n const extra = entry.extra ?? {};\n const { feePayer } = extra;\n if (typeof feePayer !== \"string\" || !isCanonicalPubkey(feePayer)) {\n refuse(\"fee_payer\", \"The entry's extra.feePayer is not a public key\");\n }\n if (feePayer === wallet.toBase58()) {\n refuse(\"fee_payer\", \"The entry names the bot's own key as extra.feePayer\");\n }\n if (\"splits\" in extra && !(Array.isArray(extra.splits) && extra.splits.length === 0)) {\n refuse(\"splits\", \"The entry's extra.splits would pay a third party\");\n }\n if (extra.ataCreationRequired === true) {\n refuse(\"ata_creation\", \"The entry would have the bot fund a token account\");\n }\n if (\"memo\" in extra && !isMemoAllowed(extra.memo)) {\n refuse(\n \"memo\",\n `The entry's extra.memo must be 1 to ${String(MAX_MEMO_BYTES)} bytes of printable ASCII`,\n );\n }\n if (\"transactionVersions\" in extra && !isVersionListAllowed(extra.transactionVersions)) {\n refuse(\"transaction_version\", \"The entry's extra.transactionVersions does not admit version 0\");\n }\n if (!Number.isSafeInteger(entry.maxTimeoutSeconds) || entry.maxTimeoutSeconds <= 0) {\n refuse(\"max_timeout\", \"The entry's maxTimeoutSeconds is not a positive whole number\");\n }\n}\n\n/**\n * Builds and signs the payment for a checked entry. A scheme instance is built per payment, under a\n * signer good for that payment only, against the client's own RPC URL (the scheme otherwise uses a\n * public one). A failed load of the package rejects {@link EscroRailNotEnabledError}; a scheme error\n * rejects {@link EscroPayError} `transaction`/`build`; the signer's own refusals reach the caller\n * unwrapped.\n */\nexport async function exactPayload(\n entry: PaymentRequirements,\n deps: {\n wallet: Keypair;\n cluster: SolanaCluster;\n rpcUrl: string;\n onSigned: (memo: string) => void;\n },\n): Promise<{ transaction: string }> {\n let client: typeof import(\"@x402/svm/exact/client\");\n try {\n client = await import(\"@x402/svm/exact/client\");\n } catch (cause) {\n throw new EscroRailNotEnabledError(\"x402\", { cause });\n }\n const buildRefusal = (cause: unknown): EscroPayError =>\n new EscroPayError(\"transaction\", \"The x402 scheme client could not build the payment\", {\n detail: \"build\",\n cause,\n });\n let transaction: unknown;\n try {\n const signer = guardedSigner(deps.wallet, entry, deps.cluster, deps.onSigned);\n const scheme = new client.ExactSvmScheme(signer, { rpcUrl: deps.rpcUrl });\n // checkExactRequirements has established `extra`.\n const { payload } = await scheme.createPaymentPayload(2, entry as CorePaymentRequirements);\n transaction = payload.transaction;\n } catch (err) {\n if (err instanceof EscroPayError) throw err;\n throw buildRefusal(err);\n }\n if (typeof transaction !== \"string\") {\n throw buildRefusal(new Error(\"the scheme client returned no transaction\"));\n }\n return { transaction };\n}\n","// Funding a selected `on-delivery` entry through the SDK's own `createEscrow`\n// (docs/specs/scheme_on_delivery_svm.md, \"Job specification\", \"Job creation\", \"Payment payload\").\nimport { PublicKey, type Keypair } from \"@solana/web3.js\";\nimport {\n computeTaskSpecHash,\n isRecord,\n type OnDeliveryPaymentPayload,\n type TaskSpec,\n} from \"@escro/shared\";\nimport { deriveEscrowPda } from \"@escro/shared/solana\";\n\nimport type { Escro } from \"../client.js\";\nimport { EscroError } from \"../errors.js\";\nimport { spendSelection, type EscrowAcceptSelection } from \"./accept.js\";\nimport { isAbsoluteHttpUrl, isSignedAt, signEscrowPayload } from \"./buyer-signature.js\";\nimport { OnDeliveryFundError } from \"./errors.js\";\nimport {\n callResolver,\n isBadPortUrl,\n judge,\n pinnedRequest,\n untilAborted,\n type HostResolver,\n} from \"./pinned-request.js\";\n\nconst SPEC_FETCH_TIMEOUT_MS = 10_000;\nconst SPEC_MAX_BYTES = 256 * 1024;\nconst MAX_TASK_ID_BYTES = 32;\n\n/**\n * A job specification document: a non-null, non-array object. The API's TaskSpec schema validates\n * its members when `createEscrow` sends it.\n */\nfunction isSpecDocument(value: unknown): value is TaskSpec {\n return isRecord(value);\n}\n\nconst specFetchError = (message: string, cause?: unknown): OnDeliveryFundError =>\n new OnDeliveryFundError(\"spec_fetch\", message, cause === undefined ? {} : { cause });\n\n/** The response body's bytes, refusing past `SPEC_MAX_BYTES` without reading further. */\nasync function boundedBody(response: Response): Promise<Uint8Array> {\n const chunks: Uint8Array[] = [];\n let total = 0;\n if (response.body !== null) {\n const reader = response.body.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > SPEC_MAX_BYTES) {\n await reader.cancel();\n throw specFetchError(`The job specification is over ${String(SPEC_MAX_BYTES)} bytes`);\n }\n chunks.push(value);\n }\n }\n const bytes = new Uint8Array(total);\n let at = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, at);\n at += chunk.byteLength;\n }\n return bytes;\n}\n\n/** The spec host's address rule and the resolutions it reads. */\ninterface SpecPinning {\n admit: (address: string) => boolean;\n resolve: HostResolver;\n}\n\n/**\n * The spec GET through the pin: the host resolved once (within the fetch's deadline), every answer put to the rule,\n * the connection made only to the admitted answers.\n */\nasync function pinnedSpecGet(\n specUri: string,\n pinning: SpecPinning,\n signal: AbortSignal,\n): Promise<Response> {\n let answers: Awaited<ReturnType<HostResolver>>;\n try {\n answers = await untilAborted(pinning.resolve(new URL(specUri).hostname), signal);\n } catch (cause) {\n throw specFetchError(\"The job specification's host did not resolve\", cause);\n }\n const judged = judge(answers, pinning.admit);\n if (\"refused\" in judged) {\n if (judged.refused === \"unresolved\") {\n throw specFetchError(\"The job specification's host did not resolve\");\n }\n throw new OnDeliveryFundError(\n \"spec_host\",\n \"The job specification's host answered an address the address rule refuses\",\n );\n }\n return pinnedRequest(\n specUri,\n { method: \"GET\", headers: new Headers({ accept: \"application/json\" }), signal },\n judged.admitted,\n );\n}\n\n/**\n * The job specification at an `https:` `specUri`, fetched with no SDK header (only `Accept`), no\n * redirect, a total deadline of `timeoutMs` (default 10 000) and at most 256 KiB of body. Throws\n * {@link OnDeliveryFundError} `spec_fetch` on any other URI, a network failure, a non-2xx status,\n * an oversized, non-UTF-8 or non-JSON body, or a document that is not a JSON object; a URI carrying a\n * username or password, or naming a port `fetch` blocks, is refused before any lookup or connection. With\n * `admitAddress`, the host is resolved once within the deadline, every answer is put to it, and the\n * request connects only to the answers it admitted (exactly `true`); a refused answer throws\n * `spec_host`, an unresolved host `spec_fetch`.\n */\nexport function fetchTaskSpec(\n specUri: string,\n options: { timeoutMs?: number; admitAddress?: (address: string) => boolean } = {},\n): Promise<Record<string, unknown>> {\n const { admitAddress } = options;\n return readTaskSpec(\n specUri,\n options.timeoutMs,\n admitAddress === undefined ? undefined : { admit: admitAddress, resolve: callResolver() },\n );\n}\n\nasync function readTaskSpec(\n specUri: string,\n timeoutMs: number | undefined,\n pinning: SpecPinning | undefined,\n): Promise<Record<string, unknown>> {\n let parsed: URL;\n try {\n parsed = new URL(specUri);\n } catch (cause) {\n throw specFetchError(\"The job specification URI is not a URL\", cause);\n }\n if (parsed.protocol !== \"https:\") {\n throw specFetchError(\"The default job specification fetch reads https: URIs only\");\n }\n // node:https would send these as Authorization: Basic; fetch refuses them.\n if (parsed.username !== \"\" || parsed.password !== \"\") {\n throw specFetchError(\"The job specification URI carries a username or password\");\n }\n if (isBadPortUrl(parsed)) {\n throw specFetchError(\"The job specification URI names a port fetch blocks\");\n }\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(new Error(\"The job specification fetch timed out\"));\n }, timeoutMs ?? SPEC_FETCH_TIMEOUT_MS);\n let document: unknown;\n try {\n const response =\n pinning === undefined\n ? await fetch(specUri, {\n headers: { accept: \"application/json\" },\n redirect: \"error\",\n signal: controller.signal,\n })\n : await pinnedSpecGet(specUri, pinning, controller.signal);\n if (!response.ok) {\n await response.body?.cancel();\n throw specFetchError(`The job specification answered HTTP ${String(response.status)}`);\n }\n const text = new TextDecoder(\"utf-8\", { fatal: true }).decode(await boundedBody(response));\n document = JSON.parse(text);\n } catch (cause) {\n if (cause instanceof OnDeliveryFundError) throw cause;\n throw specFetchError(\"The job specification could not be fetched as JSON\", cause);\n } finally {\n clearTimeout(timer);\n }\n if (!isRecord(document)) throw specFetchError(\"The job specification is not a JSON object\");\n return document;\n}\n\nexport interface FundFromAcceptDeps {\n escro: Pick<Escro, \"createEscrow\">;\n wallet: Keypair;\n /** The absolute URL the paid request goes to: the 402's `resource.url`. */\n resourceUrl: string;\n /** Fetches `extra.specUri`; the only way to read an `ipfs:` URI. Default {@link fetchTaskSpec}. */\n fetchSpec?: (specUri: string) => Promise<unknown>;\n /**\n * Decides each address the default spec fetch may connect to (see {@link fetchTaskSpec}); a caller's\n * `fetchSpec` is its own transport and does not read it.\n */\n admitAddress?: (address: string) => boolean;\n /** The buyer's veto over the hash-checked specification, before `createEscrow`; absent admits. */\n admitSpec?: (spec: TaskSpec) => boolean;\n /** Unix milliseconds. */\n now?: () => number;\n}\n\nexport interface FundFromAcceptResult {\n payment: OnDeliveryPaymentPayload;\n taskSpec: TaskSpec;\n}\n\nasync function specDocument(\n specUri: string,\n fetchSpec: FundFromAcceptDeps[\"fetchSpec\"],\n pinning: SpecPinning | undefined,\n): Promise<TaskSpec> {\n let document: unknown;\n if (fetchSpec === undefined) {\n document = await readTaskSpec(specUri, undefined, pinning);\n } else {\n try {\n document = await fetchSpec(specUri);\n } catch (cause) {\n throw specFetchError(\"fetchSpec failed\", cause);\n }\n }\n if (!isSpecDocument(document)) throw specFetchError(\"The job specification is not a JSON object\");\n return document;\n}\n\n/** The escrow PDA of `buyer` and `taskId` under `program`; undefined for a task id over 32 bytes. */\nfunction escrowPdaOf(program: string, buyer: PublicKey, taskId: string): string | undefined {\n if (new TextEncoder().encode(taskId).length > MAX_TASK_ID_BYTES) return undefined;\n return deriveEscrowPda(new PublicKey(program), buyer, taskId).toBase58();\n}\n\n/**\n * Funds a selection {@link parseEscrowAccept} returned, once: fetches the job specification, checks\n * its hash before it is used or sent, creates the escrow through `deps.escro.createEscrow` with\n * `payTo` as the assigned worker, and returns the `PAYMENT-SIGNATURE` payload signed by\n * `deps.wallet` over `deps.resourceUrl`, with the hash-checked specification.\n *\n * A selection is known only to the copy of the SDK that parsed it. An `escro` built with another\n * wallet, or for another cluster, is caught after the create lands, as `escrow_mismatch`; that\n * error carries `escrowId`, `escrowPda` and `signature`, and `cancelEscrow` is the recovery. An\n * error from `createEscrow` propagates unchanged.\n */\nexport function fundFromAccept(\n selection: EscrowAcceptSelection,\n deps: FundFromAcceptDeps,\n): Promise<FundFromAcceptResult> {\n return fundSelection(selection, deps, callResolver());\n}\n\n/** {@link fundFromAccept} reading the spec host through `resolve`, the resolutions of the pay() call it belongs to. */\nexport async function fundSelection(\n selection: EscrowAcceptSelection,\n deps: FundFromAcceptDeps,\n resolve: HostResolver,\n): Promise<FundFromAcceptResult> {\n // Synchronous up to the first await, so two calls in flight cannot both find it fresh.\n const state = spendSelection(selection);\n if (state === undefined) {\n throw new OnDeliveryFundError(\n \"selection_unknown\",\n \"parseEscrowAccept did not return this selection\",\n );\n }\n if (state === \"spent\") {\n throw new OnDeliveryFundError(\"selection_spent\", \"This selection has already been funded\");\n }\n const { entry, resource } = selection;\n if (!isAbsoluteHttpUrl(deps.resourceUrl)) {\n throw new OnDeliveryFundError(\n \"resource_url\",\n \"resourceUrl must be an absolute http: or https: URL\",\n );\n }\n if (deps.resourceUrl !== resource.url) {\n throw new OnDeliveryFundError(\"resource_mismatch\", \"resourceUrl is not the 402's resource.url\");\n }\n const now = (): number => deps.now?.() ?? Date.now();\n if (!isSignedAt(now())) {\n throw new EscroError(\n \"now() must return non-negative safe-integer Unix milliseconds\",\n \"VALIDATION_ERROR\",\n );\n }\n const { admitAddress } = deps;\n const taskSpec = await specDocument(\n entry.extra.specUri,\n deps.fetchSpec,\n admitAddress === undefined ? undefined : { admit: admitAddress, resolve },\n );\n if (computeTaskSpecHash(taskSpec) !== entry.extra.specHash) {\n throw new OnDeliveryFundError(\n \"spec_hash_mismatch\",\n \"The job specification does not hash to the entry's specHash\",\n );\n }\n if (deps.admitSpec !== undefined && !deps.admitSpec(taskSpec)) {\n throw new OnDeliveryFundError(\"spec_refused\", \"admitSpec refused the job specification\");\n }\n const created = await deps.escro.createEscrow({\n taskSpec,\n amountUsdc: Number(entry.amount),\n deadlineUnix: entry.extra.deadline,\n assignedWorker: entry.payTo,\n });\n const { escrowId, escrowPda, signature } = created;\n if (escrowPdaOf(entry.extra.program, deps.wallet.publicKey, escrowId) !== escrowPda) {\n throw new OnDeliveryFundError(\n \"escrow_mismatch\",\n `The created escrow ${escrowPda} is not this wallet's escrow under the entry's program; recover the deposit with cancelEscrow`,\n { escrowId, escrowPda, signature },\n );\n }\n const payload = signEscrowPayload(\n {\n escrow: escrowPda,\n buyer: deps.wallet.publicKey.toBase58(),\n taskId: escrowId,\n createSignature: signature,\n },\n { wallet: deps.wallet, resourceUrl: deps.resourceUrl, now },\n );\n const payment: OnDeliveryPaymentPayload = {\n x402Version: 2,\n resource,\n accepted: entry,\n payload,\n ...(selection.extensions === undefined ? {} : { extensions: selection.extensions }),\n };\n return { payment, taskSpec };\n}\n","// The buyer's presentation signature (docs/specs/scheme_on_delivery_svm.md, \"Buyer message\"): the\n// only message the buyer's key signs under x402/, and its only signing site.\nimport bs58 from \"bs58\";\nimport nacl from \"tweetnacl\";\nimport type { Keypair } from \"@solana/web3.js\";\nimport { buildSignedMessage, type OnDeliveryPayloadFields } from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { EscroError } from \"../errors.js\";\n\n/** The buyer message's method place: a value no API route accepts. */\nexport const BUYER_MESSAGE_METHOD = \"ON-DELIVERY\" as const;\n\n/** An absolute http: or https: URL: a path alone could make the message an API request's. */\nexport function isAbsoluteHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value);\n return protocol === \"https:\" || protocol === \"http:\";\n } catch {\n return false;\n }\n}\n\n/** A Unix-millisecond timestamp the message can carry: a non-negative safe integer. */\nexport function isSignedAt(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\n/**\n * `escro:<signedAt>:ON-DELIVERY:<resourceUrl>:<escrow>`: the API's request message shape with a\n * method no API route accepts and an absolute URL in the path place, so it never verifies as an API\n * request signature. Throws on a `resourceUrl` that is not an absolute http(s) URL, an `escrow` that\n * is not a canonical base58 key, or a `signedAt` that is not a non-negative safe integer.\n */\nexport function buyerMessage(signedAt: number, resourceUrl: string, escrow: string): string {\n if (!isAbsoluteHttpUrl(resourceUrl)) {\n throw new EscroError(\n \"The resource URL of a buyer message must be an absolute http: or https: URL\",\n \"VALIDATION_ERROR\",\n );\n }\n if (!isCanonicalPubkey(escrow)) {\n throw new EscroError(\n \"The escrow of a buyer message must be a canonical base58 public key\",\n \"VALIDATION_ERROR\",\n );\n }\n if (!isSignedAt(signedAt)) {\n throw new EscroError(\n \"signedAt must be a non-negative safe integer of Unix milliseconds\",\n \"VALIDATION_ERROR\",\n );\n }\n return buildSignedMessage(signedAt, BUYER_MESSAGE_METHOD, resourceUrl, escrow);\n}\n\n/**\n * The payload fields signed by `wallet` over the buyer message for `resourceUrl`, `signedAt` being\n * `now()`. A poll re-signs with the poll URL and a fresh `now()`.\n */\nexport function signEscrowPayload(\n fields: Pick<OnDeliveryPayloadFields, \"escrow\" | \"buyer\" | \"taskId\" | \"createSignature\">,\n options: { wallet: Keypair; resourceUrl: string; now?: () => number },\n): OnDeliveryPayloadFields {\n const signedAt = options.now?.() ?? Date.now();\n const message = buyerMessage(signedAt, options.resourceUrl, fields.escrow);\n const signature = nacl.sign.detached(new TextEncoder().encode(message), options.wallet.secretKey);\n return {\n escrow: fields.escrow,\n buyer: fields.buyer,\n taskId: fields.taskId,\n createSignature: fields.createSignature,\n signedAt,\n buyerSignature: bs58.encode(signature),\n };\n}\n","// pay()'s transport when its caller gives an address rule (PayParams.admitAddress). Each host is resolved once per\n// call, every answer is put to the rule, and the request goes over node:http or node:https with a `lookup` that answers\n// only the admitted addresses from memory, so the address judged is the address connected to. global fetch takes no\n// lookup, which is why this is not fetch. TLS keeps Node's default checks against the URL's name: nothing here takes a\n// CA, a verification switch or an agent from a caller.\nimport type { LookupAddress } from \"node:dns\";\nimport { lookup } from \"node:dns/promises\";\nimport http from \"node:http\";\nimport https from \"node:https\";\nimport { isIP } from \"node:net\";\nimport { Readable } from \"node:stream\";\n\n/** A frozen view whose set lives in this closure, so the table is not module-level state any importer could change. */\nfunction readonlySetOf(values: readonly number[]): ReadonlySet<number> {\n const set = new Set(values);\n const view: ReadonlySet<number> = Object.freeze({\n get size(): number {\n return set.size;\n },\n has: (value: number): boolean => set.has(value),\n forEach: (\n callback: (value: number, key: number, of: ReadonlySet<number>) => void,\n thisArg?: unknown,\n ): void => {\n set.forEach((value) => {\n callback.call(thisArg, value, value, view);\n });\n },\n entries: () => set.entries(),\n keys: () => set.keys(),\n values: () => set.values(),\n [Symbol.iterator]: () => set.values(),\n });\n return view;\n}\n\n/**\n * The Fetch standard's bad ports (§ \"should be blocked due to a bad port\", whatwg/fetch `fetch.bs` at\n * e9460d1b22ead1c6a72eeac37fb2ec0dc01aeb1d): `fetch` refuses them and the pinned transport would not, so pay() and the\n * job-specification read refuse them before either. Port 0 is the standard's, though Node's `fetch` lacks it.\n */\nexport const FETCH_BAD_PORTS: ReadonlySet<number> = readonlySetOf([\n 0, 1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79, 87, 95, 101, 102,\n 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137, 139, 143, 161, 179, 389, 427, 465,\n 512, 513, 514, 515, 526, 530, 531, 532, 540, 548, 554, 556, 563, 587, 601, 636, 989, 990, 993,\n 995, 1719, 1720, 1723, 2049, 3659, 4045, 4190, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668,\n 6669, 6679, 6697, 10080,\n]);\n\n/** An http: or https: URL whose port (the scheme's default when the URL names none) `fetch` blocks. */\nexport function isBadPortUrl(url: URL): boolean {\n const defaultPort = url.protocol === \"http:\" ? 80 : url.protocol === \"https:\" ? 443 : undefined;\n if (defaultPort === undefined) return false;\n return FETCH_BAD_PORTS.has(url.port === \"\" ? defaultPort : Number(url.port));\n}\n\n/** One call's resolutions: a host is looked up at most once, and every request of the call reads that answer. */\nexport type HostResolver = (hostname: string) => Promise<readonly LookupAddress[]>;\n\n/** A URL's hostname as the rule sees it: an IPv6 literal without its brackets. */\nfunction unbracketed(hostname: string): string {\n return hostname.startsWith(\"[\") && hostname.endsWith(\"]\") ? hostname.slice(1, -1) : hostname;\n}\n\n/** A literal is its own answer (Node calls no lookup for one, so it is judged here); a name is looked up. */\nasync function resolveHost(hostname: string): Promise<readonly LookupAddress[]> {\n const host = unbracketed(hostname);\n const family = isIP(host);\n if (family !== 0) return [{ address: host, family }];\n return lookup(host, { all: true });\n}\n\nexport function callResolver(): HostResolver {\n const answers = new Map<string, Promise<readonly LookupAddress[]>>();\n return (hostname) => {\n const known = answers.get(hostname);\n if (known !== undefined) return known;\n const answer = resolveHost(hostname);\n // A caller past its deadline stops listening; the lookup's later rejection must not go unhandled.\n answer.catch(() => undefined);\n answers.set(hostname, answer);\n return answer;\n };\n}\n\n/** `promise`, or the abort reason once `signal` aborts first. */\nexport function untilAborted<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n const reason = (): Error =>\n signal.reason instanceof Error ? signal.reason : new Error(\"The request was aborted\");\n if (signal.aborted) return Promise.reject(reason());\n return new Promise<T>((resolve, reject) => {\n const onAbort = (): void => {\n reject(reason());\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n promise.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n },\n (err: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\nexport type Judgement =\n | { admitted: readonly LookupAddress[] }\n | { refused: \"address\" | \"unresolved\" };\n\n/**\n * Every answer put to `admit`: an address is admitted only when `admit` returns exactly true, a rule that throws\n * refuses, and one refused answer refuses the host, since any answer could be connected to. No answer is unresolved.\n */\nexport function judge(\n answers: readonly LookupAddress[],\n admit: (address: string) => unknown,\n): Judgement {\n if (answers.length === 0) return { refused: \"unresolved\" };\n const admits = (address: string): boolean => {\n try {\n return admit(address) === true;\n } catch {\n return false;\n }\n };\n return answers.every(({ address }) => admits(address))\n ? { admitted: answers }\n : { refused: \"address\" };\n}\n\ntype LookupFunction = NonNullable<http.RequestOptions[\"lookup\"]>;\n\n/** Answers Node's socket lookup from the judged list, in the form it is asked; it never resolves. */\nfunction pinnedLookup(pinned: readonly LookupAddress[]): LookupFunction {\n return (_hostname, options, callback) => {\n const { family } = options;\n const wanted =\n family === 4 || family === \"IPv4\" ? 4 : family === 6 || family === \"IPv6\" ? 6 : 0;\n const answers =\n wanted === 0 ? [...pinned] : pinned.filter((answer) => answer.family === wanted);\n const [first] = answers;\n if (first === undefined) {\n callback(\n Object.assign(new Error(\"No admitted address of the family asked\"), { code: \"ENOTFOUND\" }),\n \"\",\n );\n return;\n }\n if (options.all === true) callback(null, answers);\n else callback(null, first.address, first.family);\n };\n}\n\nconst NULL_BODY_STATUSES: readonly number[] = [204, 205, 304];\n\nexport interface PinnedInit {\n method: string;\n headers: Headers;\n body?: string | undefined;\n /** Bounds the connect and the headers, and once the response is out, its body. */\n signal: AbortSignal;\n}\n\n/** The response at its headers, body unread; cancelling the body destroys the socket. `url` is the requested URL. */\nfunction responseOf(message: http.IncomingMessage, url: string, method: string): Response {\n const headers = new Headers();\n const raw = message.rawHeaders;\n for (let i = 0; i + 1 < raw.length; i += 2) {\n const name = raw[i];\n const value = raw[i + 1];\n if (name !== undefined && value !== undefined) headers.append(name, value);\n }\n const status = message.statusCode ?? 0;\n const nullBody = method === \"HEAD\" || NULL_BODY_STATUSES.includes(status);\n if (nullBody) {\n // Nothing reads a null body, so a socket reset after the headers must not surface as an uncaught error.\n message.on(\"error\", () => undefined);\n message.resume();\n }\n const body = nullBody ? null : (Readable.toWeb(message) as ReadableStream<Uint8Array>);\n const response = new Response(body, { status, statusText: message.statusMessage ?? \"\", headers });\n Object.defineProperty(response, \"url\", { value: url });\n return response;\n}\n\n/**\n * One request to `url` connecting only to `pinned`, framed as fetch frames it (`accept: *\\/*` and `user-agent: node`\n * where the caller set none, a string body's length and default content type) with no encoding of its own, following\n * no redirect. The method is sent upper-cased whatever its case: node:http upper-cases every method, where fetch\n * keeps a method other than DELETE, GET, HEAD, OPTIONS, POST and PUT as given. Rejects with Node's own error (a TLS failure's code intact), or a status a\n * Response cannot hold.\n */\nexport function pinnedRequest(\n url: string,\n init: PinnedInit,\n pinned: readonly LookupAddress[],\n): Promise<Response> {\n const target = new URL(url);\n const method = init.method.toUpperCase();\n const headers: Record<string, string> = {};\n init.headers.forEach((value, name) => {\n headers[name] = value;\n });\n if (!init.headers.has(\"accept\")) headers.accept = \"*/*\";\n if (!init.headers.has(\"user-agent\")) headers[\"user-agent\"] = \"node\";\n let payload: Buffer | undefined;\n if (init.body !== undefined) {\n payload = Buffer.from(init.body, \"utf8\");\n if (!init.headers.has(\"content-type\")) headers[\"content-type\"] = \"text/plain;charset=UTF-8\";\n headers[\"content-length\"] = String(payload.byteLength);\n } else if (method === \"POST\" || method === \"PUT\") {\n headers[\"content-length\"] = \"0\";\n }\n const secure = target.protocol === \"https:\";\n const name = unbracketed(target.hostname);\n const options: https.RequestOptions = {\n method,\n headers,\n // A fresh agent per request: no socket from a global pool, none reused by another call.\n agent: false,\n lookup: pinnedLookup(pinned),\n signal: init.signal,\n // The certificate is checked against the URL's name, never the pinned address. An IP literal sends no SNI, and an\n // empty servername keeps a caller's Host header from naming the certificate in its place.\n ...(secure ? { servername: isIP(name) === 0 ? name : \"\" } : {}),\n };\n return new Promise<Response>((resolve, reject) => {\n const onResponse = (message: http.IncomingMessage): void => {\n try {\n resolve(responseOf(message, url, method));\n } catch (err) {\n message.destroy();\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n };\n const request = secure\n ? https.request(target, options, onResponse)\n : http.request(target, options, onResponse);\n request.on(\"error\", reject);\n request.end(payload);\n });\n}\n","// The x402 V2 HTTP transport headers (x402-foundation/x402 commit\n// 513dd66d2b3eb2388065f9923d81aa496e626082, specs/transports-v2/http.md): standard RFC 4648 base64,\n// with padding, of the UTF-8 bytes of the JSON value. One codec serves every rail.\nimport {\n isRecord,\n type PaymentPayload,\n type PaymentRequired,\n type SettlementResponse,\n} from \"@escro/shared\";\n\nimport { X402CodecError } from \"./errors.js\";\n\n/** The three x402 V2 HTTP header names. */\nexport const X402_HEADERS = {\n paymentRequired: \"PAYMENT-REQUIRED\",\n paymentSignature: \"PAYMENT-SIGNATURE\",\n paymentResponse: \"PAYMENT-RESPONSE\",\n} as const;\n\nconst STANDARD_BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\nfunction encode(value: unknown): string {\n return Buffer.from(JSON.stringify(value), \"utf8\").toString(\"base64\");\n}\n\n/** The JSON object a header carries; throws X402CodecError on anything else. */\nfunction decodeObject(header: string, what: string): Record<string, unknown> {\n if (!STANDARD_BASE64.test(header)) {\n throw new X402CodecError(`The ${what} header is not padded standard base64`);\n }\n let text: string;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: true }).decode(Buffer.from(header, \"base64\"));\n } catch (cause) {\n throw new X402CodecError(`The ${what} header is not UTF-8`, { cause });\n }\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch (cause) {\n throw new X402CodecError(`The ${what} header is not JSON`, { cause });\n }\n if (!isRecord(value)) throw new X402CodecError(`The ${what} header is not a JSON object`);\n return value;\n}\n\nfunction requireVersion2(value: Record<string, unknown>, what: string): void {\n if (value.x402Version !== 2) throw new X402CodecError(`The ${what} header is not x402Version 2`);\n}\n\n/** A 402's `PAYMENT-REQUIRED` header value. */\nexport function encodePaymentRequired(value: PaymentRequired): string {\n return encode(value);\n}\n\n/**\n * A `PAYMENT-REQUIRED` header's value, checked for version 2, `resource.url` and each entry's\n * `scheme` and `network`; throws {@link X402CodecError} otherwise.\n */\nexport function decodePaymentRequired(header: string): PaymentRequired {\n const what = X402_HEADERS.paymentRequired;\n const value = decodeObject(header, what);\n requireVersion2(value, what);\n if (!isRecord(value.resource) || typeof value.resource.url !== \"string\") {\n throw new X402CodecError(`The ${what} header has no resource.url`);\n }\n const accepts = value.accepts;\n if (!Array.isArray(accepts)) throw new X402CodecError(`The ${what} header has no accepts array`);\n for (const entry of accepts) {\n if (!isRecord(entry) || typeof entry.scheme !== \"string\" || typeof entry.network !== \"string\") {\n throw new X402CodecError(\n `The ${what} header has an accepts entry without scheme and network`,\n );\n }\n }\n return value as unknown as PaymentRequired;\n}\n\n/** A payment's `PAYMENT-SIGNATURE` header value. */\nexport function encodePaymentSignature(value: PaymentPayload): string {\n return encode(value);\n}\n\n/**\n * A `PAYMENT-SIGNATURE` header's value, checked for version 2 and the `accepted` and `payload`\n * objects; throws {@link X402CodecError} otherwise.\n */\nexport function decodePaymentSignature(header: string): PaymentPayload {\n const what = X402_HEADERS.paymentSignature;\n const value = decodeObject(header, what);\n requireVersion2(value, what);\n if (!isRecord(value.accepted) || !isRecord(value.payload)) {\n throw new X402CodecError(`The ${what} header has no accepted or payload object`);\n }\n return value as unknown as PaymentPayload;\n}\n\n/** A settlement's `PAYMENT-RESPONSE` header value. */\nexport function encodePaymentResponse(value: SettlementResponse): string {\n return encode(value);\n}\n\n/**\n * A `PAYMENT-RESPONSE` header's value, checked for a boolean `success`; throws\n * {@link X402CodecError} otherwise.\n */\nexport function decodePaymentResponse(header: string): SettlementResponse {\n const what = X402_HEADERS.paymentResponse;\n const value = decodeObject(header, what);\n if (typeof value.success !== \"boolean\") {\n throw new X402CodecError(`The ${what} header has no boolean success`);\n }\n return value as unknown as SettlementResponse;\n}\n","// Paying a 402 (docs/specs/scheme_on_delivery_svm.md, \"Client, before funding\"): one offer, the\n// caller's own terms, then either the on-delivery selection and funding of accept.ts and fund.ts or\n// the `exact` payment of exact.ts, and one paid request to the URL that answered.\nimport type { LookupAddress } from \"node:dns\";\nimport type { Connection, Keypair } from \"@solana/web3.js\";\nimport {\n escrowFee,\n getCaip2Network,\n isRecord,\n type PaymentRequired,\n type PaymentRequirements,\n type SettlementResponse,\n type SolanaCluster,\n} from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport type { Escro } from \"../client.js\";\nimport { EscroError, EscroPayError, EscroRailNotEnabledError } from \"../errors.js\";\nimport {\n ENABLED_RAILS,\n PAY_MAX_TIMEOUT_SECONDS,\n railOfScheme,\n type PayOffer,\n type PayParams,\n type PaymentResult,\n type PaymentRouter,\n type TxShape,\n} from \"../payments.js\";\nimport { admitX402Payment } from \"../spend-cap.js\";\nimport type { X402SpendCap } from \"../types.js\";\nimport { deepFreeze, parseEscrowAccept, readPlatformConfig } from \"./accept.js\";\nimport { X402CodecError } from \"./errors.js\";\nimport { checkExactRequirements, exactPayload } from \"./exact.js\";\nimport { fundSelection } from \"./fund.js\";\nimport {\n X402_HEADERS,\n decodePaymentRequired,\n decodePaymentResponse,\n encodePaymentRequired,\n encodePaymentSignature,\n} from \"./headers.js\";\nimport {\n callResolver,\n isBadPortUrl,\n judge,\n pinnedRequest,\n untilAborted,\n type HostResolver,\n} from \"./pinned-request.js\";\n\nconst FIRST_REQUEST_TIMEOUT_MS = 30_000;\n\n// RFC 9110 section 5.6.2.\nconst TOKEN = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n// The methods fetch refuses to send.\nconst FORBIDDEN_METHODS: readonly string[] = [\"CONNECT\", \"TRACE\", \"TRACK\"];\n\nexport interface PayOver402Deps {\n escro: Pick<Escro, \"createEscrow\">;\n wallet: Keypair;\n cluster: SolanaCluster;\n rpc: Pick<Connection, \"getAccountInfo\">;\n router: PaymentRouter;\n /** The client's own RPC URL, the only one the x402 scheme client reads through. */\n rpcUrl: string;\n /** Frozen at construction; absent means no x402 budget, which mainnet refuses. */\n x402SpendCap?: Readonly<X402SpendCap> | undefined;\n}\n\ntype Offer = { decoded: PaymentRequired } | { url: string };\n\ninterface RequestParts {\n method: string;\n /** Copied into each request's own Headers; never sent itself. */\n headers: Headers;\n body: string | undefined;\n /** The resource host's admitted answers, when the caller gave an address rule; absent, fetch. */\n pin?: readonly LookupAddress[];\n}\n\n/** The caller's address rule and the call's one resolution of each host. */\ninterface Pinning {\n rule: NonNullable<PayParams[\"admitAddress\"]>;\n resolve: HostResolver;\n}\n\n/** The escrow a refusal after the create names, so the caller can cancel it. */\ninterface Handle {\n escrowPda: string;\n createSignature: string;\n}\n\n/** What a refusal after an x402 payment left the process names, to match against chain. */\ntype X402Handle = Required<Pick<EscroPayError, \"payment\">>;\n\n/**\n * The arguments, checked in this order before any network, RPC or API call and before the 402 is\n * read: the terms, the offer, the URL, the request's headers, the request's method and body. A\n * request fetch would refuse is refused here, so it never fails after the escrow is funded.\n */\nfunction checkArguments(params: PayParams): { offer: Offer; parts: RequestParts } {\n if (!isCanonicalPubkey(params.to)) {\n throw new EscroError(\n `to must be a base-58 public key: ${JSON.stringify(params.to)}`,\n \"VALIDATION_ERROR\",\n );\n }\n if (!Number.isSafeInteger(params.amountMicroUsdc) || params.amountMicroUsdc <= 0) {\n throw new EscroError(\n `amountMicroUsdc must be a positive whole micro-USDC amount: ${String(params.amountMicroUsdc)}`,\n \"VALIDATION_ERROR\",\n );\n }\n const { paymentRequired, url } = params;\n if (paymentRequired !== undefined && url !== undefined) {\n throw new EscroPayError(\n \"both_offers\",\n \"pay() takes one offer: give paymentRequired or url, not both\",\n );\n }\n const offer: Offer | undefined =\n paymentRequired !== undefined\n ? { decoded: paymentRequired }\n : url !== undefined\n ? { url }\n : undefined;\n if (offer === undefined) {\n throw new EscroPayError(\"no_offer\", \"pay() needs a 402 to pay: give paymentRequired or url\");\n }\n if (\"url\" in offer && !isPayableUrl(offer.url)) {\n throw new EscroPayError(\n \"url\",\n \"url must be an absolute http: or https: URL without credentials\",\n );\n }\n if (\"url\" in offer && isBadPortUrl(new URL(offer.url))) {\n throw new EscroPayError(\"url\", \"url names a port fetch blocks\");\n }\n const request = params.request ?? {};\n const headers: unknown = request.headers ?? {};\n if (!isPlainRecord(headers)) {\n throw new EscroPayError(\"request_header\", \"request.headers must be a plain object record\", {\n detail: \"not_record\",\n });\n }\n // The copy is what every request sends, so the name check reads the copy, never the caller's object again.\n let validated: Headers;\n try {\n validated = new Headers(headers);\n } catch (cause) {\n throw new EscroPayError(\n \"request_header\",\n \"request.headers holds a name or value fetch refuses\",\n {\n cause,\n },\n );\n }\n if (validated.has(X402_HEADERS.paymentSignature)) {\n // Only the message's detail reads the caller's keys; the copy has already decided.\n const named = Object.keys(headers).find(\n (name) => name.toLowerCase() === X402_HEADERS.paymentSignature.toLowerCase(),\n );\n throw new EscroPayError(\"request_header\", \"request.headers may not carry PAYMENT-SIGNATURE\", {\n detail: named ?? X402_HEADERS.paymentSignature,\n });\n }\n const method = request.method ?? \"GET\";\n const upper = method.toUpperCase();\n if (!TOKEN.test(method) || FORBIDDEN_METHODS.includes(upper)) {\n throw new EscroPayError(\n \"request\",\n `request.method is not a method fetch sends: ${JSON.stringify(method)}`,\n {\n detail: method,\n },\n );\n }\n if ((upper === \"GET\" || upper === \"HEAD\") && request.body !== undefined) {\n throw new EscroPayError(\"request\", `A ${upper} request cannot carry a body`, {\n detail: method,\n });\n }\n return {\n offer,\n parts: { method, headers: validated, body: request.body },\n };\n}\n\n/**\n * An object whose prototype is Object.prototype or null, not an array, with no own symbol key: the record\n * PayRequest.headers declares. A Headers, an array, a Map or an iterable reads empty to Object.keys and still\n * carries headers into `new Headers(...)`.\n */\nfunction isPlainRecord(value: unknown): value is Record<string, string> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return false;\n return Object.getOwnPropertySymbols(value).length === 0;\n}\n\nfunction isPayableUrl(value: string): boolean {\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n return false;\n }\n return (\n (parsed.protocol === \"https:\" || parsed.protocol === \"http:\") &&\n parsed.username === \"\" &&\n parsed.password === \"\"\n );\n}\n\n/**\n * The caller's decoded 402, copied once (so nothing the caller holds is read again) and checked\n * through the header codec; the result is a deep-frozen object of pay()'s own.\n */\nfunction copyOfDecoded(required: PaymentRequired): PaymentRequired {\n let header: string;\n try {\n header = encodePaymentRequired(structuredClone(required));\n } catch (cause) {\n throw new EscroError(\n \"The 402 is not plain JSON data and cannot be copied\",\n \"VALIDATION_ERROR\",\n undefined,\n { cause },\n );\n }\n const offer = decodePaymentRequired(header);\n deepFreeze(offer);\n return offer;\n}\n\nconst isRedirect = (response: Response): boolean =>\n response.type === \"opaqueredirect\" || (response.status >= 300 && response.status < 400);\n\n/** `run` under one deadline of `timeoutMs`: its signal aborts when the deadline passes. */\nasync function withDeadline<T>(\n timeoutMs: number,\n run: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort(new Error(`The deadline of ${String(timeoutMs)} ms passed`));\n }, timeoutMs);\n try {\n return await run(controller.signal);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** One request bounded by `signal`; resolves at the response's headers, its body unread. */\nasync function send(\n url: string,\n parts: RequestParts,\n extraHeaders: Readonly<Record<string, string>>,\n signal: AbortSignal,\n): Promise<{ response: Response } | { timedOut: true } | { failed: unknown }> {\n const headers = new Headers(parts.headers);\n for (const [name, value] of Object.entries(extraHeaders)) headers.set(name, value);\n try {\n if (parts.pin !== undefined) {\n const init = { method: parts.method, headers, body: parts.body, signal };\n return { response: await pinnedRequest(url, init, parts.pin) };\n }\n const response = await fetch(url, {\n method: parts.method,\n headers,\n ...(parts.body === undefined ? {} : { body: parts.body }),\n redirect: \"manual\",\n signal,\n });\n return { response };\n } catch (failed) {\n return signal.aborted ? { timedOut: true } : { failed };\n }\n}\n\n/**\n * The resource host's answers the caller's rule admitted, from the call's one resolution, within the first request's\n * deadline (`signal`). Refusals name no host, URL or address.\n */\nasync function pinResource(\n url: string,\n pinning: Pinning,\n signal: AbortSignal,\n): Promise<readonly LookupAddress[]> {\n let answers: readonly LookupAddress[];\n try {\n answers = await untilAborted(pinning.resolve(new URL(url).hostname), signal);\n } catch (cause) {\n if (signal.aborted) {\n throw new EscroPayError(\n \"timeout\",\n `The resource's host did not resolve within ${String(FIRST_REQUEST_TIMEOUT_MS)} ms`,\n );\n }\n throw new EscroPayError(\"host\", \"The resource's host did not resolve\", {\n detail: \"unresolved\",\n cause,\n });\n }\n const judged = judge(answers, (address) => pinning.rule(address, \"resource\"));\n if (\"refused\" in judged) {\n throw judged.refused === \"address\"\n ? new EscroPayError(\n \"host\",\n \"The resource's host answered an address the address rule refuses\",\n { detail: \"address\" },\n )\n : new EscroPayError(\"host\", \"The resource's host did not resolve\", { detail: \"unresolved\" });\n }\n return judged.admitted;\n}\n\n/** url mode: the unpaid request within the first request's deadline (`signal`); its 402 must name `url`. */\nasync function requestOffer(\n url: string,\n parts: RequestParts,\n signal: AbortSignal,\n): Promise<PaymentRequired> {\n const sent = await send(url, parts, {}, signal);\n if (\"timedOut\" in sent) {\n throw new EscroPayError(\n \"timeout\",\n `${url} did not answer within ${String(FIRST_REQUEST_TIMEOUT_MS)} ms`,\n );\n }\n if (\"failed\" in sent) {\n throw new EscroError(`The request to ${url} failed`, \"NETWORK_ERROR\", undefined, {\n cause: sent.failed,\n });\n }\n const { response } = sent;\n await response.body?.cancel();\n if (isRedirect(response)) {\n throw new EscroPayError(\"redirect\", `${url} answered a redirect; pay() follows none`, {\n detail: String(response.status),\n });\n }\n if (response.status !== 402) {\n throw new EscroPayError(\"not_402\", `${url} answered HTTP ${String(response.status)}, not 402`, {\n detail: String(response.status),\n });\n }\n const header = response.headers.get(X402_HEADERS.paymentRequired);\n if (header === null) {\n throw new X402CodecError(`The 402 from ${url} has no ${X402_HEADERS.paymentRequired} header`);\n }\n const offer = decodePaymentRequired(header);\n deepFreeze(offer);\n if (offer.resource.url !== url) {\n throw new EscroPayError(\"resource_mismatch\", `The 402 from ${url} names another resource`, {\n detail: offer.resource.url,\n });\n }\n return offer;\n}\n\nconst overCeiling = (entry: PaymentRequirements): boolean =>\n typeof entry.maxTimeoutSeconds === \"number\" && entry.maxTimeoutSeconds > PAY_MAX_TIMEOUT_SECONDS;\n\nconst ceilingRefusal = (entry: PaymentRequirements): EscroPayError =>\n new EscroPayError(\n \"timeout_ceiling\",\n `The entry's maxTimeoutSeconds ${String(entry.maxTimeoutSeconds)} is over ${String(PAY_MAX_TIMEOUT_SECONDS)}`,\n { detail: String(entry.maxTimeoutSeconds) },\n );\n\nconst uptoRefusal = (): EscroPayError =>\n new EscroPayError(\"unsupported_scheme\", \"The upto scheme is not paid\", { detail: \"upto\" });\n\n/**\n * The entry to pay, chosen before any RPC read. An entry is eligible when it pays exactly the\n * caller's amount to the caller's `to` on the client's network, its scheme routes to an enabled\n * rail and is one Escro pays (`upto` is not), and its `maxTimeoutSeconds` is within the ceiling.\n * Without a policy the escrow rail wins whatever the 402's order, so the counterparty's list order\n * cannot move the buyer's funds off it; the order decides only within a rail, and a term-matching\n * escrow entry over the ceiling keeps the payment on that rail. A policy's choice must be one of\n * the copied entries and match the terms, and is then routed and held to the ceiling, with no\n * fallback.\n */\nfunction choose(\n offer: PaymentRequired,\n params: PayParams,\n deps: PayOver402Deps,\n): PaymentRequirements {\n const network = getCaip2Network(deps.cluster);\n const amount = String(params.amountMicroUsdc);\n const matchesTerms = (entry: PaymentRequirements): boolean =>\n entry.network === network && entry.payTo === params.to && entry.amount === amount;\n const route = (entry: PaymentRequirements): void => {\n const tx: TxShape = {\n to: params.to,\n amountMicroUsdc: params.amountMicroUsdc,\n mode: railOfScheme(entry.scheme) === \"x402\" ? \"sync\" : \"async\",\n accept: entry,\n };\n deps.router.selectRail(tx);\n };\n\n if (params.policy !== undefined) {\n const view: PayOffer = Object.freeze({\n resource: offer.resource,\n ...(offer.extensions === undefined ? {} : { extensions: offer.extensions }),\n });\n const chosen = params.policy(offer.accepts, view);\n if (!offer.accepts.includes(chosen)) {\n throw new EscroPayError(\n \"policy_choice\",\n \"The policy returned an object that is not one of the entries\",\n );\n }\n if (!matchesTerms(chosen)) {\n throw new EscroPayError(\n \"no_eligible_entry\",\n \"The policy chose an entry outside the caller's terms\",\n );\n }\n route(chosen);\n if (chosen.scheme === \"upto\") throw uptoRefusal();\n if (overCeiling(chosen)) throw ceilingRefusal(chosen);\n return chosen;\n }\n\n const matching = offer.accepts.filter(matchesTerms);\n const enabled = matching.filter((entry) => {\n const rail = railOfScheme(entry.scheme);\n return rail !== undefined && ENABLED_RAILS.includes(rail) && entry.scheme !== \"upto\";\n });\n const escrowEntries = enabled.filter((entry) => railOfScheme(entry.scheme) === \"escrow\");\n const candidates = escrowEntries.length > 0 ? escrowEntries : enabled;\n const chosen = candidates.find((entry) => !overCeiling(entry));\n if (chosen !== undefined) {\n route(chosen);\n return chosen;\n }\n for (const entry of matching) {\n const rail = railOfScheme(entry.scheme);\n if (rail !== undefined && !ENABLED_RAILS.includes(rail))\n throw new EscroRailNotEnabledError(rail);\n }\n const first = candidates[0];\n if (first !== undefined) throw ceilingRefusal(first);\n if (matching.length > 0 && matching.every((entry) => entry.scheme === \"upto\")) {\n throw uptoRefusal();\n }\n throw new EscroPayError(\n \"no_eligible_entry\",\n `The 402 offers no entry paying ${amount} micro-USDC to ${params.to} on ${network}`,\n );\n}\n\n/** The paid request, once, and its settlement; every failure carries `handle`. */\nasync function present(\n url: string,\n parts: RequestParts,\n header: string,\n timeoutMs: number,\n handle: Handle | X402Handle,\n): Promise<{ settlement: SettlementResponse; response: Response }> {\n const sent = await withDeadline(timeoutMs, (signal) =>\n send(url, parts, { [X402_HEADERS.paymentSignature]: header }, signal),\n );\n if (\"timedOut\" in sent) {\n throw new EscroPayError(\n \"timeout\",\n `The paid request to ${url} did not answer within ${String(timeoutMs)} ms`,\n handle,\n );\n }\n if (\"failed\" in sent) {\n throw new EscroPayError(\"presentation\", `The paid request to ${url} failed`, {\n ...handle,\n cause: sent.failed,\n });\n }\n const { response } = sent;\n const answered = { ...handle, status: response.status };\n if (isRedirect(response)) {\n await response.body?.cancel();\n throw new EscroPayError(\n \"redirect\",\n `The paid request to ${url} answered a redirect; pay() follows none`,\n answered,\n );\n }\n if (!response.ok) {\n const reported = refusalSettlement(response.headers.get(X402_HEADERS.paymentResponse));\n await response.body?.cancel();\n throw new EscroPayError(\n \"presentation\",\n `The paid request to ${url} answered HTTP ${String(response.status)}`,\n reported === undefined ? answered : { ...answered, settlement: reported },\n );\n }\n const value = response.headers.get(X402_HEADERS.paymentResponse);\n if (value === null) {\n await response.body?.cancel();\n throw new EscroPayError(\n \"settlement\",\n `The paid answer carries no ${X402_HEADERS.paymentResponse}`,\n answered,\n );\n }\n let settlement: SettlementResponse;\n try {\n settlement = decodePaymentResponse(value);\n } catch (cause) {\n await response.body?.cancel();\n throw new EscroPayError(\n \"settlement\",\n `The paid answer's ${X402_HEADERS.paymentResponse} does not decode`,\n {\n ...answered,\n cause,\n },\n );\n }\n if (!settlement.success) {\n await response.body?.cancel();\n throw new EscroPayError(\"settlement\", `The worker reported the settlement failed`, {\n ...answered,\n ...(settlement.errorReason === undefined ? {} : { detail: settlement.errorReason }),\n });\n }\n return { settlement, response };\n}\n\n/**\n * The settlement a worker sent beside an error status, when its header decodes with a string `transaction` and\n * `network`; otherwise none. It never changes the refusal: an undecodable header on an error answer is not the error.\n */\nfunction refusalSettlement(value: string | null): SettlementResponse | undefined {\n if (value === null) return undefined;\n let settlement: SettlementResponse;\n try {\n settlement = decodePaymentResponse(value);\n } catch {\n return undefined;\n }\n const { transaction, network }: { transaction: unknown; network: unknown } = settlement;\n return typeof transaction === \"string\" && typeof network === \"string\" ? settlement : undefined;\n}\n\n/**\n * The x402 rail, in order: the requirement checks, the cap admission, the package load and the\n * guarded signature, then one paid request. The amount is credited back only while no signature\n * can exist; once the signer's flag is set it stays counted.\n */\nasync function payExact(\n deps: PayOver402Deps,\n offer: PaymentRequired,\n chosen: PaymentRequirements,\n parts: RequestParts,\n amountMicroUsdc: number,\n): Promise<PaymentResult> {\n checkExactRequirements(chosen, deps.wallet.publicKey, deps.cluster);\n // Echoed into the payment, a non-object `extensions` would make it invalid V2 once signed.\n const extensions: unknown = offer.extensions;\n if (extensions !== undefined && !isRecord(extensions)) {\n throw new EscroPayError(\"requirements\", \"The 402's extensions is not a JSON object\", {\n detail: \"extensions\",\n });\n }\n const release = await admitX402Payment(\n deps.x402SpendCap,\n deps.cluster,\n deps.wallet.publicKey.toBase58(),\n amountMicroUsdc,\n );\n const signed: { memo?: string } = {};\n let payload: { transaction: string };\n try {\n payload = await exactPayload(chosen, {\n wallet: deps.wallet,\n cluster: deps.cluster,\n rpcUrl: deps.rpcUrl,\n onSigned: (memo) => {\n signed.memo = memo;\n },\n });\n } catch (err) {\n if (signed.memo === undefined) release();\n throw err;\n }\n if (signed.memo === undefined) {\n release();\n throw new EscroPayError(\"transaction\", \"The x402 scheme client returned an unsigned payment\", {\n detail: \"build\",\n });\n }\n\n const handle: X402Handle = {\n payment: { memo: signed.memo, amountMicroUsdc, payTo: chosen.payTo },\n };\n const url = offer.resource.url;\n let paid: { settlement: SettlementResponse; response: Response };\n try {\n paid = await present(\n url,\n parts,\n encodePaymentSignature({\n x402Version: 2,\n resource: offer.resource,\n accepted: chosen,\n payload: { ...payload },\n ...(extensions === undefined ? {} : { extensions }),\n }),\n chosen.maxTimeoutSeconds * 1000,\n handle,\n );\n } catch (err) {\n if (err instanceof EscroPayError) throw err;\n throw new EscroPayError(\"presentation\", \"Presenting the x402 payment failed\", {\n ...handle,\n cause: err,\n });\n }\n // The header decoder checks only `success`; this rail's reference is the settlement's transaction.\n const transaction: unknown = paid.settlement.transaction;\n if (typeof transaction !== \"string\" || transaction === \"\") {\n await paid.response.body?.cancel();\n throw new EscroPayError(\"settlement\", \"The paid answer names no settlement transaction\", {\n ...handle,\n status: paid.response.status,\n });\n }\n return { rail: \"x402\", reference: transaction, ...paid };\n}\n\n/**\n * Pays a 402 for {@link Escro.pay}: checks the arguments, takes the offer (requesting `params.url`,\n * or copying `params.paymentRequired`) and chooses an entry matching the caller's `to`, amount and\n * cluster. An x402-routed entry goes to {@link payExact}; an escrow entry is funded through\n * {@link parseEscrowAccept} and {@link fundSelection} (so through `createEscrow` and its spend\n * cap). The payment is presented once to the 402's resource URL. With `admitAddress`, every request of the call\n * connects only to the answers the rule admitted from one resolution of its host; in url mode the resource host's\n * lookup and the unpaid request share the first request's one deadline.\n */\nexport async function payOver402(deps: PayOver402Deps, params: PayParams): Promise<PaymentResult> {\n const { offer: given, parts: unpinned } = checkArguments(params);\n const rule = params.admitAddress;\n const pinning: Pinning | undefined =\n rule === undefined ? undefined : { rule, resolve: callResolver() };\n const pinnedTo = async (url: string, signal: AbortSignal): Promise<RequestParts> =>\n pinning === undefined\n ? unpinned\n : { ...unpinned, pin: await pinResource(url, pinning, signal) };\n let parts = unpinned;\n let offer: PaymentRequired;\n if (\"decoded\" in given) {\n offer = copyOfDecoded(given.decoded);\n } else {\n const { url } = given;\n [parts, offer] = await withDeadline(FIRST_REQUEST_TIMEOUT_MS, async (signal) => {\n const pinned = await pinnedTo(url, signal);\n return [pinned, await requestOffer(url, pinned, signal)] as const;\n });\n }\n const resourceUrl = offer.resource.url;\n // A decoded 402 names its own URL; one fetch would refuse must not reach the create.\n if (!isPayableUrl(resourceUrl)) {\n throw new EscroPayError(\n \"url\",\n \"The 402's resource.url must be an absolute http: or https: URL without credentials\",\n { detail: \"resource.url\" },\n );\n }\n if (isBadPortUrl(new URL(resourceUrl))) {\n throw new EscroPayError(\"url\", \"The 402's resource.url names a port fetch blocks\", {\n detail: \"resource.url\",\n });\n }\n // Before any policy call, chain read, spec fetch or signature.\n if (\"decoded\" in given) {\n parts = await withDeadline(FIRST_REQUEST_TIMEOUT_MS, (signal) => pinnedTo(resourceUrl, signal));\n }\n const chosen = choose(offer, params, deps);\n if (railOfScheme(chosen.scheme) === \"x402\") {\n return payExact(deps, offer, chosen, parts, params.amountMicroUsdc);\n }\n\n const platformConfig = await readPlatformConfig(deps.rpc, deps.cluster);\n const amount = BigInt(params.amountMicroUsdc);\n const selection = parseEscrowAccept(\n { ...offer, accepts: [chosen] },\n {\n cluster: deps.cluster,\n platformConfig,\n maxDepositMicroUsdc: amount + escrowFee(amount, platformConfig.feeBps),\n payTo: params.to,\n ...(params.admitAcceptance === undefined ? {} : { admitAcceptance: params.admitAcceptance }),\n },\n );\n const { payment } = await fundSelection(\n selection,\n {\n escro: deps.escro,\n wallet: deps.wallet,\n resourceUrl,\n // judge() admits an answer only when the rule returns exactly true.\n ...(pinning === undefined\n ? {}\n : { admitAddress: (address: string) => pinning.rule(address, \"spec\") }),\n },\n pinning?.resolve ?? callResolver(),\n );\n\n const handle: Handle = {\n escrowPda: payment.payload.escrow,\n createSignature: payment.payload.createSignature,\n };\n let paid: { settlement: SettlementResponse; response: Response };\n try {\n paid = await present(\n resourceUrl,\n parts,\n // The spread only types the payload fields as the codec's Record; the payment is not written.\n encodePaymentSignature({ ...payment, payload: { ...payment.payload } }),\n selection.entry.maxTimeoutSeconds * 1000,\n handle,\n );\n } catch (err) {\n if (err instanceof EscroPayError) throw err;\n throw new EscroPayError(\n \"presentation\",\n \"Presenting the payment failed after the escrow was funded\",\n {\n ...handle,\n cause: err,\n },\n );\n }\n return {\n rail: \"escrow\",\n reference: handle.createSignature,\n escrow: handle.escrowPda,\n ...paid,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { canonicalize, type Acceptance } from \"@escro/shared\";\n\nimport { EscroError } from \"../errors.js\";\n\nexport type PredicateName =\n | \"hash-matches\"\n | \"tests-pass\"\n | \"json-schema\"\n | \"file-format\"\n | \"pod-receipt\"\n | \"llm-rubric\"\n | \"ci-check\"\n | \"period-sla\"\n | \"attestation-valid\";\n\n/** The job a decision record decides (docs/specs/escro-extension.md \"Decision record\", `job`). */\nexport interface DecisionJob {\n /** CAIP-2: `solana:<32 base58>` or `eip155:<decimal chain id>`. */\n network: string;\n /** Solana: the base58 program id; ERC-8183: the lowercase `0x` contract address. */\n program: string;\n /** Solana: the escrow PDA, base58; ERC-8183: the jobId in decimal. */\n id: string;\n}\n\n/** The one decision record the `escro` extension defines (docs/specs/escro-extension.md \"Decision record\"). */\nexport interface DecisionRecord {\n acceptance: Acceptance;\n decision: \"pass\" | \"fail\";\n deliverableHash: string;\n job: DecisionJob;\n}\n\nexport interface Delivery {\n /** The delivered bytes, as the deliverable derivation defines them. */\n bytes: Uint8Array;\n /** pod-receipt: a base58 ed25519 signature. */\n receipt?: string;\n /** attestation-valid: the attestation as the worker supplied it. */\n attestation?: Uint8Array;\n}\n\n/** Every external evaluator is the buyer's own function; the library calls nothing else. */\nexport interface PredicateContext {\n runTests?(i: {\n suite: string;\n delivery: Uint8Array;\n }): Promise<{ passed: number; failed: number }>;\n grade?(i: { rubric: string; model: string; delivery: Uint8Array }): Promise<number>;\n ciStatus?(i: {\n repository: string;\n revision: string;\n check: string;\n }): Promise<\"success\" | \"failure\" | \"pending\" | \"missing\">;\n samples?(i: { metric: string; from: number; to: number }): Promise<number[]>;\n verifyAttestation?(i: {\n kind: string;\n attestation: Uint8Array;\n }): Promise<{ valid: boolean; subjectSha256: string }>;\n}\n\nexport interface PredicateOutcome {\n decision: \"pass\" | \"fail\";\n reason: string;\n}\n\nexport interface Predicate<P = unknown> {\n readonly name: PredicateName;\n /** Throws {@link PredicateParamsError}; callable before funding. */\n parseParams(raw: unknown): P;\n evaluate(delivery: Delivery, params: P, ctx: PredicateContext): Promise<PredicateOutcome>;\n}\n\n/** Parameters a predicate does not accept, or that do not hash to the advertised `paramsHash`. */\nexport class PredicateParamsError extends EscroError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, \"PREDICATE_PARAMS\", undefined, options);\n this.name = \"PredicateParamsError\";\n }\n}\n\n/** A decision record, or an `acceptance`, the extension's schema refuses. */\nexport class PredicateRecordError extends EscroError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, \"PREDICATE_RECORD\", undefined, options);\n this.name = \"PredicateRecordError\";\n }\n}\n\n/** No decision was reached: the buyer's evaluator is absent, failed, or cannot decide yet. */\nexport class PredicateEvaluationError extends EscroError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, \"PREDICATE_EVALUATION\", undefined, options);\n this.name = \"PredicateEvaluationError\";\n }\n}\n\nexport function sha256Hex(data: Uint8Array | string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n\nexport const SHA256_HEX = /^[0-9a-f]{64}$/;\n\nexport function isSha256Hex(value: unknown): value is string {\n return typeof value === \"string\" && value.length === 64 && SHA256_HEX.test(value);\n}\n\n/** RFC 6901: `~` and `/` in a member name are escaped. */\nexport function pointerTo(parent: string, member: string | number): string {\n return `${parent}/${String(member).replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\")}`;\n}\n\nconst LONE_SURROGATE = /[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]/;\n\nfunction isPlainObject(value: object): boolean {\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** The deepest nesting of arrays and objects {@link jcs} and {@link jsonRefusal} walk before refusing. */\nconst MAX_JSON_DEPTH = 128;\n\n/**\n * Why `value` is not RFC 8785 JSON, or null when it is: a non-finite number (`canonicalize` would\n * write null), a lone surrogate (escaped), an undefined member (dropped) or item (to null), any value\n * JSON cannot hold, or nesting deeper than {@link MAX_JSON_DEPTH}. The walk stops at that depth, so a\n * counterparty's value cannot overflow the stack here or in the `canonicalize` that follows.\n */\nexport function jsonRefusal(value: unknown, pointer = \"\", depth = 0): string | null {\n const at = pointer === \"\" ? \"/\" : pointer;\n switch (typeof value) {\n case \"boolean\":\n return null;\n case \"number\":\n return Number.isFinite(value) ? null : `${String(value)} at ${at} is not a JSON number`;\n case \"string\":\n return LONE_SURROGATE.test(value)\n ? `a lone surrogate at ${at} is not well-formed text`\n : null;\n case \"object\": {\n if (value === null) return null;\n if (depth >= MAX_JSON_DEPTH) {\n return `${at} nests deeper than ${String(MAX_JSON_DEPTH)} arrays and objects`;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i += 1) {\n const found = jsonRefusal((value as unknown[])[i], pointerTo(pointer, i), depth + 1);\n if (found !== null) return found;\n }\n return null;\n }\n if (!isPlainObject(value)) return `a non-plain object at ${at} is not JSON`;\n for (const [key, member] of Object.entries(value)) {\n if (LONE_SURROGATE.test(key)) return `a member name at ${at} holds a lone surrogate`;\n const found = jsonRefusal(member, pointerTo(pointer, key), depth + 1);\n if (found !== null) return found;\n }\n return null;\n }\n default:\n return `a ${typeof value} at ${at} is not JSON`;\n }\n}\n\n/** RFC 8785 canonical JSON: a refusal pass ({@link PredicateParamsError}), then the shared `canonicalize`. */\nexport function jcs(value: unknown): string {\n const refused = jsonRefusal(value);\n if (refused !== null) throw new PredicateParamsError(refused);\n return canonicalize(value);\n}\n\n/** The SHA-256 hex of the UTF-8 {@link jcs} of `params`: what `acceptance.paramsHash` carries. */\nexport function paramsHash(params: unknown): string {\n return sha256Hex(Buffer.from(jcs(params), \"utf8\"));\n}\n\n/** `raw` as a plain object holding no member outside `allowed`. */\nexport function paramsObject(\n predicate: PredicateName,\n raw: unknown,\n allowed: readonly string[],\n): Record<string, unknown> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw) || !isPlainObject(raw)) {\n throw new PredicateParamsError(`${predicate} params must be a JSON object`);\n }\n for (const key of Object.keys(raw)) {\n if (!allowed.includes(key)) {\n throw new PredicateParamsError(`${predicate} takes no parameter named ${key}`);\n }\n }\n return raw as Record<string, unknown>;\n}\n\nconst MAX_IDENTIFIER = 256;\nconst IDENTIFIER = /^[!-~]{1,256}$/;\n\n/** An identifier parameter: 1 to 256 printable ASCII characters, no space. */\nexport function identifier(\n predicate: PredicateName,\n params: Record<string, unknown>,\n field: string,\n): string {\n const value = params[field];\n if (typeof value !== \"string\" || value.length > MAX_IDENTIFIER || !IDENTIFIER.test(value)) {\n throw new PredicateParamsError(\n `${predicate} ${field} must be 1 to ${String(MAX_IDENTIFIER)} printable ASCII characters with no space`,\n );\n }\n return value;\n}\n\n/** An optional whole, non-negative number parameter no smaller than `min`. */\nexport function optionalInteger(\n predicate: PredicateName,\n params: Record<string, unknown>,\n field: string,\n min: number,\n): number | undefined {\n if (!Object.hasOwn(params, field)) return undefined;\n const value = params[field];\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < min) {\n throw new PredicateParamsError(\n `${predicate} ${field} must be a whole number of at least ${String(min)}`,\n );\n }\n return value;\n}\n\n/**\n * The answer of the buyer's evaluator, which `call` invokes through an optional call\n * (`ctx.grade?.(...)`). An absent evaluator, or any failure of it, is a\n * {@link PredicateEvaluationError}: no decision was reached.\n */\nexport async function consult<T>(\n predicate: PredicateName,\n evaluator: string,\n call: () => Promise<T> | undefined,\n): Promise<T> {\n let pending: Promise<T> | undefined;\n try {\n pending = call();\n if (pending !== undefined) return await pending;\n } catch (err) {\n throw new PredicateEvaluationError(\n `${predicate}: the buyer's ${evaluator} failed: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n throw new PredicateEvaluationError(\n `${predicate} needs the buyer's own ${evaluator} function in the predicate context`,\n );\n}\n\nconst UTF8 = new TextDecoder(\"utf-8\", { fatal: true });\n\n/** The bytes as UTF-8 text, or null when they are not UTF-8. */\nexport function utf8(bytes: Uint8Array): string | null {\n try {\n return UTF8.decode(bytes);\n } catch {\n return null;\n }\n}\n","import {\n PredicateEvaluationError,\n consult,\n identifier,\n paramsObject,\n sha256Hex,\n type Predicate,\n} from \"./core.js\";\n\ninterface AttestationValidParams {\n kind: string;\n}\n\n// A valid attestation passes only when its subject is these bytes: a proof over other content\n// releases nothing.\nconst predicate: Predicate<AttestationValidParams> = {\n name: \"attestation-valid\",\n parseParams(raw) {\n const params = paramsObject(\"attestation-valid\", raw, [\"kind\"]);\n return { kind: identifier(\"attestation-valid\", params, \"kind\") };\n },\n async evaluate(delivery, params, ctx) {\n const { attestation } = delivery;\n if (attestation === undefined) {\n return { decision: \"fail\", reason: \"the delivery carries no attestation\" };\n }\n const verdict: unknown = await consult(\"attestation-valid\", \"verifyAttestation\", () =>\n ctx.verifyAttestation?.({ kind: params.kind, attestation }),\n );\n if (typeof verdict !== \"object\" || verdict === null) {\n throw new PredicateEvaluationError(\n \"attestation-valid: the buyer's verifyAttestation returned no verdict\",\n );\n }\n const { valid, subjectSha256 } = verdict as Record<string, unknown>;\n if (typeof valid !== \"boolean\") {\n throw new PredicateEvaluationError(\n \"attestation-valid: the buyer's verifyAttestation returned no boolean valid\",\n );\n }\n if (!valid) return { decision: \"fail\", reason: `the ${params.kind} attestation is not valid` };\n const subject = sha256Hex(delivery.bytes);\n return subjectSha256 === subject\n ? { decision: \"pass\", reason: `a valid ${params.kind} attestation covers the delivery` }\n : {\n decision: \"fail\",\n reason: `the ${params.kind} attestation's subject is not the delivery`,\n };\n },\n};\n\nexport const attestationValid: Predicate = predicate;\n","import {\n PredicateEvaluationError,\n consult,\n identifier,\n paramsObject,\n utf8,\n type Predicate,\n} from \"./core.js\";\n\ninterface CiCheckParams {\n repository: string;\n check: string;\n}\n\nconst REVISION = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;\n\nconst predicate: Predicate<CiCheckParams> = {\n name: \"ci-check\",\n parseParams(raw) {\n const params = paramsObject(\"ci-check\", raw, [\"repository\", \"check\"]);\n return {\n repository: identifier(\"ci-check\", params, \"repository\"),\n check: identifier(\"ci-check\", params, \"check\"),\n };\n },\n async evaluate(delivery, params, ctx) {\n // A delivery that is not a revision never reaches the buyer's CI client.\n const revision = utf8(delivery.bytes)?.trim();\n if (revision === undefined || !REVISION.test(revision)) {\n return {\n decision: \"fail\",\n reason: \"the delivery is not a 40- or 64-character lowercase hex revision\",\n };\n }\n const status: unknown = await consult(\"ci-check\", \"ciStatus\", () =>\n ctx.ciStatus?.({ repository: params.repository, revision, check: params.check }),\n );\n switch (status) {\n case \"success\":\n return { decision: \"pass\", reason: `${params.check} succeeded at ${revision}` };\n case \"failure\":\n case \"missing\":\n return { decision: \"fail\", reason: `${params.check} is ${status} at ${revision}` };\n case \"pending\":\n throw new PredicateEvaluationError(\n `ci-check: ${params.check} is still pending at ${revision}; no decision yet`,\n );\n default:\n throw new PredicateEvaluationError(\n `ci-check: the buyer's ciStatus returned ${String(status)}, not a CI status`,\n );\n }\n },\n};\n\nexport const ciCheck: Predicate = predicate;\n","import {\n PredicateParamsError,\n optionalInteger,\n paramsObject,\n utf8,\n type Predicate,\n} from \"./core.js\";\n\nconst SIGNATURES = {\n \"application/pdf\": [0x25, 0x50, 0x44, 0x46, 0x2d],\n \"image/png\": [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],\n \"image/jpeg\": [0xff, 0xd8, 0xff],\n \"application/zip\": [0x50, 0x4b, 0x03, 0x04],\n \"model/gltf-binary\": [0x67, 0x6c, 0x54, 0x46],\n} as const;\nconst TEXT_TYPES = [\"text/plain\", \"text/markdown\", \"text/csv\"] as const;\nconst MIME_TYPES = [\"application/json\", ...Object.keys(SIGNATURES), ...TEXT_TYPES];\n\ninterface FileFormatParams {\n mimeType: string;\n minSizeBytes: number;\n maxSizeBytes: number;\n}\n\nfunction startsWith(bytes: Uint8Array, signature: readonly number[]): boolean {\n return bytes.length >= signature.length && signature.every((b, i) => bytes[i] === b);\n}\n\nfunction matches(mimeType: string, bytes: Uint8Array): boolean {\n if (mimeType === \"application/json\") {\n const text = utf8(bytes);\n if (text === null) return false;\n try {\n JSON.parse(text);\n return true;\n } catch {\n return false;\n }\n }\n if ((TEXT_TYPES as readonly string[]).includes(mimeType)) {\n return !bytes.includes(0) && utf8(bytes) !== null;\n }\n const signature = (SIGNATURES as Record<string, readonly number[] | undefined>)[mimeType];\n return signature !== undefined && startsWith(bytes, signature);\n}\n\nconst predicate: Predicate<FileFormatParams> = {\n name: \"file-format\",\n parseParams(raw) {\n const params = paramsObject(\"file-format\", raw, [\"mimeType\", \"minSizeBytes\", \"maxSizeBytes\"]);\n const { mimeType } = params;\n if (typeof mimeType !== \"string\" || !MIME_TYPES.includes(mimeType)) {\n throw new PredicateParamsError(\n `file-format mimeType must be one of ${MIME_TYPES.join(\", \")}`,\n );\n }\n const minSizeBytes = optionalInteger(\"file-format\", params, \"minSizeBytes\", 0) ?? 0;\n const maxSizeBytes =\n optionalInteger(\"file-format\", params, \"maxSizeBytes\", 0) ?? Number.MAX_SAFE_INTEGER;\n if (minSizeBytes > maxSizeBytes) {\n throw new PredicateParamsError(\"file-format minSizeBytes must not exceed maxSizeBytes\");\n }\n return { mimeType, minSizeBytes, maxSizeBytes };\n },\n // The size bounds are checked before any content check, so an oversized delivery is never parsed.\n evaluate(delivery, params) {\n const size = delivery.bytes.length;\n if (size < params.minSizeBytes || size > params.maxSizeBytes) {\n return Promise.resolve({\n decision: \"fail\",\n reason: `the delivery is ${String(size)} bytes, outside [${String(params.minSizeBytes)}, ${String(params.maxSizeBytes)}]`,\n });\n }\n return Promise.resolve(\n matches(params.mimeType, delivery.bytes)\n ? { decision: \"pass\", reason: `the delivery is ${params.mimeType}` }\n : { decision: \"fail\", reason: `the delivery's content is not ${params.mimeType}` },\n );\n },\n};\n\nexport const fileFormat: Predicate = predicate;\n","import {\n PredicateParamsError,\n isSha256Hex,\n paramsObject,\n sha256Hex,\n type Predicate,\n} from \"./core.js\";\n\ninterface HashMatchesParams {\n sha256: string;\n}\n\n// The expected hash is the buyer's (the params), never the escrow's commitment: the worker chose that.\nconst predicate: Predicate<HashMatchesParams> = {\n name: \"hash-matches\",\n parseParams(raw) {\n const params = paramsObject(\"hash-matches\", raw, [\"sha256\"]);\n if (!isSha256Hex(params.sha256)) {\n throw new PredicateParamsError(\"hash-matches sha256 must be 64 lowercase hex characters\");\n }\n return { sha256: params.sha256 };\n },\n evaluate(delivery, params) {\n const actual = sha256Hex(delivery.bytes);\n return Promise.resolve(\n actual === params.sha256\n ? { decision: \"pass\", reason: `the delivery hashes to ${params.sha256}` }\n : { decision: \"fail\", reason: `the delivery hashes to ${actual}, not ${params.sha256}` },\n );\n },\n};\n\nexport const hashMatches: Predicate = predicate;\n","import { canonicalize } from \"@escro/shared\";\n\nimport {\n PredicateParamsError,\n jcs,\n jsonRefusal,\n paramsObject,\n pointerTo,\n utf8,\n type Predicate,\n} from \"./core.js\";\n\nconst TYPES = [\"null\", \"boolean\", \"object\", \"array\", \"number\", \"integer\", \"string\"] as const;\ntype JsonType = (typeof TYPES)[number];\n\n/** A compiled subschema of the subset; `properties` is a Map so no member name meets a prototype. */\ninterface Subschema {\n type?: JsonType;\n required?: string[];\n properties?: Map<string, Subschema>;\n additionalProperties?: boolean;\n enum?: Set<string>;\n minimum?: number;\n maximum?: number;\n items?: Subschema;\n}\n\ninterface JsonSchemaParams {\n schema: Subschema;\n}\n\nconst ANNOTATIONS = new Set([\"$schema\", \"$id\", \"$comment\", \"title\", \"description\"]);\nconst MAX_DEPTH = 32;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction refuse(message: string): never {\n throw new PredicateParamsError(`json-schema ${message}`);\n}\n\n// Fails closed: a keyword outside the subset, or a supported keyword in another form,\n// is refused, so no schema is half-read. `pattern` is refused too: a counterparty's regex run in\n// the buyer's process could hang it past the 24 h auto-release.\nfunction compile(schema: unknown, pointer: string, depth: number): Subschema {\n if (depth > MAX_DEPTH) {\n refuse(`nests deeper than ${String(MAX_DEPTH)} subschemas at ${pointer}`);\n }\n if (!isObject(schema)) refuse(`subschema at ${pointer} is not an object`);\n const out: Subschema = {};\n for (const [keyword, value] of Object.entries(schema)) {\n const at = pointerTo(pointer, keyword);\n if (ANNOTATIONS.has(keyword)) continue;\n switch (keyword) {\n case \"type\":\n if (typeof value !== \"string\" || !(TYPES as readonly string[]).includes(value)) {\n refuse(`type at ${at} must be one of ${TYPES.join(\", \")}`);\n }\n out.type = value as JsonType;\n break;\n case \"required\":\n if (!Array.isArray(value) || !value.every((name) => typeof name === \"string\")) {\n refuse(`required at ${at} must be an array of member names`);\n }\n out.required = value;\n break;\n case \"properties\": {\n if (!isObject(value)) refuse(`properties at ${at} must be an object`);\n const properties = new Map<string, Subschema>();\n for (const [name, sub] of Object.entries(value)) {\n properties.set(name, compile(sub, pointerTo(at, name), depth + 1));\n }\n out.properties = properties;\n break;\n }\n case \"additionalProperties\":\n if (typeof value !== \"boolean\") {\n refuse(`additionalProperties at ${at} must be a boolean`);\n }\n out.additionalProperties = value;\n break;\n case \"enum\":\n if (!Array.isArray(value)) refuse(`enum at ${at} must be an array`);\n out.enum = new Set(value.map((member) => jcs(member)));\n break;\n case \"minimum\":\n case \"maximum\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n refuse(`${keyword} at ${at} must be a finite number`);\n }\n out[keyword] = value;\n break;\n case \"items\":\n if (Array.isArray(value)) refuse(`items at ${at} must be one schema, not an array`);\n out.items = compile(value, at, depth + 1);\n break;\n default:\n refuse(`does not support the keyword ${keyword} (at ${at})`);\n }\n }\n return out;\n}\n\nfunction typeOf(value: unknown): JsonType[] {\n if (value === null) return [\"null\"];\n if (Array.isArray(value)) return [\"array\"];\n switch (typeof value) {\n case \"boolean\":\n return [\"boolean\"];\n case \"number\":\n return Number.isInteger(value) ? [\"number\", \"integer\"] : [\"number\"];\n case \"string\":\n return [\"string\"];\n default:\n return [\"object\"];\n }\n}\n\n/**\n * The first violation of `schema` by `value`, or null. Recursion follows the schema's bounded depth;\n * `value` has passed {@link jsonRefusal}, so the `canonicalize` at an enum is bounded too.\n */\nfunction violation(value: unknown, schema: Subschema, pointer: string): string | null {\n const at = pointer === \"\" ? \"/\" : pointer;\n if (schema.type !== undefined && !typeOf(value).includes(schema.type)) {\n return `${at} is not of type ${schema.type}`;\n }\n // The instance passed jsonRefusal (finite numbers, well-formed text, bounded depth), so\n // canonicalize equals jcs over it; the enum members passed jcs when the schema was compiled.\n if (schema.enum !== undefined && !schema.enum.has(canonicalize(value))) {\n return `${at} is not one of the enum values`;\n }\n if (typeof value === \"number\") {\n if (schema.minimum !== undefined && value < schema.minimum) {\n return `${at} is below the minimum ${String(schema.minimum)}`;\n }\n if (schema.maximum !== undefined && value > schema.maximum) {\n return `${at} is above the maximum ${String(schema.maximum)}`;\n }\n }\n if (Array.isArray(value) && schema.items !== undefined) {\n for (let i = 0; i < value.length; i += 1) {\n const found = violation((value as unknown[])[i], schema.items, pointerTo(pointer, i));\n if (found !== null) return found;\n }\n }\n if (isObject(value)) {\n for (const name of schema.required ?? []) {\n if (!Object.hasOwn(value, name)) return `${at} lacks the required member ${name}`;\n }\n for (const name of Object.keys(value)) {\n const sub = schema.properties?.get(name);\n if (sub !== undefined) {\n const found = violation(value[name], sub, pointerTo(pointer, name));\n if (found !== null) return found;\n } else if (schema.additionalProperties === false) {\n return `${at} has the member ${name}, outside properties`;\n }\n }\n }\n return null;\n}\n\nconst predicate: Predicate<JsonSchemaParams> = {\n name: \"json-schema\",\n parseParams(raw) {\n const params = paramsObject(\"json-schema\", raw, [\"schema\"]);\n return { schema: compile(params.schema, \"/schema\", 0) };\n },\n evaluate(delivery, params) {\n const text = utf8(delivery.bytes);\n if (text === null) {\n return Promise.resolve({ decision: \"fail\", reason: \"the delivery is not UTF-8\" });\n }\n let instance: unknown;\n try {\n instance = JSON.parse(text);\n } catch {\n return Promise.resolve({ decision: \"fail\", reason: \"the delivery is not JSON\" });\n }\n const refused = jsonRefusal(instance);\n if (refused !== null) {\n return Promise.resolve({\n decision: \"fail\",\n reason: `the delivery is not RFC 8785 JSON: ${refused}`,\n });\n }\n const found = violation(instance, params.schema, \"\");\n return Promise.resolve(\n found === null\n ? { decision: \"pass\", reason: \"the delivery validates against the schema\" }\n : { decision: \"fail\", reason: found },\n );\n },\n};\n\nexport const jsonSchema: Predicate = predicate;\n","import {\n PredicateEvaluationError,\n PredicateParamsError,\n consult,\n identifier,\n paramsObject,\n type Predicate,\n} from \"./core.js\";\n\ninterface LlmRubricParams {\n rubric: string;\n threshold: number;\n model: string;\n}\n\nconst MAX_RUBRIC = 8192;\nconst SURROGATE_PAIR = /[\\ud800-\\udbff][\\udc00-\\udfff]/g;\n\nfunction isUnitScore(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 && value <= 1;\n}\n\n// The model is the buyer's, run by the buyer: the library holds no default grader.\nconst predicate: Predicate<LlmRubricParams> = {\n name: \"llm-rubric\",\n parseParams(raw) {\n const params = paramsObject(\"llm-rubric\", raw, [\"rubric\", \"threshold\", \"model\"]);\n const { rubric, threshold } = params;\n // A code point is at most two UTF-16 units: the unit count bounds the string before it is walked.\n if (\n typeof rubric !== \"string\" ||\n rubric.length === 0 ||\n rubric.length > 2 * MAX_RUBRIC ||\n rubric.length - (rubric.match(SURROGATE_PAIR)?.length ?? 0) > MAX_RUBRIC\n ) {\n throw new PredicateParamsError(\n `llm-rubric rubric must be 1 to ${String(MAX_RUBRIC)} code points`,\n );\n }\n if (!isUnitScore(threshold)) {\n throw new PredicateParamsError(\"llm-rubric threshold must be a number in [0, 1]\");\n }\n return { rubric, threshold, model: identifier(\"llm-rubric\", params, \"model\") };\n },\n async evaluate(delivery, params, ctx) {\n const score: unknown = await consult(\"llm-rubric\", \"grade\", () =>\n ctx.grade?.({ rubric: params.rubric, model: params.model, delivery: delivery.bytes }),\n );\n if (!isUnitScore(score)) {\n throw new PredicateEvaluationError(\n `llm-rubric: the buyer's grade returned ${String(score)}, not a score in [0, 1]`,\n );\n }\n return score >= params.threshold\n ? {\n decision: \"pass\",\n reason: `scored ${String(score)}, at least ${String(params.threshold)}`,\n }\n : { decision: \"fail\", reason: `scored ${String(score)}, below ${String(params.threshold)}` };\n },\n};\n\nexport const llmRubric: Predicate = predicate;\n","import {\n PredicateEvaluationError,\n PredicateParamsError,\n consult,\n identifier,\n optionalInteger,\n paramsObject,\n type Predicate,\n} from \"./core.js\";\n\ninterface PeriodSlaParams {\n metric: string;\n from: number;\n to: number;\n min: number;\n max: number;\n minSamples: number;\n minCompliance: number;\n}\n\nfunction optionalNumber(params: Record<string, unknown>, field: string): number | undefined {\n if (!Object.hasOwn(params, field)) return undefined;\n const value = params[field];\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new PredicateParamsError(`period-sla ${field} must be a finite number`);\n }\n return value;\n}\n\nfunction wholeNumber(params: Record<string, unknown>, field: string): number {\n const value = params[field];\n if (typeof value !== \"number\" || !Number.isSafeInteger(value)) {\n throw new PredicateParamsError(`period-sla ${field} must be whole unix seconds`);\n }\n return value;\n}\n\n// The measurement is the buyer's own monitor's, never anything the worker delivered.\nconst predicate: Predicate<PeriodSlaParams> = {\n name: \"period-sla\",\n parseParams(raw) {\n const params = paramsObject(\"period-sla\", raw, [\n \"metric\",\n \"from\",\n \"to\",\n \"min\",\n \"max\",\n \"minSamples\",\n \"minCompliance\",\n ]);\n const metric = identifier(\"period-sla\", params, \"metric\");\n const from = wholeNumber(params, \"from\");\n const to = wholeNumber(params, \"to\");\n if (from >= to) throw new PredicateParamsError(\"period-sla from must be before to\");\n const min = optionalNumber(params, \"min\");\n const max = optionalNumber(params, \"max\");\n if (min === undefined && max === undefined) {\n throw new PredicateParamsError(\"period-sla needs min, max or both\");\n }\n if (min !== undefined && max !== undefined && min > max) {\n throw new PredicateParamsError(\"period-sla min must not exceed max\");\n }\n const minSamples = optionalInteger(\"period-sla\", params, \"minSamples\", 1);\n if (minSamples === undefined) {\n throw new PredicateParamsError(\"period-sla minSamples is required\");\n }\n const minCompliance = optionalNumber(params, \"minCompliance\") ?? 1;\n if (minCompliance < 0 || minCompliance > 1) {\n throw new PredicateParamsError(\"period-sla minCompliance must be in [0, 1]\");\n }\n return {\n metric,\n from,\n to,\n min: min ?? Number.NEGATIVE_INFINITY,\n max: max ?? Number.POSITIVE_INFINITY,\n minSamples,\n minCompliance,\n };\n },\n async evaluate(_delivery, params, ctx) {\n const answer: unknown = await consult(\"period-sla\", \"samples\", () =>\n ctx.samples?.({ metric: params.metric, from: params.from, to: params.to }),\n );\n if (!Array.isArray(answer)) {\n throw new PredicateEvaluationError(\"period-sla: the buyer's samples returned no array\");\n }\n const values = answer as unknown[];\n for (const value of values) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new PredicateEvaluationError(\n `period-sla: the buyer's monitor returned the sample ${String(value)}, not a finite number`,\n );\n }\n }\n if (values.length < params.minSamples) {\n return {\n decision: \"fail\",\n reason: `${String(values.length)} sample(s); at least ${String(params.minSamples)} are needed`,\n };\n }\n const within = (values as number[]).filter((v) => v >= params.min && v <= params.max).length;\n const share = within / values.length;\n return share >= params.minCompliance\n ? {\n decision: \"pass\",\n reason: `${String(within)} of ${String(values.length)} samples within bounds`,\n }\n : {\n decision: \"fail\",\n reason: `${String(within)} of ${String(values.length)} samples within bounds; ${String(params.minCompliance)} required`,\n };\n },\n};\n\nexport const periodSla: Predicate = predicate;\n","import bs58 from \"bs58\";\nimport nacl from \"tweetnacl\";\nimport { PublicKey } from \"@solana/web3.js\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { PredicateParamsError, paramsObject, sha256Hex, type Predicate } from \"./core.js\";\n\ninterface PodReceiptParams {\n signer: Uint8Array;\n}\n\n// Both strings are bounded before any decode: base58 decoding is quadratic, so an unbounded\n// string from a worker or a server could hang the buyer until the 24 h auto-release pays.\nconst MIN_SIGNER = 32;\nconst MAX_SIGNER = 44;\nconst MAX_RECEIPT = 88;\n\nconst fail = (reason: string) => Promise.resolve({ decision: \"fail\" as const, reason });\n\nconst predicate: Predicate<PodReceiptParams> = {\n name: \"pod-receipt\",\n parseParams(raw) {\n const { signer } = paramsObject(\"pod-receipt\", raw, [\"signer\"]);\n if (typeof signer !== \"string\" || signer.length < MIN_SIGNER || signer.length > MAX_SIGNER) {\n throw new PredicateParamsError(\n `pod-receipt signer must be a base58 key of ${String(MIN_SIGNER)} to ${String(MAX_SIGNER)} characters`,\n );\n }\n if (!isCanonicalPubkey(signer)) {\n throw new PredicateParamsError(\"pod-receipt signer is not a canonical base58 ed25519 key\");\n }\n return { signer: new PublicKey(signer).toBytes() };\n },\n evaluate(delivery, params) {\n const { receipt } = delivery;\n if (typeof receipt !== \"string\") return fail(\"the delivery carries no receipt\");\n if (receipt.length > MAX_RECEIPT) {\n return fail(\n `the receipt is ${String(receipt.length)} characters; a signature is at most ${String(MAX_RECEIPT)}`,\n );\n }\n const signature = bs58.decodeUnsafe(receipt);\n if (signature?.length !== nacl.sign.signatureLength) {\n return fail(\"the receipt is not a base58 ed25519 signature\");\n }\n const message = Buffer.from(`escro:pod:${sha256Hex(delivery.bytes)}`, \"utf8\");\n return nacl.sign.detached.verify(message, signature, params.signer)\n ? Promise.resolve({ decision: \"pass\", reason: \"the signer's receipt covers this delivery\" })\n : fail(\"the receipt is not the signer's over this delivery's hash\");\n },\n};\n\nexport const podReceipt: Predicate = predicate;\n","import {\n PredicateEvaluationError,\n consult,\n identifier,\n optionalInteger,\n paramsObject,\n type Predicate,\n} from \"./core.js\";\n\ninterface TestsPassParams {\n suite: string;\n minPassed: number;\n}\n\nfunction count(answer: unknown, field: \"passed\" | \"failed\"): number {\n const value =\n typeof answer === \"object\" && answer !== null\n ? (answer as Record<string, unknown>)[field]\n : undefined;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new PredicateEvaluationError(\n `tests-pass: the buyer's runTests returned ${field} ${String(value)}, not a non-negative whole number`,\n );\n }\n return value;\n}\n\nconst predicate: Predicate<TestsPassParams> = {\n name: \"tests-pass\",\n parseParams(raw) {\n const params = paramsObject(\"tests-pass\", raw, [\"suite\", \"minPassed\"]);\n return {\n suite: identifier(\"tests-pass\", params, \"suite\"),\n minPassed: optionalInteger(\"tests-pass\", params, \"minPassed\", 1) ?? 1,\n };\n },\n async evaluate(delivery, params, ctx) {\n const answer: unknown = await consult(\"tests-pass\", \"runTests\", () =>\n ctx.runTests?.({ suite: params.suite, delivery: delivery.bytes }),\n );\n const passed = count(answer, \"passed\");\n const failed = count(answer, \"failed\");\n if (failed > 0) {\n return { decision: \"fail\", reason: `${String(failed)} test(s) of ${params.suite} failed` };\n }\n if (passed < params.minPassed) {\n return {\n decision: \"fail\",\n reason: `${String(passed)} test(s) of ${params.suite} passed; at least ${String(params.minPassed)} must`,\n };\n }\n return {\n decision: \"pass\",\n reason: `${String(passed)} test(s) of ${params.suite} passed, none failed`,\n };\n },\n};\n\nexport const testsPass: Predicate = predicate;\n","import { getCaip2Network, type Acceptance, type SolanaCluster } from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { resolveProgramId } from \"../solana.js\";\n\nimport { attestationValid } from \"./attestation-valid.js\";\nimport { ciCheck } from \"./ci-check.js\";\nimport {\n PredicateParamsError,\n PredicateRecordError,\n isSha256Hex,\n jcs,\n paramsHash,\n sha256Hex,\n type DecisionJob,\n type DecisionRecord,\n type Delivery,\n type Predicate,\n type PredicateContext,\n type PredicateName,\n} from \"./core.js\";\nimport { fileFormat } from \"./file-format.js\";\nimport { hashMatches } from \"./hash.js\";\nimport { jsonSchema } from \"./json-schema.js\";\nimport { llmRubric } from \"./llm-rubric.js\";\nimport { periodSla } from \"./period-sla.js\";\nimport { podReceipt } from \"./pod-receipt.js\";\nimport { testsPass } from \"./tests-pass.js\";\n\nexport {\n PredicateEvaluationError,\n PredicateParamsError,\n PredicateRecordError,\n jcs,\n paramsHash,\n} from \"./core.js\";\nexport type {\n DecisionJob,\n DecisionRecord,\n Delivery,\n Predicate,\n PredicateContext,\n PredicateName,\n PredicateOutcome,\n} from \"./core.js\";\nexport type { Acceptance } from \"@escro/shared\";\nexport {\n attestationValid,\n ciCheck,\n fileFormat,\n hashMatches,\n jsonSchema,\n llmRubric,\n periodSla,\n podReceipt,\n testsPass,\n};\n\n/** The `escro` extension's predicate catalogue (docs/specs/escro-extension.md \"Predicate catalogue\"). */\nexport const PREDICATES: Readonly<Record<PredicateName, Predicate>> = Object.freeze({\n \"hash-matches\": hashMatches,\n \"tests-pass\": testsPass,\n \"json-schema\": jsonSchema,\n \"file-format\": fileFormat,\n \"pod-receipt\": podReceipt,\n \"llm-rubric\": llmRubric,\n \"ci-check\": ciCheck,\n \"period-sla\": periodSla,\n \"attestation-valid\": attestationValid,\n});\n\nexport interface PredicateCheck {\n acceptance: Acceptance;\n params: unknown;\n /** The job the record decides; build it with {@link predicateJob}. */\n job: DecisionJob;\n}\n\nexport interface PredicateResult {\n record: DecisionRecord;\n memo: string;\n reason: string;\n}\n\nconst NAME = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst MAX_NAME = 64;\n\nfunction plainMembers(value: unknown, what: string): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new PredicateRecordError(`${what} must be an object`);\n }\n return value as Record<string, unknown>;\n}\n\n// An own member whose value is undefined is refused, never dropped: `canonicalize` would hash it\n// as absent.\nfunction checkMembers(\n value: Record<string, unknown>,\n what: string,\n required: readonly string[],\n optional: readonly string[] = [],\n): void {\n for (const key of Object.keys(value)) {\n if (!required.includes(key) && !optional.includes(key)) {\n throw new PredicateRecordError(`${what} has an unexpected member ${key}`);\n }\n if (value[key] === undefined) throw new PredicateRecordError(`${what}.${key} is undefined`);\n }\n for (const key of required) {\n if (!Object.hasOwn(value, key)) throw new PredicateRecordError(`${what} lacks ${key}`);\n }\n}\n\n/** Refuses an `acceptance` the extension's schema (`$defs.acceptance`) refuses. */\nfunction checkAcceptance(value: unknown): Acceptance {\n const acceptance = plainMembers(value, \"acceptance\");\n checkMembers(acceptance, \"acceptance\", [\"name\", \"paramsHash\"], [\"fixtureHashes\"]);\n const { name, fixtureHashes } = acceptance;\n if (typeof name !== \"string\" || name.length > MAX_NAME || !NAME.test(name)) {\n throw new PredicateRecordError(\n `acceptance.name must be at most ${String(MAX_NAME)} lowercase words joined by hyphens`,\n );\n }\n if (!isSha256Hex(acceptance.paramsHash)) {\n throw new PredicateRecordError(\"acceptance.paramsHash must be 64 lowercase hex characters\");\n }\n if (Object.hasOwn(acceptance, \"fixtureHashes\")) {\n if (!Array.isArray(fixtureHashes) || !fixtureHashes.every(isSha256Hex)) {\n throw new PredicateRecordError(\n \"acceptance.fixtureHashes must be an array of 64-character lowercase hex hashes\",\n );\n }\n if (new Set(fixtureHashes).size !== fixtureHashes.length) {\n throw new PredicateRecordError(\"acceptance.fixtureHashes holds a duplicate\");\n }\n }\n return acceptance as unknown as Acceptance;\n}\n\nconst JOB_MEMBERS = [\"network\", \"program\", \"id\"] as const;\nconst SOLANA_NETWORK = /^solana:[1-9A-HJ-NP-Za-km-z]{32}$/;\nconst EIP155_NETWORK = /^eip155:[1-9][0-9]{0,31}$/;\nconst EVM_ADDRESS = /^0x[0-9a-f]{40}$/;\nconst EVM_JOB_ID = /^(0|[1-9][0-9]{0,77})$/;\n\n/**\n * Refuses a `job` the extension's schema (`$defs.job`) refuses, and on Solana a `program` or `id`\n * that is not a canonical base58 key of 32 bytes (the decode the schema states in words). Returns a\n * fresh copy holding exactly the three members.\n */\nfunction checkJob(value: unknown, what: string): DecisionJob {\n const job = plainMembers(value, what);\n checkMembers(job, what, JOB_MEMBERS);\n for (const member of JOB_MEMBERS) {\n if (typeof job[member] !== \"string\") {\n throw new PredicateRecordError(`${what}.${member} must be a string`);\n }\n }\n const { network, program, id } = job as unknown as DecisionJob;\n if (SOLANA_NETWORK.test(network)) {\n if (!isCanonicalPubkey(program)) {\n throw new PredicateRecordError(\n `${what}.program must be a canonical base58 key of 32 bytes on a solana network`,\n );\n }\n if (!isCanonicalPubkey(id)) {\n throw new PredicateRecordError(\n `${what}.id must be the escrow's canonical base58 address of 32 bytes on a solana network`,\n );\n }\n } else if (EIP155_NETWORK.test(network)) {\n if (!EVM_ADDRESS.test(program)) {\n throw new PredicateRecordError(\n `${what}.program must be 0x and 40 lowercase hex characters on an eip155 network`,\n );\n }\n if (!EVM_JOB_ID.test(id)) {\n throw new PredicateRecordError(\n `${what}.id must be the jobId in decimal, with no leading zero, on an eip155 network`,\n );\n }\n } else {\n throw new PredicateRecordError(\n `${what}.network must be solana:<32 base58 characters> or eip155:<decimal chain id>`,\n );\n }\n return { network, program, id };\n}\n\n/**\n * The job a record decides on Solana: this cluster's CAIP-2 network and Escro program, and the\n * escrow's address. Throws {@link PredicateRecordError} when `address` is not a canonical base58\n * key of 32 bytes.\n */\nexport function predicateJob(cluster: SolanaCluster, address: string): DecisionJob {\n if (typeof address !== \"string\" || !isCanonicalPubkey(address)) {\n throw new PredicateRecordError(\n \"job.id must be the escrow's address, a canonical base58 key of 32 bytes\",\n );\n }\n return {\n network: getCaip2Network(cluster),\n program: resolveProgramId(cluster).toBase58(),\n id: address,\n };\n}\n\n/** Refuses a record the extension's schema (`$defs.decisionRecord`) refuses. */\nfunction checkRecord(value: unknown): DecisionRecord {\n const record = plainMembers(value, \"the decision record\");\n checkMembers(record, \"the decision record\", [\"acceptance\", \"decision\", \"deliverableHash\", \"job\"]);\n checkAcceptance(record.acceptance);\n if (record.decision !== \"pass\" && record.decision !== \"fail\") {\n throw new PredicateRecordError(\"the decision record's decision must be pass or fail\");\n }\n if (!isSha256Hex(record.deliverableHash)) {\n throw new PredicateRecordError(\n \"the decision record's deliverableHash must be 64 lowercase hex characters\",\n );\n }\n checkJob(record.job, \"the decision record's job\");\n return record as unknown as DecisionRecord;\n}\n\n/** The SHA-256 hex of the UTF-8 {@link jcs} of a valid decision record. */\nexport function decisionRecordHash(record: DecisionRecord): string {\n return sha256Hex(Buffer.from(jcs(checkRecord(record)), \"utf8\"));\n}\n\n/** `escro:predicate:<name>:<pass|fail>:<decisionRecordHash>`. Throws {@link PredicateRecordError}. */\nexport function predicateMemo(record: DecisionRecord): string {\n const hash = decisionRecordHash(record);\n return `escro:predicate:${record.acceptance.name}:${record.decision}:${hash}`;\n}\n\n/**\n * Applies one advertised check to a delivery, in the buyer's process: refuses an `acceptance` the\n * extension refuses, a `job` the extension refuses, a name this library does not implement, params\n * the predicate refuses, and params that do not hash to `acceptance.paramsHash`, all before the\n * predicate runs; then returns the one decision record, naming `check.job`, its memo and the\n * predicate's reason. Throws {@link PredicateEvaluationError} when the buyer's evaluator reaches\n * no decision.\n */\nexport async function runPredicate(\n check: PredicateCheck,\n delivery: Delivery,\n ctx: PredicateContext = {},\n): Promise<PredicateResult> {\n const acceptance = checkAcceptance(check.acceptance);\n const job = checkJob(check.job, \"check.job\");\n if (!Object.hasOwn(PREDICATES, acceptance.name)) {\n throw new PredicateRecordError(\n `no predicate named ${acceptance.name} is implemented; skip this acceptance`,\n );\n }\n const predicate = PREDICATES[acceptance.name as PredicateName];\n const params = predicate.parseParams(check.params);\n const advertised = paramsHash(check.params);\n if (advertised !== acceptance.paramsHash) {\n throw new PredicateParamsError(\n `the params hash to ${advertised}, not the advertised paramsHash ${acceptance.paramsHash}`,\n );\n }\n const deliverableHash = sha256Hex(delivery.bytes);\n const { decision, reason } = await predicate.evaluate(delivery, params, ctx);\n const record: DecisionRecord = {\n acceptance: {\n name: acceptance.name,\n paramsHash: acceptance.paramsHash,\n ...(acceptance.fixtureHashes === undefined\n ? {}\n : { fixtureHashes: [...acceptance.fixtureHashes] }),\n },\n decision,\n deliverableHash,\n job,\n };\n return { record, memo: predicateMemo(record), reason };\n}\n","import type { TaskSpec } from \"@escro/shared\";\n\nimport type { SubmitDeliverableParams } from \"./types.js\";\n\n/**\n * The result a {@link ServiceAdapter} returns from `execute`. Escro is agnostic\n * to what produced it: `content` is the deliverable itself, `contentHash` is the\n * SHA-256 hex digest the Buyer verifies the deliverable against, and `proofUri`\n * optionally points at where the content is pinned (IPFS/Arweave) or at a proof.\n * No currency or token field appears here; token conversion is adapter-internal,\n * since the escrow vault holds USDC only.\n */\nexport interface ServiceResult {\n /** The deliverable itself. */\n content: string | Buffer;\n /** SHA-256 hex digest of {@link ServiceResult.content}. */\n contentHash: string;\n /** Content-addressed URI (ipfs://, ar://) or proof URI for the deliverable. */\n proofUri?: string;\n /** Arbitrary adapter-specific metadata (model, timings, subnet ids, ...). */\n metadata: Record<string, unknown>;\n}\n\n/**\n * A Worker Bot implements ServiceAdapter to wrap any async service (a Bittensor\n * subnet, an Akash deployment, a Render job, ...). Escro never sees what is\n * underneath and never sees a non-USDC token: the adapter handles any token\n * conversion internally. Every pre-built adapter reuses\n * this interface and is validated by `assertServiceAdapterContract`.\n */\nexport interface ServiceAdapter {\n /** Stable identifier, e.g. \"bittensor:sn56\", \"akash\", \"render\". */\n id: string;\n /** Advertised capabilities, e.g. [\"llm_inference\", \"image_gen\"]. */\n capabilities: string[];\n /** Execute the task described by `spec` and return the deliverable. */\n execute(spec: TaskSpec): Promise<ServiceResult>;\n /** Report whether the underlying service is reachable and ready. */\n healthCheck(): Promise<boolean>;\n}\n\n/**\n * The buyer's port that fetches the bytes a `proofUri` names (an IPFS or Arweave gateway,\n * a storage bucket). A throw or rejection is an infrastructure failure that propagates to\n * the caller, which retries it; it is never a verdict on the deliverable.\n */\nexport type ResolveProofUri = (proofUri: string) => Promise<string | Buffer> | string | Buffer;\n\n/**\n * Map a {@link ServiceResult} onto {@link SubmitDeliverableParams}, surfacing the\n * `contentHash` (and `proofUri`, when present) that `submit_deliverable` records.\n * This is the single point where an adapter's output crosses into the escrow\n * worker flow.\n */\nexport function serviceResultToSubmitParams(result: ServiceResult): SubmitDeliverableParams {\n return {\n contentHash: result.contentHash,\n ...(result.proofUri !== undefined && { proofUri: result.proofUri }),\n };\n}\n","import { createHash } from \"crypto\";\n\nimport { proofUriError, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"./adapter.js\";\nimport { EscroError } from \"./errors.js\";\n\n/** Options controlling {@link assertServiceAdapterContract}. */\nexport interface AdapterContractOptions {\n /**\n * A representative TaskSpec the adapter can execute. The harness calls\n * `execute(sampleSpec)` and validates the returned ServiceResult, so the spec\n * should be one the adapter genuinely handles.\n */\n sampleSpec: TaskSpec;\n}\n\n/** Thrown by {@link assertServiceAdapterContract}, listing every contract violation. */\nexport class AdapterContractError extends EscroError {\n constructor(\n adapterId: string,\n public readonly violations: string[],\n ) {\n super(\n `ServiceAdapter \"${adapterId}\" violates the adapter contract:\\n- ${violations.join(\"\\n- \")}`,\n \"ADAPTER_CONTRACT_VIOLATION\",\n );\n this.name = \"AdapterContractError\";\n }\n}\n\nfunction errMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/** Validate the shape and hash integrity of a value returned by `execute`. */\nfunction validateServiceResult(result: unknown): string[] {\n if (typeof result !== \"object\" || result === null) {\n return [\"`execute()` must resolve to a ServiceResult object\"];\n }\n const violations: string[] = [];\n const r = result as {\n content?: unknown;\n contentHash?: unknown;\n proofUri?: unknown;\n metadata?: unknown;\n };\n\n const contentIsValid = typeof r.content === \"string\" || Buffer.isBuffer(r.content);\n if (!contentIsValid) {\n violations.push(\"`content` must be a string or Buffer\");\n }\n\n if (typeof r.contentHash !== \"string\" || r.contentHash.trim() === \"\") {\n violations.push(\"`contentHash` must be a non-empty string\");\n } else if (contentIsValid && r.contentHash !== sha256Hex(r.content as string | Buffer)) {\n violations.push(\"`contentHash` must equal the SHA-256 hex digest of `content`\");\n }\n\n if (r.proofUri !== undefined && typeof r.proofUri !== \"string\") {\n violations.push(\"`proofUri`, when present, must be a string\");\n } else if (typeof r.proofUri === \"string\") {\n const error = proofUriError(r.proofUri);\n if (error !== null) {\n violations.push(`\\`proofUri\\` cannot be submitted: ${error}`);\n }\n }\n\n if (typeof r.metadata !== \"object\" || r.metadata === null || Array.isArray(r.metadata)) {\n violations.push(\"`metadata` must be a plain object\");\n }\n\n return violations;\n}\n\n/**\n * Assert that `adapter` satisfies the ServiceAdapter contract. Resolves with the\n * ServiceResult produced by `execute(sampleSpec)` when the adapter conforms;\n * rejects with an {@link AdapterContractError} listing every violation otherwise.\n *\n * Reusable across adapters (the Bittensor subnets, the compute networks, the proof\n * adapters): a conforming adapter passes, a malformed one fails. The parameter is\n * typed `ServiceAdapter`, but the harness validates at runtime: JS callers and\n * `as`-cast objects reach this too, so every field is checked defensively.\n */\nexport async function assertServiceAdapterContract(\n adapter: ServiceAdapter,\n options: AdapterContractOptions,\n): Promise<ServiceResult> {\n const a = adapter as {\n id?: unknown;\n capabilities?: unknown;\n execute?: unknown;\n healthCheck?: unknown;\n };\n const violations: string[] = [];\n const id = typeof a.id === \"string\" && a.id.trim() !== \"\" ? a.id : \"(unknown)\";\n\n if (typeof a.id !== \"string\" || a.id.trim() === \"\") {\n violations.push(\"`id` must be a non-empty string\");\n }\n // capabilities must be non-empty so the adapter is discoverable in EscroBots.\n if (\n !Array.isArray(a.capabilities) ||\n a.capabilities.length === 0 ||\n (a.capabilities as unknown[]).some((c) => typeof c !== \"string\" || c.trim() === \"\")\n ) {\n violations.push(\"`capabilities` must be a non-empty array of non-empty strings\");\n }\n if (typeof a.healthCheck !== \"function\") {\n violations.push(\"`healthCheck` must be a function\");\n }\n if (typeof a.execute !== \"function\") {\n violations.push(\"`execute` must be a function\");\n }\n\n if (typeof a.healthCheck === \"function\") {\n try {\n const healthy = await (a.healthCheck as () => Promise<unknown>)();\n if (typeof healthy !== \"boolean\") {\n violations.push(\"`healthCheck()` must resolve to a boolean\");\n }\n } catch (err) {\n violations.push(`\\`healthCheck()\\` threw: ${errMessage(err)}`);\n }\n }\n\n let result: ServiceResult | undefined;\n if (typeof a.execute === \"function\") {\n try {\n result = await (a.execute as (spec: TaskSpec) => Promise<ServiceResult>)(options.sampleSpec);\n violations.push(...validateServiceResult(result));\n } catch (err) {\n violations.push(`\\`execute()\\` threw: ${errMessage(err)}`);\n result = undefined;\n }\n }\n\n if (violations.length > 0 || result === undefined) {\n throw new AdapterContractError(\n id,\n violations.length > 0 ? violations : [\"`execute()` produced no result\"],\n );\n }\n return result;\n}\n","/**\n * Shared Bittensor-subnet ServiceAdapter core. SN56 (gradients), SN17 (404gen) and\n * SN51 (lium) are three Bittensor-shaped adapters that swap a per-task USDC budget\n * into TAO internally, pay subnet miners in TAO, collect a deliverable, and return a\n * currency-free `ServiceResult`. This module owns what they share: the branded `Tao`\n * type (which exists ONLY in the adapter layer and can never reach a `ServiceResult`\n * or the escrow submit path, a compile-time guarantee),\n * the USDC->TAO swap / subnet-call / pin ports, the shared default ports, and the\n * `execute` skeleton. Each adapter supplies its own subnet id, capabilities, budget,\n * demo logic and default-port wiring, then delegates `execute` to\n * {@link createBittensorSubnetAdapter}. Ridges (USD-billed, no TAO) is deliberately\n * NOT part of this core.\n */\nimport { createHash } from \"crypto\";\n\nimport type { TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in TAO (Bittensor's token). Branded so it cannot be assigned to\n * or from a plain `number` by accident and (the point of the brand) so it can never\n * appear in a `ServiceResult` or the escrow submit path: those types have no field of\n * this type. TAO exists ONLY inside the Bittensor adapter layer.\n */\nexport type Tao = number & { readonly __brand: \"TAO\" };\n\n/** Construct a {@link Tao} amount from a plain number. Adapter-internal use only. */\nexport function tao(amount: number): Tao {\n return amount as Tao;\n}\n\n/** Swap a microUSDC budget into TAO. Real workers route this through a DEX (e.g. Jupiter). */\nexport type UsdcToTaoSwap = (microUsdc: number) => Promise<Tao>;\n\n/**\n * Pay subnet miners `budget` TAO to run `spec`; resolve with the raw deliverable. The\n * single shared port shape across every Bittensor adapter (a GPU-rental call is a paid\n * subnet call too; lium re-exports this as `RunGpuJob`).\n */\nexport type SubnetCall = (spec: TaskSpec, budget: Tao) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** SHA-256 hex digest of a deliverable. */\nexport function sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// Nominal reference rate: microUSDC -> TAO. Only the stub swap cares about the exact value.\nexport const REFERENCE_MICRO_USDC_PER_TAO = 300_000_000;\n\n/** Default fixed-rate reference swap, shared by every reference Bittensor adapter. */\nexport const defaultSwap: UsdcToTaoSwap = (microUsdc) =>\n Promise.resolve(tao(microUsdc / REFERENCE_MICRO_USDC_PER_TAO));\n\n/** Default deterministic `ipfs://` placeholder pin, shared by every reference adapter. */\nexport const defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/** Fully-resolved ports and identity for {@link createBittensorSubnetAdapter}. */\nexport interface BittensorSubnetAdapterConfig {\n /** Subnet identifier (e.g. \"sn56\"); forms the adapter id `bittensor:<subnet>`. */\n subnet: string;\n /** Advertised capabilities for EscroBots discovery. */\n capabilities: string[];\n /** microUSDC allocated to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc: number;\n /** USDC->TAO swap port. */\n swap: UsdcToTaoSwap;\n /** Subnet-call port (pays the subnet in TAO and returns the deliverable). */\n callSubnet: SubnetCall;\n /** Pinning port. */\n pin: PinContent;\n /** Health-check port. */\n checkHealth: () => Promise<boolean>;\n}\n\n/**\n * Build a Bittensor-subnet {@link ServiceAdapter} from fully-resolved ports. The\n * execute skeleton: swap the USDC budget into TAO (internal, never surfaced), pay the\n * subnet in TAO and collect the deliverable, then hash and pin. The recorded\n * `ServiceResult` is currency-free (no TAO field). Every reference TAO adapter resolves\n * its own defaults and delegates here.\n */\nexport function createBittensorSubnetAdapter(config: BittensorSubnetAdapterConfig): ServiceAdapter {\n const id = `bittensor:${config.subnet}`;\n return {\n id,\n capabilities: config.capabilities,\n healthCheck: config.checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into TAO (internal, never surfaced).\n const budgetTao = await config.swap(config.taskBudgetMicroUsdc);\n // 2. Pay subnet miners in TAO and collect the deliverable.\n const content = await config.callSubnet(spec, budgetTao);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await config.pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: id, subnet: config.subnet },\n };\n },\n };\n}\n","/**\n * Gradients (Bittensor SN56) ServiceAdapter: the first SHIPPED, supported adapter\n * (the reference pattern the other subnet adapters replicate). A Worker Bot wraps the Gradients\n * fine-tuning subnet behind the `ServiceAdapter` interface: it swaps a per-task\n * USDC budget into TAO internally, pays subnet miners in TAO to fine-tune, collects\n * a checkpoint + eval deliverable, and returns a currency-free `ServiceResult`. The\n * Buyer and the escrow contract only ever see USDC; no TAO-typed value crosses this\n * boundary into SDK core (the branded `Tao` type of ../bittensor/index.ts keeps it out\n * at compile time for the Bittensor trio).\n *\n * The swap, subnet call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN56 dendrite, Pinata/Arweave).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (checkpoint\n * + eval JSON). Whether the eval clears the threshold is decided by the BUYER's\n * review.ts, which independently recomputes the score (see `scoreGradientsDemoDeliverable`).\n * The worker never scores-for-release and never releases: the buyer is the judge.\n *\n * Relationship to `examples/worker-bot/bittensor-adapter.ts`: that example is\n * pedagogy (\"author your own adapter against the public interface\", driven by e2e\n * scenario 13); THIS module is the shipped, importable\n * surface a generated bot uses. The USDC->TAO port skeleton and the execute shape are\n * shared with the other Bittensor adapters via `../bittensor/index.js`; this module\n * supplies only its subnet identity, capabilities, budget, and demo logic.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Configuration and injectable ports for {@link createGradientsAdapter}. */\nexport interface GradientsAdapterConfig {\n /** Subnet identifier. Defaults to \"sn56\" (Gradients); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"fine-tune\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n callSubnet?: SubnetCall;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** Stable id/capabilities, LOCKED against `ADAPTER_DESCRIPTORS.gradients` by a kit test. */\nexport const GRADIENTS_ADAPTER_ID = \"bittensor:sn56\";\nexport const GRADIENTS_CAPABILITIES = [\"fine-tune\"] as const;\n\nconst DEFAULT_SUBNET = \"sn56\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 5_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a deterministic fine-tune the buyer\n// template's 5-minute journey hires this bot for. The \"model\" learns the fixed\n// affine map y = 2x + 1 on a fixed dataset; the deliverable is the model's\n// predictions on that dataset. Acceptance is machine-checkable and recomputed by\n// the BUYER (see scoreGradientsDemoDeliverable); the worker's self-reported eval\n// score is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */\nexport const GRADIENTS_DEMO_MARKER = \"gradients-sn56-demo-v1\";\n\n/** The demo eval floor: predictions must be at least this accurate to be accepted. */\nexport const GRADIENTS_DEMO_EVAL_FLOOR = 0.8;\n\n/** The demo's fixed inputs. The reference target maps each `x` to `2x + 1`. */\nconst DEMO_DATASET: readonly number[] = [3, 7, 11, 15, 19];\n\nfunction demoExpectedOutputs(): number[] {\n return DEMO_DATASET.map((x) => 2 * x + 1);\n}\n\n/**\n * The canned Gradients demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const gradientsDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no fine-tune category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Fine-tune the reference model on the canned SN56 demo dataset and return its \" +\n \"predictions on the same inputs. The target map is y = 2x + 1. Acceptance is \" +\n \"deterministic and recomputed by the buyer: prediction accuracy must be >= 0.8; \" +\n \"the worker's self-reported eval score is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-eval-floor\",\n description:\n \"Prediction accuracy on the demo dataset is >= 0.8, recomputed by the buyer from the deliverable.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GRADIENTS_DEMO_MARKER,\n dataset: [...DEMO_DATASET],\n target: \"y = 2x + 1\",\n evalFloor: GRADIENTS_DEMO_EVAL_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the correct predictions plus a\n * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.\n * Exposed so the demo journey and tests share one source of the expected artifact.\n */\nexport function solveGradientsDemo(): string {\n const predictions = demoExpectedOutputs();\n return canonicalize({\n checkpoint: \"reference-sn56-demo-checkpoint\",\n eval: { metric: \"accuracy\", score: 1 },\n predictions,\n });\n}\n\ninterface DemoDeliverable {\n predictions: number[];\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const predictions = (parsed as { predictions?: unknown }).predictions;\n if (!Array.isArray(predictions) || predictions.some((p) => typeof p !== \"number\")) {\n return null;\n }\n return { predictions: predictions as number[] };\n}\n\n/**\n * The BUYER's independent recompute of the demo eval score in [0, 1]. Reads the\n * substantive output (the predictions) and compares it to the target map the buyer\n * itself defines; it deliberately IGNORES any self-reported `eval.score` in the\n * deliverable, so release can never be worker-controlled. Malformed\n * or unparseable content scores 0 and never throws.\n */\nexport function scoreGradientsDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n const expected = demoExpectedOutputs();\n let matches = 0;\n for (let i = 0; i < expected.length; i++) {\n if (parsed.predictions[i] === expected[i]) {\n matches++;\n }\n }\n return matches / expected.length;\n}\n\n// A generic (non-demo) fine-tune produces a placeholder checkpoint+eval so a fresh\n// worker returns a well-formed ServiceResult before a real SN56 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n checkpoint: \"reference-sn56-checkpoint\",\n eval: { metric: \"accuracy\", score: 0 },\n note: \"reference stub - replace the callSubnet port with a real SN56 miner call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultCallSubnet: SubnetCall = (spec) =>\n Promise.resolve(\n spec.metadata.demo === GRADIENTS_DEMO_MARKER\n ? solveGradientsDemo()\n : referencePlaceholder(spec),\n );\n\n/**\n * Build a Gradients (SN56) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core.\n */\nexport function createGradientsAdapter(config: GradientsAdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...GRADIENTS_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.callSubnet ?? defaultCallSubnet,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Ridges (AI coding agents) ServiceAdapter: a SHIPPED, supported reference adapter\n * built on the same pattern as the Gradients SN56 adapter. A Worker Bot\n * wraps a Ridges coding agent behind the `ServiceAdapter` interface: given a coding\n * task, it runs the agent to produce a solution, runs the task's test suite, and\n * returns a test report as the `ServiceResult` deliverable. The Buyer and the escrow\n * contract only ever see USDC.\n *\n * Unlike the Bittensor adapters (gradients SN56, 404gen SN17, lium SN51), Ridges is\n * billed in USD through its platform API, so there is no in-adapter token conversion\n * and no TAO-typed value to keep out of SDK core: `serviceRef` is a bare `\"ridges\"`,\n * not `bittensor:<subnet>` (kit `ADAPTER_DESCRIPTORS.ridges`). The worker still fronts\n * the service cost and is reimbursed in USDC at release (see README float profile).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (a test\n * report). Whether the suite passed and coverage cleared the target is decided by the\n * BUYER's review.ts, which independently recomputes the outcome from the delivered\n * test outputs (see `scoreRidgesDemoDeliverable`). The worker never scores-for-release\n * and never releases, and its self-reported pass/coverage is never trusted: the\n * buyer is the judge.\n *\n * The coding-agent call and pinning are injectable ports so the reference runs (and is\n * tested) without a live Ridges endpoint or IPFS node. A production worker supplies\n * real implementations (the Ridges platform API for `runAgent`, Pinata/Arweave for\n * `pin`). The port pattern mirrors the gradients adapter deliberately. Ridges is\n * USD-billed with no TAO, so it deliberately does not use the shared `adapters/bittensor`\n * core (that core covers only the Bittensor trio: SN56, SN17, SN51).\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/** Run the coding agent for `spec`; resolve with the raw deliverable (a test report). */\nexport type RunCodingAgent = (spec: TaskSpec) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** Configuration and injectable ports for {@link createRidgesAdapter}. */\nexport interface RidgesAdapterConfig {\n /** Service identifier. Defaults to \"ridges\"; forms the adapter id. */\n service?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"code-generation\"]`. */\n capabilities?: string[];\n /** Coding-agent port. Default: solves the canned demo kata; a placeholder otherwise. */\n runAgent?: RunCodingAgent;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/**\n * Stable id/capabilities. Locked against `ADAPTER_DESCRIPTORS.ridges` by a kit test\n * (the lock lives in create-escro-bot, which depends on this package).\n */\nexport const RIDGES_ADAPTER_ID = \"ridges\";\nexport const RIDGES_CAPABILITIES = [\"code-generation\"] as const;\n\nconst DEFAULT_SERVICE = \"ridges\";\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ---------------------------------------------------------------------------\n// Canned demo kata: a deterministic coding job the buyer\n// template's 5-minute journey hires this bot for. The kata is a fixed FizzBuzz\n// repo: implement FizzBuzz and make its test battery pass. The deliverable is the\n// solution's test report (each battery input and the output the solution produced).\n// Acceptance is machine-checkable and recomputed by the BUYER (see\n// scoreRidgesDemoDeliverable): every delivered test must pass (exit 0) AND coverage\n// of the battery must clear the target. The worker's self-report is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default agent stub recognizes it. */\nexport const RIDGES_DEMO_MARKER = \"ridges-demo-v1\";\n\n/** The demo coverage target: the fraction of the test battery that must be covered. */\nexport const RIDGES_DEMO_COVERAGE_TARGET = 0.8;\n\n/**\n * The demo's fixed test battery: FizzBuzz over these inputs, chosen to exercise every\n * branch (plain number, Fizz, Buzz, FizzBuzz).\n */\nconst DEMO_INPUTS: readonly number[] = [1, 2, 3, 5, 15];\n\n/** The kata's reference logic; the buyer recomputes expected outputs from this. */\nfunction fizzbuzz(n: number): string {\n if (n % 15 === 0) return \"FizzBuzz\";\n if (n % 3 === 0) return \"Fizz\";\n if (n % 5 === 0) return \"Buzz\";\n return String(n);\n}\n\n/**\n * The canned Ridges demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const ridgesDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"code_generation\",\n description:\n \"Implement FizzBuzz for the fixed demo battery and return a test report: for each \" +\n \"battery input, the output your implementation produced. Acceptance is deterministic \" +\n \"and recomputed by the buyer: every delivered test must pass (exit 0) and coverage of \" +\n \"the battery must be >= 0.8; the worker's self-reported pass/coverage is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-tests-pass\",\n description:\n \"Every delivered test passes (exit 0), recomputed by the buyer from the test report.\",\n required: true,\n },\n {\n id: \"ac-coverage\",\n description: \"Coverage of the demo battery is >= 0.8, recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: RIDGES_DEMO_MARKER,\n kata: \"fizzbuzz\",\n inputs: [...DEMO_INPUTS],\n coverageTarget: RIDGES_DEMO_COVERAGE_TARGET,\n },\n};\n\n/** The reference source solution, carried in the deliverable for human readers only. */\nconst REFERENCE_SOLUTION =\n \"export function fizzbuzz(n: number): string {\\n\" +\n ' if (n % 15 === 0) return \"FizzBuzz\";\\n' +\n ' if (n % 3 === 0) return \"Fizz\";\\n' +\n ' if (n % 5 === 0) return \"Buzz\";\\n' +\n \" return String(n);\\n\" +\n \"}\\n\";\n\n/**\n * The reference solution to the demo kata: a passing test report over the full\n * battery, plus a (self-reported, buyer-ignored) pass/coverage block, as canonical\n * JSON. Deterministic. Exposed so the demo journey and tests share one source of the\n * expected artifact.\n */\nexport function solveRidgesDemo(): string {\n const tests = DEMO_INPUTS.map((input) => ({ input, output: fizzbuzz(input) }));\n return canonicalize({\n language: \"typescript\",\n solution: REFERENCE_SOLUTION,\n coverage: 1,\n passed: true,\n tests,\n });\n}\n\ninterface DemoTestResult {\n input: number;\n output: string;\n}\n\nfunction parseTestReport(content: string | Buffer): DemoTestResult[] | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const tests = (parsed as { tests?: unknown }).tests;\n if (!Array.isArray(tests)) {\n return null;\n }\n const results: DemoTestResult[] = [];\n for (const t of tests) {\n if (typeof t !== \"object\" || t === null) {\n return null;\n }\n const { input, output } = t as { input?: unknown; output?: unknown };\n if (typeof input !== \"number\" || typeof output !== \"string\") {\n return null;\n }\n results.push({ input, output });\n }\n return results;\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance, as a score in [0, 1].\n * It reads the substantive output (the delivered test outputs) and recomputes the\n * expected FizzBuzz result for each; it deliberately IGNORES any self-reported\n * pass/coverage in the deliverable, so release can never be worker-controlled.\n * Semantics:\n * - Any delivered test whose output is wrong = the suite did not pass (exit != 0):\n * score 0, no matter how much of the battery is covered.\n * - Otherwise the score is coverage = (distinct battery inputs delivered) / (battery\n * size); the buyer releases when it clears {@link RIDGES_DEMO_COVERAGE_TARGET}.\n * Malformed or unparseable content scores 0 and never throws.\n */\nexport function scoreRidgesDemoDeliverable(content: string | Buffer): number {\n const results = parseTestReport(content);\n if (results === null) {\n return 0;\n }\n const battery = new Set(DEMO_INPUTS);\n const coveredInputs = new Set<number>();\n for (const { input, output } of results) {\n if (!battery.has(input)) {\n // A result outside the battery does not fail the suite and does not count\n // toward coverage; it is simply ignored.\n continue;\n }\n if (output !== fizzbuzz(input)) {\n // A failing test = non-zero exit: the whole suite is rejected.\n return 0;\n }\n coveredInputs.add(input);\n }\n return coveredInputs.size / DEMO_INPUTS.length;\n}\n\n// A generic (non-demo) coding job produces a placeholder solution+report so a fresh\n// worker returns a well-formed ServiceResult before a real Ridges agent is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n language: \"typescript\",\n solution: \"// reference stub - replace the runAgent port with a real Ridges agent call.\",\n passed: false,\n tests: [],\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunAgent: RunCodingAgent = (spec) =>\n Promise.resolve(\n spec.metadata.demo === RIDGES_DEMO_MARKER ? solveRidgesDemo() : referencePlaceholder(spec),\n );\n\nconst defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/**\n * Build a Ridges {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with\n * the default ports; supply real ports for production use.\n */\nexport function createRidgesAdapter(config: RidgesAdapterConfig = {}): ServiceAdapter {\n const service = config.service ?? DEFAULT_SERVICE;\n const capabilities = config.capabilities ?? [...RIDGES_CAPABILITIES];\n const runAgent = config.runAgent ?? defaultRunAgent;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: service,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Run the coding agent and collect the test report (USD-billed; no swap).\n const content = await runAgent(spec);\n // 2. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: service },\n };\n },\n };\n}\n","/**\n * 404gen (Bittensor SN17) ServiceAdapter: a batch 3D-generation reference adapter,\n * built to the pattern the shipped Gradients (SN56) adapter established. A\n * Worker Bot wraps the 404gen text-to-3D subnet behind the `ServiceAdapter` interface:\n * it swaps a per-task USDC budget into TAO internally, pays subnet miners in TAO to\n * generate a batch of 3D assets, collects the batch deliverable, and returns a\n * currency-free `ServiceResult`. The Buyer and the escrow contract only ever see USDC;\n * no TAO-typed value crosses this boundary into SDK core (the branded `Tao` type of\n * ../bittensor/index.ts keeps it out at compile time for the Bittensor trio).\n *\n * The swap, subnet call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN17 dendrite, Pinata/Arweave).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (a batch of\n * 3D assets, each with a declared container format and polygon count). Whether the batch\n * is acceptable is decided by the BUYER's review.ts. For the canned demo the buyer knows\n * the exact expected artifact (the eval-threshold review re-verifies the fetched\n * deliverable hashes to the submitted contentHash) and additionally gates on the declared\n * per-asset descriptors via `score404genDemoDeliverable` (format, polygon range, batch\n * completeness). That recompute reads the DECLARED descriptors, not the asset bytes: a\n * production 404gen buyer generating novel assets must derive the container from the\n * fetched asset's magic bytes and the polygon count from its parsed geometry before\n * releasing. The worker never scores-for-release and never releases: the buyer is the judge.\n *\n * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor\n * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,\n * capabilities, budget, and demo logic.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Configuration and injectable ports for {@link create404genAdapter}. */\nexport interface Gen404AdapterConfig {\n /** Subnet identifier. Defaults to \"sn17\" (404gen); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"3d-generation\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n callSubnet?: SubnetCall;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** Stable id/capabilities, to be locked against `ADAPTER_DESCRIPTORS[\"404gen\"]` by a kit test at merge. */\nexport const GEN404_ADAPTER_ID = \"bittensor:sn17\";\nexport const GEN404_CAPABILITIES = [\"3d-generation\"] as const;\n\nconst DEFAULT_SUBNET = \"sn17\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 5_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a deterministic batch 3D job the buyer\n// template's 5-minute journey hires this bot for. The batch requests one asset with\n// a machine-checkable format + polygon-count contract. Acceptance is recomputed by\n// the BUYER (see score404genDemoDeliverable): each declared asset's format must be an\n// allowed container, its declared polygon count must fall in range, and the batch must\n// be complete. Any self-reported eval score is ignored (a production buyer parses the\n// actual asset geometry - see the module note).\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */\nexport const GEN404_DEMO_MARKER = \"404gen-sn17-demo-v1\";\n\n/** The demo eval floor: the batch must be complete and every asset valid (score 1). */\nexport const GEN404_DEMO_EVAL_FLOOR = 1;\n\n/** The demo batch contract: what the buyer independently checks each asset against. */\ninterface BatchExpectation {\n /** Number of assets the batch must contain to be complete. */\n requestedAssets: number;\n /** Container formats the buyer accepts (compared case-insensitively). */\n allowedFormats: readonly string[];\n /** Inclusive polygon-count bounds a valid asset must fall within. */\n minPolygons: number;\n maxPolygons: number;\n}\n\nconst DEMO_EXPECTATION: BatchExpectation = {\n requestedAssets: 1,\n allowedFormats: [\"GLB\", \"PLY\"],\n minPolygons: 1_000,\n maxPolygons: 1_000_000,\n};\n\n/**\n * The canned 404gen demo job. Deterministic; its specHash is pinned by a test\n * because the buyer journey depends on hash stability.\n */\nexport const gen404DemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no 3D category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Generate the canned SN17 demo batch: one 3D asset in a GLB or PLY container with a \" +\n \"polygon count between 1000 and 1000000. Acceptance is deterministic and recomputed \" +\n \"by the buyer: every requested asset must be present, in an allowed format, and in \" +\n \"polygon range; the worker's self-reported validity is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-format-valid\",\n description:\n \"Every asset is in an allowed container format (GLB or PLY), recomputed by the buyer.\",\n required: true,\n },\n {\n id: \"ac-polygon-range\",\n description:\n \"Every asset's polygon count is within [1000, 1000000], recomputed by the buyer.\",\n required: true,\n },\n {\n id: \"ac-batch-complete\",\n description:\n \"The batch contains all requested assets (completeness), recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GEN404_DEMO_MARKER,\n requestedAssets: DEMO_EXPECTATION.requestedAssets,\n allowedFormats: [...DEMO_EXPECTATION.allowedFormats],\n minPolygons: DEMO_EXPECTATION.minPolygons,\n maxPolygons: DEMO_EXPECTATION.maxPolygons,\n },\n};\n\n/**\n * The reference solution to the demo job: a complete batch of valid assets plus a\n * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.\n * Exposed so the demo journey and tests share one source of the expected artifact.\n */\nexport function solveGen404Demo(): string {\n return canonicalize({\n assets: [{ format: \"GLB\", polygonCount: 5_000, uri: \"ipfs://404gen-sn17-demo-asset-0\" }],\n eval: { metric: \"validity\", score: 1 },\n });\n}\n\ninterface DemoAsset {\n format: string;\n polygonCount: number;\n}\n\ninterface DemoBatch {\n assets: DemoAsset[];\n}\n\nfunction parseBatch(content: string | Buffer): DemoBatch | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const assets = (parsed as { assets?: unknown }).assets;\n if (!Array.isArray(assets)) {\n return null;\n }\n const cleaned: DemoAsset[] = [];\n for (const asset of assets) {\n if (typeof asset !== \"object\" || asset === null) {\n return null;\n }\n const format = (asset as { format?: unknown }).format;\n const polygonCount = (asset as { polygonCount?: unknown }).polygonCount;\n if (typeof format !== \"string\" || typeof polygonCount !== \"number\") {\n return null;\n }\n cleaned.push({ format, polygonCount });\n }\n return { assets: cleaned };\n}\n\nfunction isAssetValid(asset: DemoAsset): boolean {\n const formatOk = DEMO_EXPECTATION.allowedFormats.some(\n (f) => f.toLowerCase() === asset.format.toLowerCase(),\n );\n const rangeOk =\n asset.polygonCount >= DEMO_EXPECTATION.minPolygons &&\n asset.polygonCount <= DEMO_EXPECTATION.maxPolygons;\n return formatOk && rangeOk;\n}\n\n/**\n * The BUYER's recompute of the demo batch score in [0, 1] over the deliverable's\n * DECLARED per-asset descriptors. Every delivered asset must pass the format and\n * polygon-range checks (any single invalid asset scores 0, so a well-formed but junk\n * extra cannot slip through), and the batch must contain at least the requested count\n * (completeness); a short batch scores the filled fraction. Any self-reported `eval`\n * score in the deliverable is ignored. Malformed or unparseable content scores 0 and\n * never throws.\n *\n * NOTE: this gates the deliverable's declared `format`/`polygonCount` fields, not the\n * asset bytes. For the deterministic canned demo that is sufficient because the buyer\n * additionally knows the exact expected artifact (the eval-threshold review re-verifies\n * the fetched deliverable hashes to the submitted contentHash). A production 404gen\n * buyer generating NOVEL assets must derive the container from the fetched asset's magic\n * bytes and the polygon count from its parsed geometry before releasing (kit-docs debt).\n */\nexport function score404genDemoDeliverable(content: string | Buffer): number {\n const batch = parseBatch(content);\n if (batch === null) {\n return 0;\n }\n if (batch.assets.some((asset) => !isAssetValid(asset))) {\n return 0;\n }\n return Math.min(batch.assets.length / DEMO_EXPECTATION.requestedAssets, 1);\n}\n\n// A generic (non-demo) batch produces a placeholder asset so a fresh worker returns a\n// well-formed ServiceResult before a real SN17 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n assets: [{ format: \"GLB\", polygonCount: 0, uri: \"ipfs://placeholder\" }],\n note: \"reference stub - replace the callSubnet port with a real SN17 miner call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultCallSubnet: SubnetCall = (spec) =>\n Promise.resolve(\n spec.metadata.demo === GEN404_DEMO_MARKER ? solveGen404Demo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a 404gen (SN17) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core.\n */\nexport function create404genAdapter(config: Gen404AdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...GEN404_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.callSubnet ?? defaultCallSubnet,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Lium (Bittensor SN51) ServiceAdapter: a SHIPPED, supported adapter following the\n * Gradients pattern. A Worker Bot wraps the Lium GPU-compute subnet behind the\n * `ServiceAdapter` interface: it swaps a per-task USDC budget into TAO internally,\n * rents GPU compute from subnet miners in TAO to run the job, collects the output\n * artifact, and returns a currency-free `ServiceResult`. The Buyer and the escrow\n * contract only ever see USDC; no TAO-typed value crosses this boundary into SDK core\n * (the branded `Tao` type of ../bittensor/index.ts keeps it out at compile time for the\n * Bittensor trio).\n *\n * The swap, GPU-job call, and pinning are injectable ports so the reference runs (and\n * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies\n * real implementations (Jupiter for the swap, the SN51 GPU-rental dendrite,\n * Pinata/Arweave for pinning).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the job's\n * output artifact). Whether the job completed with a matching artifact is decided by\n * the BUYER's review.ts, which independently recomputes the scripted job's output and\n * compares hashes (see `scoreLiumDemoDeliverable`). The worker never scores-for-release\n * and never releases, and its self-reported `artifactHash` is never trusted\n * (the buyer is the judge).\n *\n * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor\n * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,\n * capabilities, budget, and demo logic. A GPU-rental call is a paid subnet call, so its\n * port reuses the shared `SubnetCall` shape under the local `RunGpuJob` name.\n */\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter } from \"../../adapter.js\";\nimport {\n createBittensorSubnetAdapter,\n defaultPin,\n defaultSwap,\n sha256Hex,\n type PinContent,\n type SubnetCall,\n type UsdcToTaoSwap,\n} from \"../bittensor/index.js\";\n\n/** Rent GPU compute for `budget` TAO and run `spec`'s job; resolve with the raw output artifact. */\nexport type RunGpuJob = SubnetCall;\n\n/** Configuration and injectable ports for {@link createLiumAdapter}. */\nexport interface LiumAdapterConfig {\n /** Subnet identifier. Defaults to \"sn51\" (Lium GPU compute); forms the adapter id `bittensor:<subnet>`. */\n subnet?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"gpu-compute\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToTaoSwap;\n /** GPU-job port. Default: runs the canned demo job; a deterministic placeholder otherwise. */\n runJob?: RunGpuJob;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// Stable id/capabilities. The adapter's own tests pin its runtime output to these\n// constants, and the kit's tests cross-check them against `ADAPTER_DESCRIPTORS.lium` in\n// create-escro-bot so the registry descriptor and the shipped adapter cannot drift apart.\nexport const LIUM_ADAPTER_ID = \"bittensor:sn51\";\nexport const LIUM_CAPABILITIES = [\"gpu-compute\"] as const;\n\nconst DEFAULT_SUBNET = \"sn51\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 20_000_000;\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a 5-minute scripted GPU job the buyer\n// template's journey hires this bot for. The \"GPU job\" is a deterministic hash\n// chain over a fixed seed, so its output artifact is reproducible: the buyer\n// RECOMPUTES it independently (see scoreLiumDemoDeliverable) and releases only when\n// the job completed, an artifact is present, and its hash matches. The worker's\n// self-reported artifactHash is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default job stub recognizes it. */\nexport const LIUM_DEMO_MARKER = \"lium-sn51-demo-v1\";\n\n/** The demo accept floor: hash-match is exact, so the buyer requires a full match. */\nexport const LIUM_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SEED = \"lium-sn51-demo-seed\";\nconst DEMO_ROUNDS = 1000;\n\n/**\n * The scripted GPU job's deterministic output artifact: a hash chain over the fixed\n * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.\n */\nexport function computeLiumDemoArtifact(): string {\n let h = DEMO_SEED;\n for (let i = 0; i < DEMO_ROUNDS; i++) {\n h = sha256Hex(h);\n }\n return h;\n}\n\n/**\n * The canned Lium demo job. Deterministic; its specHash is pinned by a test because\n * the buyer journey depends on hash stability.\n */\nexport const liumDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no GPU-compute category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Run the canned SN51 scripted GPU job (a fixed hash-chain compute over a known \" +\n \"seed) and return its output artifact. Acceptance is deterministic and recomputed \" +\n \"by the buyer: the job must complete, an output artifact must be present, and the \" +\n \"artifact must match the buyer's independent recompute; the worker's self-reported \" +\n \"artifact hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The scripted job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-artifact-present\",\n description: \"An output artifact is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-hash-match\",\n description:\n \"The output artifact matches the buyer's independent recompute of the scripted job.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: LIUM_DEMO_MARKER,\n seed: DEMO_SEED,\n rounds: DEMO_ROUNDS,\n acceptFloor: LIUM_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the\n * correct output artifact plus a (self-reported, buyer-ignored) artifactHash, as\n * canonical JSON. Deterministic. Exposed so the demo journey and tests share one\n * source of the expected artifact.\n */\nexport function solveLiumDemo(): string {\n const artifact = computeLiumDemoArtifact();\n return canonicalize({\n job: LIUM_DEMO_MARKER,\n status: \"completed\",\n rounds: DEMO_ROUNDS,\n artifact,\n // Self-reported and deliberately ignored by the buyer's recompute.\n artifactHash: sha256Hex(artifact),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n artifact: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as { status?: unknown; artifact?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const artifact = typeof obj.artifact === \"string\" ? obj.artifact : null;\n return { status, artifact };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1\n * when the deliverable satisfies all three criteria and 0 otherwise. It checks\n * completion (status), artifact presence, and hash match by RECOMPUTING the scripted\n * job's output and comparing the substantive artifact; it deliberately IGNORES any\n * self-reported `artifactHash`, so release can never be worker-controlled.\n * Malformed or unparseable content scores 0 and never throws.\n */\nexport function scoreLiumDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.artifact === null) {\n return 0;\n }\n return parsed.artifact === computeLiumDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) GPU job produces a placeholder completion report so a fresh\n// worker returns a well-formed ServiceResult before a real SN51 miner is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"lium-sn51-generic\",\n status: \"completed\",\n artifact: null,\n note: \"reference stub - replace the runJob port with a real SN51 GPU-rental call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunJob: RunGpuJob = (spec) =>\n Promise.resolve(\n spec.metadata.demo === LIUM_DEMO_MARKER ? solveLiumDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a Lium (SN51) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`\n * with the default ports; supply real ports for production use. The USDC->TAO swap,\n * pinning, and execute skeleton come from the shared Bittensor core; the GPU-rental\n * port is wired in as the core's `callSubnet`.\n */\nexport function createLiumAdapter(config: LiumAdapterConfig = {}): ServiceAdapter {\n return createBittensorSubnetAdapter({\n subnet: config.subnet ?? DEFAULT_SUBNET,\n capabilities: config.capabilities ?? [...LIUM_CAPABILITIES],\n taskBudgetMicroUsdc: config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC,\n swap: config.swap ?? defaultSwap,\n callSubnet: config.runJob ?? defaultRunJob,\n pin: config.pin ?? defaultPin,\n checkHealth: config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true)),\n });\n}\n","/**\n * Akash (Cosmos) ServiceAdapter: a SHIPPED, supported reference adapter that extends the\n * ServiceAdapter library beyond Bittensor. A Worker Bot\n * wraps an Akash deployment behind the `ServiceAdapter` interface: it swaps a per-task\n * USDC budget into AKT internally, provisions a deployment/lease on the Akash decentralized\n * cloud (paying providers in AKT), runs the compute job, collects the output artifact, and\n * returns a currency-free `ServiceResult`. The Buyer and the escrow contract only ever see\n * USDC; no AKT-typed value crosses this boundary into SDK core (the branded `Akt` type\n * keeps it out at compile time).\n *\n * Akash is Cosmos-based and billed in its own token (AKT), so -- like the Bittensor trio --\n * it converts USDC internally. But it is NOT a Bittensor subnet (its id is a bare \"akash\",\n * not `bittensor:<subnet>`), so it does not use the `adapters/bittensor` core: it carries\n * its own branded `Akt` and its own swap port.\n *\n * The swap, deployment call, and pinning are injectable ports so the reference runs (and is\n * tested) without a live DEX, Akash provider, or IPFS node. A production worker supplies\n * real implementations (a DEX/CEX route for the USDC->AKT swap, the Akash SDL/lease flow for\n * the deployment, Pinata/Arweave for pinning). The swap default is a fixed reference rate,\n * not a live price feed -- no price-feed dependency is introduced anywhere in SDK core\n * (the escrow contract takes no price feed; the reference rate here is a nominal constant a\n * real worker replaces with its own routing).\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the job's output\n * artifact). Whether the job completed with a matching artifact is decided by the BUYER's\n * review.ts, which independently recomputes the scripted job's output and compares hashes\n * (see `scoreAkashDemoDeliverable`). The worker never scores-for-release and never releases,\n * and its self-reported `artifactHash` is never trusted: the buyer is the judge.\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in AKT (Akash's token). Branded so it cannot be assigned to or from a\n * plain `number` by accident and (the point of the brand) so it can never appear in a\n * `ServiceResult` or the escrow submit path: those types have no field of this type. AKT\n * exists ONLY inside the Akash adapter layer.\n */\nexport type Akt = number & { readonly __brand: \"AKT\" };\n\n/** Construct an {@link Akt} amount from a plain number. Adapter-internal use only. */\nexport function akt(amount: number): Akt {\n return amount as Akt;\n}\n\n/** Swap a microUSDC budget into AKT. Real workers route this through a DEX/CEX. */\nexport type UsdcToAktSwap = (microUsdc: number) => Promise<Akt>;\n\n/**\n * Provision an Akash deployment/lease funded with `budget` AKT to run `spec`; resolve with\n * the raw deliverable (the job's output artifact).\n */\nexport type RunAkashDeployment = (spec: TaskSpec, budget: Akt) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * Stable id/capabilities. The adapter's own tests pin its runtime output to these\n * constants; the EscroBots registry descriptor for `akash` is registered separately (the\n * capability taxonomy).\n */\nexport const AKASH_ADAPTER_ID = \"akash\";\nexport const AKASH_CAPABILITIES = [\"cloud-compute\"] as const;\n\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 10_000_000;\n\n// Nominal reference rate: microUSDC -> AKT. Only the stub swap cares about the exact value;\n// it is a fixed constant, never a live price feed (a real worker replaces the swap port).\nexport const REFERENCE_MICRO_USDC_PER_AKT = 3_000_000;\n\n/** Default fixed-rate reference swap. */\nconst defaultSwap: UsdcToAktSwap = (microUsdc) =>\n Promise.resolve(akt(microUsdc / REFERENCE_MICRO_USDC_PER_AKT));\n\n/** Default deterministic `ipfs://` placeholder pin. */\nconst defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n/** Configuration and injectable ports for {@link createAkashAdapter}. */\nexport interface AkashAdapterConfig {\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"cloud-compute\"]`. */\n capabilities?: string[];\n /** μUSDC the worker allocates to a single task before converting to AKT (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub. */\n swap?: UsdcToAktSwap;\n /** Deployment port. Default: runs the canned demo job; a deterministic placeholder otherwise. */\n runDeployment?: RunAkashDeployment;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a deterministic batch compute job the buyer template's journey\n// hires this bot for. The \"compute job\" is a deterministic hash chain over a fixed\n// seed, so its output artifact is reproducible: the buyer RECOMPUTES it independently\n// (see scoreAkashDemoDeliverable) and releases only when the job completed, an artifact\n// is present, and its hash matches. The worker's self-reported artifactHash is never\n// trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default deployment stub recognizes it. */\nexport const AKASH_DEMO_MARKER = \"akash-demo-v1\";\n\n/** The demo accept floor: hash-match is exact, so the buyer requires a full match. */\nexport const AKASH_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SEED = \"akash-demo-seed\";\nconst DEMO_ROUNDS = 1000;\n\n/**\n * The scripted batch job's deterministic output artifact: a hash chain over the fixed\n * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.\n */\nexport function computeAkashDemoArtifact(): string {\n let h = DEMO_SEED;\n for (let i = 0; i < DEMO_ROUNDS; i++) {\n h = sha256Hex(h);\n }\n return h;\n}\n\n/**\n * The canned Akash demo job. Deterministic; its specHash is pinned by a test because the\n * buyer journey depends on hash stability.\n */\nexport const akashDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n // TaskType has no cloud-compute category; \"custom\" is the canonical fallback.\n taskType: \"custom\",\n description:\n \"Run the canned Akash scripted batch job (a fixed hash-chain compute over a known \" +\n \"seed) on a deployment and return its output artifact. Acceptance is deterministic and \" +\n \"recomputed by the buyer: the job must complete, an output artifact must be present, and \" +\n \"the artifact must match the buyer's independent recompute; the worker's self-reported \" +\n \"artifact hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The scripted job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-artifact-present\",\n description: \"An output artifact is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-hash-match\",\n description:\n \"The output artifact matches the buyer's independent recompute of the scripted job.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: AKASH_DEMO_MARKER,\n seed: DEMO_SEED,\n rounds: DEMO_ROUNDS,\n acceptFloor: AKASH_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the correct\n * output artifact plus a (self-reported, buyer-ignored) artifactHash, as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of the expected\n * artifact.\n */\nexport function solveAkashDemo(): string {\n const artifact = computeAkashDemoArtifact();\n return canonicalize({\n job: AKASH_DEMO_MARKER,\n status: \"completed\",\n rounds: DEMO_ROUNDS,\n artifact,\n // Self-reported and deliberately ignored by the buyer's recompute.\n artifactHash: sha256Hex(artifact),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n artifact: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n const obj = parsed as { status?: unknown; artifact?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const artifact = typeof obj.artifact === \"string\" ? obj.artifact : null;\n return { status, artifact };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when the\n * deliverable satisfies all three criteria and 0 otherwise. It checks completion (status),\n * artifact presence, and hash match by RECOMPUTING the scripted job's output and comparing\n * the substantive artifact; it deliberately IGNORES any self-reported `artifactHash`, so\n * release can never be worker-controlled. Malformed or unparseable content scores 0 and\n * never throws.\n */\nexport function scoreAkashDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.artifact === null) {\n return 0;\n }\n return parsed.artifact === computeAkashDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) job produces a placeholder completion report so a fresh worker\n// returns a well-formed ServiceResult before a real Akash deployment is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"akash-generic\",\n status: \"completed\",\n artifact: null,\n note: \"reference stub - replace the runDeployment port with a real Akash deployment call.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunDeployment: RunAkashDeployment = (spec) =>\n Promise.resolve(\n spec.metadata.demo === AKASH_DEMO_MARKER ? solveAkashDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build an Akash {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the\n * default ports; supply real ports for production use. The execute skeleton: swap the USDC\n * budget into AKT (internal, never surfaced), provision the deployment and collect the\n * output, then hash and pin. The recorded `ServiceResult` is currency-free (no AKT field).\n */\nexport function createAkashAdapter(config: AkashAdapterConfig = {}): ServiceAdapter {\n const capabilities = config.capabilities ?? [...AKASH_CAPABILITIES];\n const taskBudgetMicroUsdc = config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC;\n const swap = config.swap ?? defaultSwap;\n const runDeployment = config.runDeployment ?? defaultRunDeployment;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: AKASH_ADAPTER_ID,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into AKT (internal, never surfaced).\n const budgetAkt = await swap(taskBudgetMicroUsdc);\n // 2. Provision the Akash deployment (paid in AKT) and collect the deliverable.\n const content = await runDeployment(spec, budgetAkt);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: AKASH_ADAPTER_ID },\n };\n },\n };\n}\n","/**\n * Render Network ServiceAdapter: a SHIPPED, supported adapter for decentralized GPU\n * rendering (3D scenes, video frames, diffusion/inference jobs). A Worker Bot wraps a\n * Render Network job behind the `ServiceAdapter` interface: it swaps a per-task USDC\n * budget into RENDER internally, pays for the render job in RENDER, collects the\n * rendered output artifact, and returns a currency-free `ServiceResult`. The Buyer and\n * the escrow contract only ever see USDC; no RENDER-typed value crosses this boundary\n * into SDK core (the branded `Render` type keeps it out at compile time).\n *\n * Render is Solana-native with MINIMAL BRIDGING: RENDER is a Solana SPL token, so the\n * USDC->RENDER conversion is a same-chain DEX swap (e.g. Jupiter) with no cross-chain\n * bridge. This is the distinction from the Bittensor trio (gradients SN56, 404gen SN17,\n * lium SN51), whose TAO must be bridged off Solana to Bittensor. Because its token and\n * network differ, Render carries its own branded `Render` type and its own execute\n * skeleton and is deliberately NOT part of the shared `adapters/bittensor` core.\n *\n * No price feed lives in SDK core: the USDC->RENDER rate is an injectable `swap` port\n * defaulting to a deterministic fixed reference rate (see `defaultSwap`). A production\n * worker injects a real DEX route; SDK core embeds no live price feed. The swap,\n * render-job call, and pinning are injectable ports so the reference runs (and is\n * tested) without a live DEX, Render Network endpoint, or IPFS node.\n *\n * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the rendered\n * frame). Whether the render is acceptable is decided by the BUYER's review.ts, which\n * independently RE-RENDERS the scripted demo scene and compares the substantive frame\n * (see `scoreRenderDemoDeliverable`). The worker never scores-for-release and never\n * releases, and its self-reported `frameHash` is never trusted: the buyer is the judge.\n */\nimport { createHash } from \"crypto\";\n\nimport { canonicalize, type TaskSpec } from \"@escro/shared\";\n\nimport type { ServiceAdapter, ServiceResult } from \"../../adapter.js\";\n\n/**\n * Amount denominated in RENDER (Render Network's Solana SPL token). Branded so it cannot\n * be assigned to or from a plain `number` by accident and (the point of the brand) so it\n * can never appear in a `ServiceResult` or the escrow submit path: those types have no\n * field of this type. RENDER exists ONLY inside this adapter module.\n */\nexport type Render = number & { readonly __brand: \"RENDER\" };\n\n/** Construct a {@link Render} amount from a plain number. Adapter-internal use only. */\nexport function renderAmount(amount: number): Render {\n return amount as Render;\n}\n\n/** Swap a microUSDC budget into RENDER. Real workers route this through a Solana DEX (e.g. Jupiter). */\nexport type UsdcToRenderSwap = (microUsdc: number) => Promise<Render>;\n\n/** Submit `spec`'s render job funded with `budget` RENDER; resolve with the raw rendered artifact. */\nexport type RunRenderJob = (spec: TaskSpec, budget: Render) => Promise<string | Buffer>;\n\n/** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */\nexport type PinContent = (content: string | Buffer) => Promise<string>;\n\n/** Configuration and injectable ports for {@link createRenderAdapter}. */\nexport interface RenderAdapterConfig {\n /** Service identifier. Defaults to \"render\"; forms the adapter id. */\n service?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to {@link RENDER_CAPABILITIES}. */\n capabilities?: string[];\n /** microUSDC the worker allocates to a single task before converting to RENDER (internal budgeting). */\n taskBudgetMicroUsdc?: number;\n /** Swap port. Default: a fixed-rate reference stub (no live price feed). */\n swap?: UsdcToRenderSwap;\n /** Render-job port. Default: renders the canned demo scene; a deterministic placeholder otherwise. */\n runJob?: RunRenderJob;\n /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */\n pin?: PinContent;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n// Stable id/capabilities. The adapter's own tests pin its runtime output to these\n// constants; at merge the main-owned kit seam test cross-checks them against the\n// registry descriptor (ADAPTER_DESCRIPTORS.render) so the descriptor and the shipped\n// adapter cannot drift apart (coordinated with the capability taxonomy).\nexport const RENDER_ADAPTER_ID = \"render\";\nexport const RENDER_CAPABILITIES = [\"3d-rendering\", \"video-rendering\", \"gpu-inference\"] as const;\n\nconst DEFAULT_SERVICE = \"render\";\nconst DEFAULT_TASK_BUDGET_MICRO_USDC = 15_000_000;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// Nominal reference rate: microUSDC -> RENDER. Only the stub swap cares about the exact\n// value; a production worker injects a real DEX route via the `swap` port.\nexport const REFERENCE_MICRO_USDC_PER_RENDER = 2_000_000;\n\n/** Default fixed-rate reference swap: a pure function of its input, no live price feed. */\nexport const defaultSwap: UsdcToRenderSwap = (microUsdc) =>\n Promise.resolve(renderAmount(microUsdc / REFERENCE_MICRO_USDC_PER_RENDER));\n\n/** Default deterministic `ipfs://` placeholder pin. */\nexport const defaultPin: PinContent = (content) =>\n Promise.resolve(`ipfs://placeholder-${sha256Hex(content).slice(0, 16)}`);\n\n// ---------------------------------------------------------------------------\n// Canned demo job: a 5-minute scripted render job the buyer\n// template's journey hires this bot for. The \"render\" is a deterministic procedural\n// raster (a fixed shader over a fixed-size frame), so its output artifact is\n// reproducible: the buyer RE-RENDERS it independently (see scoreRenderDemoDeliverable)\n// and releases only when the job completed, a frame is present, and the frame matches.\n// The worker's self-reported frameHash is never trusted.\n// ---------------------------------------------------------------------------\n\n/** Stable marker on the demo spec's metadata so the default job stub recognizes it. */\nexport const RENDER_DEMO_MARKER = \"render-demo-v1\";\n\n/** The demo accept floor: frame-match is exact, so the buyer requires a full match. */\nexport const RENDER_DEMO_ACCEPT_FLOOR = 1;\n\nconst DEMO_SCENE = \"render-demo-scene-v1\";\nconst DEMO_WIDTH = 16;\nconst DEMO_HEIGHT = 16;\n\n/**\n * The deterministic per-pixel shader for the demo scene: a fixed grayscale value in\n * [0, 255] for pixel (x, y). Pure and reproducible, so the buyer can re-render and\n * compare independently.\n */\nfunction shade(x: number, y: number): number {\n return (x * 53 + y * 97 + (x ^ y) * 29) & 0xff;\n}\n\n/**\n * Render the fixed demo scene into a grayscale raster and return its hex encoding.\n * Deterministic and cheap to recompute, so the buyer verifies the frame independently.\n */\nexport function computeRenderDemoArtifact(): string {\n const raster = Buffer.alloc(DEMO_WIDTH * DEMO_HEIGHT);\n let i = 0;\n for (let y = 0; y < DEMO_HEIGHT; y++) {\n for (let x = 0; x < DEMO_WIDTH; x++) {\n raster[i++] = shade(x, y);\n }\n }\n return raster.toString(\"hex\");\n}\n\n/**\n * The canned Render demo job. Deterministic; its specHash is pinned by a test because\n * the buyer journey depends on hash stability.\n */\nexport const renderDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"image_generation\",\n description:\n \"Render the canned demo scene (a fixed procedural frame) and return the rendered \" +\n \"frame. Acceptance is deterministic and recomputed by the buyer: the job must \" +\n \"complete, a rendered frame must be present, and the frame must match the buyer's \" +\n \"independent re-render; the worker's self-reported frame hash is not trusted.\",\n acceptanceCriteria: [\n {\n id: \"ac-completion\",\n description: \"The render job ran to completion (status=completed).\",\n required: true,\n },\n {\n id: \"ac-frame-present\",\n description: \"A rendered frame is present in the deliverable.\",\n required: true,\n },\n {\n id: \"ac-frame-match\",\n description: \"The rendered frame matches the buyer's independent re-render of the scene.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: RENDER_DEMO_MARKER,\n scene: DEMO_SCENE,\n width: DEMO_WIDTH,\n height: DEMO_HEIGHT,\n acceptFloor: RENDER_DEMO_ACCEPT_FLOOR,\n },\n};\n\n/**\n * The reference solution to the demo job: the completed job report carrying the correct\n * rendered frame plus a (self-reported, buyer-ignored) frameHash, as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of the expected\n * artifact.\n */\nexport function solveRenderDemo(): string {\n const frame = computeRenderDemoArtifact();\n return canonicalize({\n job: RENDER_DEMO_MARKER,\n status: \"completed\",\n width: DEMO_WIDTH,\n height: DEMO_HEIGHT,\n frame,\n // Self-reported and deliberately ignored by the buyer's recompute.\n frameHash: sha256Hex(frame),\n });\n}\n\ninterface DemoDeliverable {\n status: string;\n frame: string | null;\n}\n\nfunction parseDemoDeliverable(content: string | Buffer): DemoDeliverable | null {\n const text = Buffer.isBuffer(content) ? content.toString(\"utf8\") : content;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const obj = parsed as { status?: unknown; frame?: unknown };\n const status = typeof obj.status === \"string\" ? obj.status : \"\";\n const frame = typeof obj.frame === \"string\" ? obj.frame : null;\n return { status, frame };\n}\n\n/**\n * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when\n * the deliverable satisfies all three criteria and 0 otherwise. It checks completion\n * (status), frame presence, and a frame match by RE-RENDERING the scripted scene and\n * comparing the substantive frame; it deliberately IGNORES any self-reported\n * `frameHash`, so release can never be worker-controlled. Malformed or\n * unparseable content scores 0 and never throws.\n */\nexport function scoreRenderDemoDeliverable(content: string | Buffer): number {\n const parsed = parseDemoDeliverable(content);\n if (parsed === null) {\n return 0;\n }\n if (parsed.status !== \"completed\") {\n return 0;\n }\n if (parsed.frame === null) {\n return 0;\n }\n return parsed.frame === computeRenderDemoArtifact() ? 1 : 0;\n}\n\n// A generic (non-demo) render job produces a placeholder completion report so a fresh\n// worker returns a well-formed ServiceResult before a real Render Network job is wired.\nfunction referencePlaceholder(spec: TaskSpec): string {\n return canonicalize({\n job: \"render-generic\",\n status: \"completed\",\n frame: null,\n note: \"reference stub - replace the runJob port with a real Render Network job submission.\",\n taskType: spec.taskType,\n });\n}\n\nconst defaultRunJob: RunRenderJob = (spec) =>\n Promise.resolve(\n spec.metadata.demo === RENDER_DEMO_MARKER ? solveRenderDemo() : referencePlaceholder(spec),\n );\n\n/**\n * Build a Render {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the\n * default ports; supply real ports for production use. The execute skeleton: swap the\n * USDC budget into RENDER (internal, same-chain, never surfaced), pay the render job in\n * RENDER and collect the frame, then hash and pin. The recorded `ServiceResult` is\n * currency-free (no RENDER field).\n */\nexport function createRenderAdapter(config: RenderAdapterConfig = {}): ServiceAdapter {\n const service = config.service ?? DEFAULT_SERVICE;\n const capabilities = config.capabilities ?? [...RENDER_CAPABILITIES];\n const taskBudgetMicroUsdc = config.taskBudgetMicroUsdc ?? DEFAULT_TASK_BUDGET_MICRO_USDC;\n const swap = config.swap ?? defaultSwap;\n const runJob = config.runJob ?? defaultRunJob;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id: service,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n // 1. Swap the USDC budget into RENDER (internal, same-chain DEX; no bridge).\n const budgetRender = await swap(taskBudgetMicroUsdc);\n // 2. Pay for the render job in RENDER and collect the rendered frame.\n const content = await runJob(spec, budgetRender);\n // 3. Hash and pin. The result the escrow records is currency-free.\n const contentHash = sha256Hex(content);\n const proofUri = await pin(content);\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: service, network: \"render\" },\n };\n },\n };\n}\n","/**\n * Gensyn ServiceAdapter + REE-proof acceptance. Gensyn is a\n * network for VERIFIABLE compute: a worker runs a job in a Reproducible Execution\n * Environment (REE) and returns a proof that binds the task, the delivered output,\n * and a reproducible execution transcript. Acceptance is buyer-side and by proof:\n * the Buyer auto-releases iff the REE proof verifies.\n *\n * The judgment is entirely BUYER-LAYER (this module, called by the buyer's bot),\n * exactly like `scoreGradientsDemoDeliverable` in the Gradients adapter. The\n * protocol still judges nothing: verification never enters the program or the\n * oracle, and this module imports no on-chain or oracle code.\n *\n * `verifyReeProof` is deliberately a BUYER recompute, mirroring the Gradients\n * pattern where the buyer re-derives the eval score rather than trusting the\n * worker's self-report: it re-runs the reproducible execution and checks the\n * worker's transcript hash against its own. A production Gensyn verifier would\n * replace the full recompute with Gensyn's interactive verification game over the\n * same `transcriptHash`; the acceptance contract (a proof binding spec, content,\n * and reproducible transcript) is unchanged.\n */\nimport { createHash } from \"crypto\";\n\nimport {\n canonicalize,\n type ReviewDeliverable,\n type ReviewPolicy,\n type ReviewResult,\n type TaskSpec,\n} from \"@escro/shared\";\n\nimport type { ResolveProofUri, ServiceAdapter, ServiceResult } from \"../../adapter.js\";\nimport { EscroError } from \"../../errors.js\";\n\n/** Stable adapter identity + EscroBots capability (pinned by a test). */\nexport const GENSYN_ADAPTER_ID = \"gensyn\";\nexport const GENSYN_CAPABILITIES = [\"verifiable-compute\"] as const;\n\n/** REE proof scheme tag. A verifier accepts only proofs carrying this exact scheme. */\nexport const GENSYN_REE_SCHEME = \"gensyn-ree-v1\";\n\n/** Marker on the demo spec's metadata so the default reproducible compute recognizes it. */\nexport const GENSYN_DEMO_MARKER = \"gensyn-ree-demo-v1\";\n\n/** The demo's fixed reproducible-execution parameters (a deterministic LCG walk). */\nexport const GENSYN_DEMO_SEED = 12345;\nexport const GENSYN_DEMO_STEPS = 16;\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ---------------------------------------------------------------------------\n// Reproducible execution: the deterministic computation the REE proof attests to.\n// A fixed linear congruential generator walked `steps` times from `seed`; the\n// ordered states are the transcript, the final state is the result. Deterministic\n// from the spec alone, so the buyer can reproduce it and confirm the worker's\n// transcript hash (the essence of a Reproducible Execution Environment).\n// ---------------------------------------------------------------------------\n\nconst LCG_MULT = 1103515245n;\nconst LCG_INC = 12345n;\nconst LCG_MOD = 1n << 31n;\n\n/** The result of one reproducible execution: its transcript and final output. */\nexport interface ReeExecution {\n /** Seed the walk started from. */\n seed: number;\n /** Number of steps walked. */\n steps: number;\n /** Ordered per-step states (the execution transcript). */\n states: number[];\n /** Final state (the deliverable's numeric result). */\n result: number;\n}\n\n/** Run the reproducible compute for `spec`, deriving the transcript and result. */\nexport type ReproduceCompute = (spec: TaskSpec) => ReeExecution;\n\nfunction readComputeParams(spec: TaskSpec): { seed: number; steps: number } {\n const rawSeed = spec.metadata.seed;\n const rawSteps = spec.metadata.steps;\n const seed =\n typeof rawSeed === \"number\" && Number.isInteger(rawSeed) ? rawSeed : GENSYN_DEMO_SEED;\n const steps =\n typeof rawSteps === \"number\" && Number.isInteger(rawSteps) && rawSteps > 0\n ? rawSteps\n : GENSYN_DEMO_STEPS;\n return { seed, steps };\n}\n\n/**\n * The reference reproducible execution. Deterministic from `spec` (its seed/steps\n * come from `spec.metadata`, defaulting to the demo parameters), so both worker and\n * buyer derive the same transcript.\n */\nexport const reproduceGensynCompute: ReproduceCompute = (spec) => {\n const { seed, steps } = readComputeParams(spec);\n const states: number[] = [];\n let x = BigInt(seed) % LCG_MOD;\n if (x < 0n) {\n x += LCG_MOD;\n }\n for (let i = 0; i < steps; i++) {\n x = (LCG_MULT * x + LCG_INC) % LCG_MOD;\n states.push(Number(x));\n }\n return { seed, steps, states, result: states[states.length - 1] ?? seed };\n};\n\n/** Serialize a reproducible execution's output into the deliverable content. */\nexport function gensynDeliverable(exec: ReeExecution): string {\n return canonicalize({ result: exec.result, steps: exec.steps });\n}\n\n// ---------------------------------------------------------------------------\n// REE proof\n// ---------------------------------------------------------------------------\n\n/**\n * A Gensyn REE proof. Every field is a commitment the buyer re-derives:\n * `commitment` binds the whole tuple, `outputHash` binds the delivered content,\n * `specHash` binds the task asked, `transcriptHash` binds the reproducible run.\n */\nexport interface ReeProof {\n scheme: typeof GENSYN_REE_SCHEME;\n /** SHA-256 hex of the canonical task spec. */\n specHash: string;\n /** SHA-256 hex of the delivered content. */\n outputHash: string;\n /** Number of reproducible execution steps (positive integer). */\n steps: number;\n /** SHA-256 hex of the canonical execution transcript. */\n transcriptHash: string;\n /** SHA-256 hex binding scheme, specHash, outputHash, steps, and transcriptHash. */\n commitment: string;\n}\n\ntype ReeProofBase = Omit<ReeProof, \"commitment\">;\n\n/** The single canonical binding the commitment (and its verification) is computed over. */\nfunction commitmentOf(base: ReeProofBase): string {\n return sha256Hex(\n [base.scheme, base.specHash, base.outputHash, String(base.steps), base.transcriptHash].join(\n \"\\n\",\n ),\n );\n}\n\n/**\n * Build the REE proof a worker attaches to its deliverable. Not a trust anchor on\n * its own: `verifyReeProof` re-derives every field, so a proof only accepts when it\n * genuinely binds the content, spec, and a reproducible transcript.\n */\nexport function buildReeProof(\n spec: TaskSpec,\n exec: ReeExecution,\n content: string | Buffer,\n): ReeProof {\n const base: ReeProofBase = {\n scheme: GENSYN_REE_SCHEME,\n specHash: sha256Hex(canonicalize(spec)),\n outputHash: sha256Hex(content),\n steps: exec.steps,\n transcriptHash: sha256Hex(canonicalize(exec.states)),\n };\n return { ...base, commitment: commitmentOf(base) };\n}\n\n/** The verifier's verdict: a proof is either valid, or invalid/malformed with a reason. */\nexport interface ReeVerification {\n valid: boolean;\n /** Prefixed `malformed` (shape/structure) or `invalid` (a binding failed), or a pass note. */\n reason: string;\n}\n\n/** Inputs the buyer verifies a proof against: the task asked and the content received. */\nexport interface ReeVerifyContext {\n /** The task spec the buyer commissioned. */\n spec: TaskSpec;\n /** The deliverable content the buyer received (fetched from proofUri in production). */\n content: string | Buffer;\n /** The reproducible compute; defaults to the reference {@link reproduceGensynCompute}. */\n reproduce?: ReproduceCompute;\n}\n\nconst HEX_64 = /^[0-9a-f]{64}$/;\n\nfunction isHex64(v: unknown): v is string {\n return typeof v === \"string\" && HEX_64.test(v);\n}\n\nfunction malformed(reason: string): ReeVerification {\n return { valid: false, reason: `malformed: ${reason}` };\n}\n\nfunction invalid(reason: string): ReeVerification {\n return { valid: false, reason: `invalid: ${reason}` };\n}\n\n/**\n * The BUYER's verification of an REE proof (untrusted input from the worker). Returns\n * `valid: true` only when the proof is well-formed AND every binding holds: the\n * commitment is self-consistent, the committed output hash equals the delivered\n * content, the spec hash equals the commissioned task, and the transcript hash\n * matches the buyer's own reproduction of the execution. Never throws.\n */\nexport function verifyReeProof(proof: unknown, ctx: ReeVerifyContext): ReeVerification {\n if (typeof proof !== \"object\" || proof === null) {\n return malformed(\"proof is not an object\");\n }\n const p = proof as Record<string, unknown>;\n\n if (p.scheme !== GENSYN_REE_SCHEME) {\n return malformed(`scheme must be \"${GENSYN_REE_SCHEME}\"`);\n }\n if (!isHex64(p.specHash)) {\n return malformed(\"specHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.outputHash)) {\n return malformed(\"outputHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.transcriptHash)) {\n return malformed(\"transcriptHash must be a 64-char lowercase hex string\");\n }\n if (!isHex64(p.commitment)) {\n return malformed(\"commitment must be a 64-char lowercase hex string\");\n }\n if (typeof p.steps !== \"number\" || !Number.isInteger(p.steps) || p.steps <= 0) {\n return malformed(\"steps must be a positive integer\");\n }\n\n const base: ReeProofBase = {\n scheme: GENSYN_REE_SCHEME,\n specHash: p.specHash,\n outputHash: p.outputHash,\n steps: p.steps,\n transcriptHash: p.transcriptHash,\n };\n\n if (commitmentOf(base) !== p.commitment) {\n return invalid(\"commitment does not bind the proof fields (tampered)\");\n }\n if (sha256Hex(ctx.content) !== p.outputHash) {\n return invalid(\"outputHash does not match the delivered content\");\n }\n if (sha256Hex(canonicalize(ctx.spec)) !== p.specHash) {\n return invalid(\"specHash does not match the commissioned task spec\");\n }\n const exec = (ctx.reproduce ?? reproduceGensynCompute)(ctx.spec);\n if (p.steps !== exec.steps) {\n return invalid(\"steps does not match the reproduced execution\");\n }\n if (sha256Hex(canonicalize(exec.states)) !== p.transcriptHash) {\n return invalid(\"transcriptHash is not reproducible from the task spec\");\n }\n // The load-bearing acceptance check: the delivered content must be the ACTUAL output\n // of the reproduced execution, not merely something the worker hashed into a\n // self-consistent proof. Without this, a worker could attach a valid proof to\n // arbitrary content (its outputHash would still equal the delivered garbage) and\n // trigger auto-release. Binding outputHash to the buyer's own reproduced deliverable\n // (and, via the check above, to the delivered content) closes that forgery.\n if (sha256Hex(gensynDeliverable(exec)) !== p.outputHash) {\n return invalid(\"outputHash does not match the reproduced deliverable\");\n }\n\n return {\n valid: true,\n reason:\n \"REE proof verified: commitment, spec, transcript, and the reproduced deliverable all bind to the delivered content.\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Buyer-layer auto-release\n// ---------------------------------------------------------------------------\n\n/** What the buyer assembles to decide acceptance: the received content and the worker's proof. */\nexport interface GensynDeliverableBundle {\n /** The deliverable content the buyer received. */\n content: string | Buffer;\n /** The REE proof the worker attached (untrusted; verified before any release). */\n proof: unknown;\n}\n\n/** A buyer auto-release decision. `release: true` means \"call release_payment()\". */\nexport interface AutoReleaseDecision {\n release: boolean;\n reason: string;\n}\n\n/**\n * The buyer bot's auto-release decision for a Gensyn deliverable. Releases ONLY when\n * the REE proof verifies against the delivered content and the commissioned spec;\n * an invalid or malformed proof never releases. This is the whole acceptance\n * mechanism, and it lives entirely at the buyer layer.\n */\nexport function gensynAutoRelease(\n bundle: GensynDeliverableBundle,\n ctx: { spec: TaskSpec; reproduce?: ReproduceCompute },\n): AutoReleaseDecision {\n const verdict = verifyReeProof(bundle.proof, {\n spec: ctx.spec,\n content: bundle.content,\n ...(ctx.reproduce !== undefined && { reproduce: ctx.reproduce }),\n });\n return { release: verdict.valid, reason: verdict.reason };\n}\n\n/** Encode the document a Gensyn worker pins: the deliverable content and its REE proof. */\nexport function encodeGensynBundle(bundle: { content: string; proof: ReeProof }): string {\n return canonicalize(bundle);\n}\n\n/**\n * Decode the document a `proofUri` resolves to. Returns null unless it parses to an object\n * with a string `content` and an object `proof` (the proof itself is verified later).\n */\nexport function decodeGensynBundle(document: string | Buffer): GensynDeliverableBundle | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(typeof document === \"string\" ? document : document.toString(\"utf8\"));\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return null;\n }\n const { content, proof } = parsed as Record<string, unknown>;\n if (typeof content !== \"string\" || typeof proof !== \"object\" || proof === null) {\n return null;\n }\n return { content, proof };\n}\n\n/** Options for {@link gensynProofAutoRelease}. */\nexport interface GensynProofAutoReleaseOptions {\n /**\n * Fetch the bundle document the submitted `proofUri` names. A throw or rejection\n * propagates (retried), never a verdict.\n */\n resolveProofUri: ResolveProofUri;\n /** The task spec the buyer commissioned; the proof must bind it. */\n spec: TaskSpec;\n /** The reproducible compute; defaults to the reference {@link reproduceGensynCompute}. */\n reproduce?: ReproduceCompute;\n}\n\nfunction gensynDispute(reason: string): ReviewResult {\n return { accept: false, dispute: true, reason };\n}\n\n/**\n * Buyer-layer auto-release over the pinned Gensyn bundle. It resolves `proofUri` through\n * `resolveProofUri`, requires the bundle's content to re-hash to the worker-submitted\n * `contentHash`, then releases only when {@link gensynAutoRelease} does; anything else\n * DISPUTES. A resolver that throws propagates: an infrastructure failure is not a verdict.\n * Construction throws `ADAPTER_CONFIG_ERROR` when `resolveProofUri` or `spec` is missing.\n */\nexport function gensynProofAutoRelease(opts: GensynProofAutoReleaseOptions): ReviewPolicy {\n // A JavaScript caller can pass no options at all; that is a config error, not a TypeError.\n const raw: unknown = opts;\n const given = (typeof raw === \"object\" && raw !== null ? raw : {}) as Partial<\n Record<keyof GensynProofAutoReleaseOptions, unknown>\n >;\n if (typeof given.resolveProofUri !== \"function\") {\n throw new EscroError(\n \"gensynProofAutoRelease: `resolveProofUri` must be a function\",\n \"ADAPTER_CONFIG_ERROR\",\n );\n }\n if (typeof given.spec !== \"object\" || given.spec === null) {\n throw new EscroError(\"gensynProofAutoRelease: `spec` is required\", \"ADAPTER_CONFIG_ERROR\");\n }\n const { resolveProofUri, spec, reproduce } = opts;\n return {\n name: \"gensyn-proof-auto-release\",\n async evaluate(d: ReviewDeliverable): Promise<ReviewResult> {\n if (d.proofUri === null || d.proofUri === \"\") {\n return gensynDispute(\"no proofUri attached\");\n }\n const bundle = decodeGensynBundle(await resolveProofUri(d.proofUri));\n if (bundle === null) {\n return gensynDispute(\"proofUri does not resolve to a decodable gensyn bundle\");\n }\n if (sha256Hex(bundle.content) !== d.contentHash) {\n return gensynDispute(\n \"bundle content does not hash to the submitted contentHash (tampered or wrong)\",\n );\n }\n const decision = gensynAutoRelease(bundle, {\n spec,\n ...(reproduce !== undefined && { reproduce }),\n });\n return decision.release\n ? { accept: true, dispute: false, reason: decision.reason }\n : gensynDispute(decision.reason);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Adapter (worker side)\n// ---------------------------------------------------------------------------\n\n/** Configuration and injectable ports for {@link createGensynAdapter}. */\nexport interface GensynAdapterConfig {\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"verifiable-compute\"]`. */\n capabilities?: string[];\n /** The reproducible compute the worker runs. Default: the reference LCG walk. */\n runCompute?: ReproduceCompute;\n /**\n * Pinning port: receives the bundle document ({@link encodeGensynBundle}) and returns its\n * reference. Default: a deterministic `ipfs://` placeholder URI over those bytes.\n */\n pin?: (content: string | Buffer) => Promise<string>;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/** The canned demo job the buyer template's journey hires a Gensyn worker for. */\nexport const gensynDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"custom\",\n description:\n \"Run the reference reproducible compute (a fixed LCG walk from the seed in \" +\n \"metadata) and return its final result. Acceptance is a valid gensyn-ree-v1 REE \" +\n \"proof: the buyer recomputes the transcript and confirms the proof binds the \" +\n \"delivered content, this spec, and the reproducible execution. The worker's \" +\n \"self-reported result is never trusted on its own.\",\n acceptanceCriteria: [\n {\n id: \"ac-ree-proof\",\n description:\n \"A valid gensyn-ree-v1 proof binding the delivered content, this spec, and a reproducible transcript.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: {\n demo: GENSYN_DEMO_MARKER,\n seed: GENSYN_DEMO_SEED,\n steps: GENSYN_DEMO_STEPS,\n },\n};\n\nconst defaultPin = (content: string | Buffer): Promise<string> =>\n Promise.resolve(`ipfs://gensyn-${sha256Hex(content).slice(0, 16)}`);\n\n/**\n * Build a Gensyn {@link ServiceAdapter}. `execute` runs the reproducible compute,\n * serializes the deliverable, builds its REE proof and pins the bundle of both; `proofUri`\n * names that bundle, which the buyer verifies with {@link gensynProofAutoRelease}. Passes\n * `assertServiceAdapterContract` with the default ports; supply real ports (a real\n * Gensyn job runner, a real pinner) for production.\n */\nexport function createGensynAdapter(config: GensynAdapterConfig = {}): ServiceAdapter {\n const runCompute = config.runCompute ?? reproduceGensynCompute;\n const pin = config.pin ?? defaultPin;\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n const capabilities = config.capabilities ?? [...GENSYN_CAPABILITIES];\n\n return {\n id: GENSYN_ADAPTER_ID,\n capabilities,\n healthCheck: checkHealth,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n const exec = runCompute(spec);\n const content = gensynDeliverable(exec);\n const contentHash = sha256Hex(content);\n const proof = buildReeProof(spec, exec, content);\n const proofUri = await pin(encodeGensynBundle({ content, proof }));\n return {\n content,\n contentHash,\n proofUri,\n metadata: { adapter: GENSYN_ADAPTER_ID },\n };\n },\n };\n}\n","/**\n * ZKML proof-verifier ServiceAdapter. A Worker Bot wraps a zk-verified\n * inference service: it runs the model, then attaches a proof that the delivered\n * output is the correct result of running a committed model on a committed input.\n * The worker pins one bundle document holding the deliverable and its proof, and\n * `ServiceResult.proofUri` is that document's content-addressed reference; the Buyer\n * resolves it through its own `resolveProofUri` port and configures auto-release on\n * proof validation. Same buyer-layer-only shape as every adapter -- the escrow\n * program and the oracle judge nothing: verification is pure TypeScript that runs\n * in the Buyer's bot, never on-chain and never in the oracle (this module imports\n * no on-chain or oracle code).\n *\n * WHAT THE SHIPPED VERIFIER IS -- AND IS NOT. The default scheme (`escro-zkml-ref-v1`)\n * is a REFERENCE verifier with NO cryptographic soundness. Its tag is a plain keyless\n * hash of the public inputs (see `computeZkmlVerificationTag`) and `buildZkmlProof` is\n * exported, so ANY party can mint a proof that `verifyZkmlProof` accepts, over whatever\n * output it chooses and any model commitment. It exists to demonstrate the lifecycle\n * (proof shape, the pinned bundle behind `proofUri`, decode, and the buyer-side\n * auto-release seam) deterministically and with no external prover. It must NEVER be the sole gate on a\n * production release. A production ZKML buyer passes a REAL SNARK/STARK verifier to\n * `zkmlProofAutoRelease` (the `verify` option): a verifying key over the same public\n * inputs, which is where soundness actually lives.\n *\n * TWO DISCIPLINES THAT DO CARRY TO PRODUCTION. (1) The buyer RE-HASHES the content of\n * the bundle it resolved and requires `sha256(content)` equals the worker-submitted\n * `contentHash` before trusting anything (`zkmlProofAutoRelease`). The submitted\n * hash is the worker's claim, never trusted on its own -- the same discipline as the\n * buyer template's `evalThresholdReview`. (2) Verification is\n * buyer-layer only: it runs in the Buyer's bot, never on-chain and never in the oracle.\n * RELEASE JUDGMENT IS THE BUYER'S: the adapter only\n * PRODUCES the deliverable and its proof; whether to release is `zkmlProofAutoRelease`\n * in the Buyer's review, never the worker and never the protocol.\n */\nimport { createHash } from \"crypto\";\n\nimport {\n canonicalize,\n type ReviewDeliverable,\n type ReviewPolicy,\n type ReviewResult,\n type TaskSpec,\n} from \"@escro/shared\";\n\nimport type { ResolveProofUri, ServiceAdapter, ServiceResult } from \"../../adapter.js\";\nimport { EscroError } from \"../../errors.js\";\n\n/** Stable id/capabilities; locked against the EscroBots registry descriptor by a kit test at merge. */\nexport const ZKML_ADAPTER_ID = \"zkml\";\nexport const ZKML_CAPABILITIES = [\"zk-verified-inference\"] as const;\n\n/** Marker on the demo spec's metadata so the default inference port recognizes it. */\nexport const ZKML_DEMO_MARKER = \"zkml-demo-v1\";\n\n/** The reference proving scheme this verifier understands. Unknown schemes are malformed to it. */\nexport const ZKML_PROOF_SCHEME = \"escro-zkml-ref-v1\";\n\n/** Prefix marking a ZKML bundle document, the bytes a worker pins: `zkml-proof:<base64url(json)>`. */\nexport const ZKML_PROOF_URI_PREFIX = \"zkml-proof:\";\n\nfunction sha256Hex(content: string | Buffer): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n// ── Proof shape ──────────────────────────────────────────────────────────────────\n\n/**\n * A ZKML proof: its public inputs plus a `verificationTag` binding them. In the\n * reference scheme the tag is recomputable (see {@link computeZkmlVerificationTag});\n * in a production scheme it is a SNARK/STARK checked against a verifying key over the\n * same public inputs.\n */\nexport interface ZkmlProof {\n /** Proving scheme identifier; the verifier only understands {@link ZKML_PROOF_SCHEME}. */\n scheme: string;\n /** Commitment to the model that produced the output (e.g. a weights hash). */\n modelCommitment: string;\n /** Commitment to the input the model was run on. */\n inputCommitment: string;\n /** SHA-256 hex of the delivered output; binds the proof to a specific deliverable. */\n outputHash: string;\n /** Binding tag over the public inputs (reference: recomputable; production: a SNARK). */\n verificationTag: string;\n}\n\n/** The public inputs a proof commits to (everything except the tag itself). */\ntype ZkmlPublicInputs = Omit<ZkmlProof, \"verificationTag\">;\n\n/** Recompute the reference binding tag over a proof's public inputs. Deterministic. */\nexport function computeZkmlVerificationTag(publicInputs: ZkmlPublicInputs): string {\n return sha256Hex(\n canonicalize({\n scheme: publicInputs.scheme,\n modelCommitment: publicInputs.modelCommitment,\n inputCommitment: publicInputs.inputCommitment,\n outputHash: publicInputs.outputHash,\n }),\n );\n}\n\n/** Build a well-formed reference proof binding the given public inputs. */\nexport function buildZkmlProof(args: {\n scheme?: string;\n modelCommitment: string;\n inputCommitment: string;\n outputHash: string;\n}): ZkmlProof {\n const publicInputs: ZkmlPublicInputs = {\n scheme: args.scheme ?? ZKML_PROOF_SCHEME,\n modelCommitment: args.modelCommitment,\n inputCommitment: args.inputCommitment,\n outputHash: args.outputHash,\n };\n return { ...publicInputs, verificationTag: computeZkmlVerificationTag(publicInputs) };\n}\n\n/** The document a ZKML worker pins: the deliverable content and the proof over it. */\nexport interface ZkmlProofBundle {\n /** The deliverable content; its SHA-256 is the escrow's on-chain `contentHash`. */\n content: string;\n /** The proof binding `content` to the committed model and input. */\n proof: ZkmlProof;\n}\n\n/** Encode a bundle as the document a worker pins; `proofUri` is that document's reference. */\nexport function encodeZkmlProofUri(bundle: ZkmlProofBundle): string {\n return ZKML_PROOF_URI_PREFIX + Buffer.from(canonicalize(bundle), \"utf8\").toString(\"base64url\");\n}\n\nfunction isProofShaped(value: unknown): value is ZkmlProof {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const p = value as Record<string, unknown>;\n return (\n typeof p.scheme === \"string\" &&\n typeof p.modelCommitment === \"string\" &&\n typeof p.inputCommitment === \"string\" &&\n typeof p.outputHash === \"string\" &&\n typeof p.verificationTag === \"string\"\n );\n}\n\n/**\n * Decode the document a `proofUri` resolves to back to a {@link ZkmlProofBundle}. Returns\n * null for a document without the prefix, an undecodable payload, a `content` that is not\n * a string or a `proof` that is not proof-shaped.\n */\nexport function decodeZkmlProofUri(document: string | Buffer): ZkmlProofBundle | null {\n const text = typeof document === \"string\" ? document : document.toString(\"utf8\");\n if (!text.startsWith(ZKML_PROOF_URI_PREFIX)) {\n return null;\n }\n const encoded = text.slice(ZKML_PROOF_URI_PREFIX.length);\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n const { content, proof } = parsed as Record<string, unknown>;\n return typeof content === \"string\" && isProofShaped(proof) ? { content, proof } : null;\n}\n\n// ── Verification ─────────────────────────────────────────────────────────────────\n\n/**\n * The outcome of verifying a proof. `malformed` = the verifier cannot understand the\n * proof (missing/wrong-typed fields, unsupported scheme, undecodable URI); `invalid`\n * = a well-formed proof that fails verification (tag does not recompute, or attests a\n * different output/model than expected).\n */\nexport type ZkmlVerification =\n | { valid: true }\n | { valid: false; category: \"invalid\" | \"malformed\"; reason: string };\n\n/** What the Buyer expects the proof to attest to: values the Buyer computes itself. */\nexport interface ZkmlExpectation {\n /** The submitted deliverable's contentHash; the proof's outputHash must equal it. */\n contentHash: string;\n /** The model the Buyer hired; the proof's modelCommitment must equal it. */\n modelCommitment: string;\n /** The Buyer's commitment over its own input; the proof's inputCommitment must equal it. */\n inputCommitment: string;\n}\n\n/**\n * Verify a decoded proof against the Buyer's expectation. NOTE: this is the REFERENCE\n * verifier and is NOT cryptographically sound -- the tag is a keyless hash, so a `valid`\n * result means only that the proof is internally consistent and bound to the expected\n * output, model and input, not that a trustworthy party produced it. Pass a real verifier\n * to {@link zkmlProofAutoRelease} for production. `malformed` = an unusable proof;\n * `invalid` = a usable proof that fails the checks.\n */\nexport function verifyZkmlProof(proof: unknown, expected: ZkmlExpectation): ZkmlVerification {\n if (!isProofShaped(proof)) {\n return { valid: false, category: \"malformed\", reason: \"proof is missing required fields\" };\n }\n if (proof.scheme !== ZKML_PROOF_SCHEME) {\n return {\n valid: false,\n category: \"malformed\",\n reason: `unsupported proof scheme \"${proof.scheme}\"`,\n };\n }\n if (proof.verificationTag !== computeZkmlVerificationTag(proof)) {\n return {\n valid: false,\n category: \"invalid\",\n reason:\n \"verification tag does not recompute (public inputs altered after the tag was computed)\",\n };\n }\n if (proof.outputHash !== expected.contentHash) {\n return {\n valid: false,\n category: \"invalid\",\n reason: \"proof attests a different output than the submitted deliverable\",\n };\n }\n if (proof.modelCommitment !== expected.modelCommitment) {\n return { valid: false, category: \"invalid\", reason: \"proof attests a different model\" };\n }\n if (proof.inputCommitment !== expected.inputCommitment) {\n return { valid: false, category: \"invalid\", reason: \"proof attests a different input\" };\n }\n return { valid: true };\n}\n\n/**\n * Decode the document a `proofUri` resolved to (or reject an absent or foreign one),\n * require its content to hash to `expected.contentHash`, then verify its proof.\n */\nexport function verifyZkmlProofUri(\n document: string | Buffer | null | undefined,\n expected: ZkmlExpectation,\n): ZkmlVerification {\n if (document === null || document === undefined) {\n return { valid: false, category: \"malformed\", reason: \"no bundle document resolved\" };\n }\n const bundle = decodeZkmlProofUri(document);\n if (bundle === null) {\n return {\n valid: false,\n category: \"malformed\",\n reason: \"document is not a decodable zkml bundle\",\n };\n }\n if (sha256Hex(bundle.content) !== expected.contentHash) {\n return {\n valid: false,\n category: \"invalid\",\n reason: \"bundle content does not hash to the expected contentHash\",\n };\n }\n return verifyZkmlProof(bundle.proof, expected);\n}\n\n// ── Buyer-layer auto-release predicate ───────────────────────────────────────────\n\n/** The submitted deliverable as the Buyer's review reads it off the escrow read model. */\nexport type ZkmlDeliverable = ReviewDeliverable;\n\n/** A release decision: release, and if not, whether to contest via dispute. */\nexport type ZkmlReviewResult = ReviewResult;\n\n/** A named release policy the Buyer's review wires in; `evaluate` may be sync or async. */\nexport type ZkmlReviewPolicy = ReviewPolicy;\n\n/** Options for {@link zkmlProofAutoRelease}. */\nexport interface ZkmlProofAutoReleaseOptions {\n /**\n * Fetch the bundle document the submitted `proofUri` names. Required: the content and\n * its proof come only from that document. A throw or rejection propagates (retried),\n * never a verdict.\n */\n resolveProofUri: ResolveProofUri;\n /** The model the Buyer hired; the proof's modelCommitment must equal it. */\n modelCommitment: string;\n /** The Buyer's commitment over its own spec ({@link computeZkmlInputCommitment}). */\n inputCommitment: string;\n /**\n * The proof verifier. DEFAULT is {@link verifyZkmlProof}, the reference verifier, which\n * is NOT cryptographically sound. A production buyer MUST pass a real SNARK/STARK\n * verifier here; the default is for demos only.\n */\n verify?: (proof: ZkmlProof, expected: ZkmlExpectation) => ZkmlVerification;\n}\n\nfunction adapterConfigError(message: string): EscroError {\n return new EscroError(message, \"ADAPTER_CONFIG_ERROR\");\n}\n\nfunction dispute(reason: string): ZkmlReviewResult {\n return { accept: false, dispute: true, reason };\n}\n\n/**\n * Buyer-layer auto-release predicate for zk-verified jobs. It resolves `proofUri` through\n * `resolveProofUri` to the pinned bundle, requires the bundle's content to re-hash to the\n * worker-submitted `contentHash`, and requires the proof's output, model and input to equal\n * that hash, the pinned model and the Buyer's input commitment (checked here, whatever\n * `verify` returns); `verify` then decides. Anything else DISPUTES. Disputing rather than\n * holding is deliberate -- a held SUBMITTED escrow is auto-released to the worker by the\n * 24h protocol timeout, so a buyer who required a proof contests a missing/invalid one\n * instead of letting it time out to release. This is the Buyer's judgment, not the\n * protocol's. Soundness lives in the `verify` option; the default reference verifier is a\n * demo and proves nothing on its own. A resolver that throws PROPAGATES: a transient infra\n * failure is not a verdict, so the caller retries it -- it is never silently converted into\n * a dispute. Construction throws `ADAPTER_CONFIG_ERROR` when a required option is missing.\n */\nexport function zkmlProofAutoRelease(opts: ZkmlProofAutoReleaseOptions): ZkmlReviewPolicy {\n // A JavaScript caller can pass no options at all; that is a config error, not a TypeError.\n const raw: unknown = opts;\n const given = (typeof raw === \"object\" && raw !== null ? raw : {}) as Partial<\n Record<keyof ZkmlProofAutoReleaseOptions, unknown>\n >;\n if (typeof given.resolveProofUri !== \"function\") {\n throw adapterConfigError(\"zkmlProofAutoRelease: `resolveProofUri` must be a function\");\n }\n for (const name of [\"modelCommitment\", \"inputCommitment\"] as const) {\n const value = given[name];\n if (typeof value !== \"string\" || value === \"\") {\n throw adapterConfigError(`zkmlProofAutoRelease: \\`${name}\\` must be a non-empty string`);\n }\n }\n const { resolveProofUri, modelCommitment, inputCommitment } = opts;\n const verify = opts.verify ?? verifyZkmlProof;\n return {\n name: \"zkml-proof-auto-release\",\n async evaluate(d: ZkmlDeliverable): Promise<ZkmlReviewResult> {\n if (d.proofUri === null || d.proofUri === \"\") {\n return dispute(\"no proofUri attached\");\n }\n const bundle = decodeZkmlProofUri(await resolveProofUri(d.proofUri));\n if (bundle === null) {\n return dispute(\"proofUri does not resolve to a decodable zkml bundle\");\n }\n const recomputed = sha256Hex(bundle.content);\n if (recomputed !== d.contentHash) {\n return dispute(\n \"bundle content does not hash to the submitted contentHash (tampered or wrong)\",\n );\n }\n if (bundle.proof.outputHash !== recomputed) {\n return dispute(\"zkml proof attests a different output than the bundle content\");\n }\n if (bundle.proof.modelCommitment !== modelCommitment) {\n return dispute(\"zkml proof attests a different model than the pinned one\");\n }\n if (bundle.proof.inputCommitment !== inputCommitment) {\n return dispute(\"zkml proof attests a different input than the buyer's commitment\");\n }\n const verdict = verify(bundle.proof, {\n contentHash: recomputed,\n modelCommitment,\n inputCommitment,\n });\n if (verdict.valid) {\n return {\n accept: true,\n dispute: false,\n reason: \"zkml proof verified against the re-hashed bundle content\",\n };\n }\n return dispute(`zkml proof ${verdict.category}: ${verdict.reason}`);\n },\n };\n}\n\n// ── Adapter ──────────────────────────────────────────────────────────────────────\n\n/** What an inference run yields: the output plus the commitments the proof binds. */\nexport interface ZkmlInferenceOutput {\n /** The deliverable content. */\n content: string;\n /** Commitment to the model that produced `content`. */\n modelCommitment: string;\n /** Commitment to the input the model was run on. */\n inputCommitment: string;\n}\n\n/** Configuration and injectable ports for {@link createZkmlAdapter}. */\nexport interface ZkmlAdapterConfig {\n /** Adapter id. Defaults to `\"zkml\"`. */\n id?: string;\n /** Advertised capabilities for EscroBots discovery. Defaults to `[\"zk-verified-inference\"]`. */\n capabilities?: string[];\n /** Inference port. Default: solves the canned demo job; a deterministic placeholder otherwise. */\n runInference?: (spec: TaskSpec) => Promise<ZkmlInferenceOutput> | ZkmlInferenceOutput;\n /** Proving port. Default: builds a reference proof binding the output to its commitments. */\n prove?: (args: {\n spec: TaskSpec;\n output: ZkmlInferenceOutput;\n outputHash: string;\n }) => Promise<ZkmlProof> | ZkmlProof;\n /**\n * Pinning port: receives the bundle document ({@link encodeZkmlProofUri}) and returns its\n * reference. Default: `ipfs://placeholder-<16 hex of the document's sha256>`, which stores\n * nothing; a production worker pins the document to IPFS/Arweave.\n */\n pin?: (document: string) => Promise<string> | string;\n /** Health-check port. Default: resolves `true`. */\n checkHealth?: () => Promise<boolean>;\n}\n\n/**\n * The canned zk-verified-inference demo job: a deterministic\n * classification the buyer template's demo journey hires this bot for.\n * Acceptance is machine-checkable by the buyer via {@link zkmlProofAutoRelease}.\n */\nexport const zkmlDemoJobSpec: TaskSpec = {\n version: \"1.0.0\",\n taskType: \"custom\",\n description:\n \"Run the canned zk-verified inference demo: classify the fixed demo input and \" +\n \"attach a proof that the output is the correct result of the committed model on \" +\n \"the committed input. Acceptance is deterministic and recomputed by the buyer: the \" +\n \"attached proof must verify against the submitted deliverable's contentHash.\",\n acceptanceCriteria: [\n {\n id: \"ac-proof-verifies\",\n description:\n \"The attached proof verifies against the submitted deliverable's contentHash, recomputed by the buyer.\",\n required: true,\n },\n ],\n deliverableFormat: { type: \"json\" },\n metadata: { demo: ZKML_DEMO_MARKER },\n};\n\n/** Commitment to the demo model: the value a buyer of the demo job pins. */\nexport const ZKML_DEMO_MODEL_COMMITMENT = sha256Hex(\"zkml-demo-classifier-v1\");\n\n/** The buyer's commitment over its own spec: the `inputCommitment` a proof must attest. */\nexport function computeZkmlInputCommitment(spec: TaskSpec): string {\n return sha256Hex(canonicalize(spec));\n}\n\n/**\n * The reference solution to the demo job: the classifier's output as canonical JSON.\n * Deterministic. Exposed so the demo journey and tests share one source of truth.\n */\nexport function solveZkmlDemo(): string {\n return canonicalize({\n model: \"zkml-demo-classifier-v1\",\n output: { label: \"cat\", confidence: 0.98 },\n });\n}\n\nfunction referencePlaceholderOutput(spec: TaskSpec): ZkmlInferenceOutput {\n return {\n content: canonicalize({\n note: \"reference stub - replace the runInference port with a real zk-verified inference call.\",\n taskType: spec.taskType,\n }),\n modelCommitment: sha256Hex(\"zkml-reference-stub-model\"),\n inputCommitment: computeZkmlInputCommitment(spec),\n };\n}\n\nconst defaultRunInference = (spec: TaskSpec): ZkmlInferenceOutput =>\n spec.metadata.demo === ZKML_DEMO_MARKER\n ? {\n content: solveZkmlDemo(),\n modelCommitment: ZKML_DEMO_MODEL_COMMITMENT,\n inputCommitment: computeZkmlInputCommitment(spec),\n }\n : referencePlaceholderOutput(spec);\n\n/**\n * Build a ZKML {@link ServiceAdapter}. `execute` pins the bundle of the delivered content and\n * its proof and returns that document's reference as `proofUri`. Passes\n * `assertServiceAdapterContract` with the default ports; the default pin stores nothing, so\n * a release needs a real pin and the buyer's `resolveProofUri` in {@link zkmlProofAutoRelease}.\n * Supply real ports (a genuine inference call, a real prover, a pin to IPFS/Arweave) for\n * production use.\n */\nexport function createZkmlAdapter(config: ZkmlAdapterConfig = {}): ServiceAdapter {\n const id = config.id ?? ZKML_ADAPTER_ID;\n const capabilities = config.capabilities ?? [...ZKML_CAPABILITIES];\n const runInference = config.runInference ?? defaultRunInference;\n const prove =\n config.prove ??\n ((args: { output: ZkmlInferenceOutput; outputHash: string }): ZkmlProof =>\n buildZkmlProof({\n modelCommitment: args.output.modelCommitment,\n inputCommitment: args.output.inputCommitment,\n outputHash: args.outputHash,\n }));\n const pin =\n config.pin ??\n ((document: string): string => `ipfs://placeholder-${sha256Hex(document).slice(0, 16)}`);\n const checkHealth = config.checkHealth ?? ((): Promise<boolean> => Promise.resolve(true));\n\n return {\n id,\n capabilities,\n async execute(spec: TaskSpec): Promise<ServiceResult> {\n const output = await runInference(spec);\n const contentHash = sha256Hex(output.content);\n const proof = await prove({ spec, output, outputHash: contentHash });\n const proofUri = await pin(encodeZkmlProofUri({ content: output.content, proof }));\n return {\n content: output.content,\n contentHash,\n proofUri,\n metadata: {\n adapterId: id,\n scheme: proof.scheme,\n modelCommitment: proof.modelCommitment,\n },\n };\n },\n healthCheck(): Promise<boolean> {\n return checkHealth();\n },\n };\n}\n","// The guards a surface that lets an agent call pay() applies before it does: the URL's host must be\n// public, and an escrow entry's deadline must fall within a bound; and the address rule it hands\n// pay() so the transport judges what it connects to. pay() itself stays policy-free about hosts.\n// This module resolves nothing: the caller passes its own resolver, so this file carries no\n// node:dns import.\nimport { SOLANA_CAIP2_DEVNET, SOLANA_CAIP2_MAINNET } from \"@escro/shared\";\n\nimport { EscroError, EscroPayError } from \"./errors.js\";\nimport type { PayParams, PayPolicy } from \"./payments.js\";\nimport type { EscroOptions } from \"./types.js\";\n\n/** Why {@link payUrlRefusal} refuses a URL; each surface turns a kind into its own sentence. */\nexport type PayUrlRefusal = \"private_host\" | \"unresolved_host\" | \"mainnet_http\";\n\n/** node:dns/promises' lookup satisfies it; the SDK resolves nothing itself. */\nexport type HostLookup = (\n hostname: string,\n options: { all: true },\n) => Promise<readonly { address: string }[]>;\n\n/** A strict dotted quad: four decimal octets, no leading zero, nothing else. */\nfunction parseIpv4(text: string): number | null {\n const octets = text.split(\".\");\n if (octets.length !== 4) return null;\n let n = 0;\n for (const octet of octets) {\n if (!/^(?:0|[1-9][0-9]{0,2})$/.test(octet) || Number(octet) > 255) return null;\n n = n * 256 + Number(octet);\n }\n return n;\n}\n\n/** The 16-bit groups of one side of an IPv6 `::`; a dotted IPv4 tail only as the address's last field. */\nfunction ipv6Groups(side: string, holdsTail: boolean): number[] | null {\n if (side === \"\") return [];\n const fields = side.split(\":\");\n const groups: number[] = [];\n for (const [i, field] of fields.entries()) {\n if (holdsTail && i === fields.length - 1 && field.includes(\".\")) {\n const v4 = parseIpv4(field);\n if (v4 === null) return null;\n groups.push(Math.floor(v4 / 0x10000), v4 % 0x10000);\n } else if (/^[0-9a-f]{1,4}$/i.test(field)) {\n groups.push(parseInt(field, 16));\n } else {\n return null;\n }\n }\n return groups;\n}\n\n/** An IPv6 address without brackets, hex or dotted-tail; a zone id, or any other character, does not parse. */\nfunction parseIpv6(text: string): bigint | null {\n if (!/^[0-9a-f:.]+$/i.test(text)) return null;\n const sides = text.split(\"::\");\n if (sides.length > 2) return null;\n const [head = \"\", tail] = sides;\n const left = ipv6Groups(head, tail === undefined);\n const right = tail === undefined ? [] : ipv6Groups(tail, true);\n if (left === null || right === null) return null;\n const explicit = left.length + right.length;\n if (tail === undefined ? explicit !== 8 : explicit > 7) return null;\n const groups = [...left, ...new Array<number>(8 - explicit).fill(0), ...right];\n return groups.reduce((n, group) => (n << 16n) | BigInt(group), 0n);\n}\n\ninterface Ipv4Range {\n base: number;\n bits: number;\n}\ninterface Ipv6Range {\n base: bigint;\n bits: number;\n}\n\nfunction ipv4Range(cidr: string): Ipv4Range {\n const [address = \"\", bits = \"\"] = cidr.split(\"/\");\n const base = parseIpv4(address);\n if (base === null) throw new Error(`the refused set holds an unparseable range ${cidr}`);\n return { base, bits: Number(bits) };\n}\n\nfunction ipv6Range(cidr: string): Ipv6Range {\n const [address = \"\", bits = \"\"] = cidr.split(\"/\");\n const base = parseIpv6(address);\n if (base === null) throw new Error(`the refused set holds an unparseable range ${cidr}`);\n return { base, bits: Number(bits) };\n}\n\nconst inIpv4Range = (n: number, { base, bits }: Ipv4Range): boolean =>\n Math.floor(n / 2 ** (32 - bits)) === Math.floor(base / 2 ** (32 - bits));\n\nconst inIpv6Range = (n: bigint, { base, bits }: Ipv6Range): boolean =>\n n >> BigInt(128 - bits) === base >> BigInt(128 - bits);\n\n/** Every IPv4 range a pay action does not reach without the operator's opt-in. */\nconst REFUSED_IPV4 = [\n \"0.0.0.0/8\",\n \"10.0.0.0/8\",\n \"100.64.0.0/10\",\n \"127.0.0.0/8\",\n \"168.63.129.16/32\",\n \"169.254.0.0/16\",\n \"172.16.0.0/12\",\n \"192.0.0.0/24\",\n \"192.168.0.0/16\",\n \"198.18.0.0/15\",\n \"224.0.0.0/4\",\n \"240.0.0.0/4\",\n].map(ipv4Range);\n\n/** Every IPv6 range refused whole; Teredo and 6to4 each embed an IPv4 address a relay reaches. */\nconst REFUSED_IPV6 = [\n \"::/128\",\n \"::1/128\",\n \"fc00::/7\",\n \"fe80::/10\",\n \"fec0::/10\",\n \"ff00::/8\",\n \"2001::/32\",\n \"2002::/16\",\n \"64:ff9b:1::/48\",\n].map(ipv6Range);\n\n/** IPv4-mapped, IPv4-compatible and NAT64: an address here is classed by its embedded IPv4 address. */\nconst IPV4_EMBEDDINGS = [\"::ffff:0:0/96\", \"::/96\", \"64:ff9b::/96\"].map(ipv6Range);\n\n/**\n * True only for text that parses as an IPv4 or IPv6 address (no brackets, no zone id) outside the\n * refused set, so an unknown form (a name, a zone id, a non-strict quad) is never public.\n */\nexport function isPublicAddress(address: string): boolean {\n const v4 = parseIpv4(address);\n if (v4 !== null) return !REFUSED_IPV4.some((range) => inIpv4Range(v4, range));\n const v6 = parseIpv6(address);\n if (v6 === null) return false;\n if (REFUSED_IPV6.some((range) => inIpv6Range(v6, range))) return false;\n if (IPV4_EMBEDDINGS.some((range) => inIpv6Range(v6, range))) {\n return isPublicAddress(\n [24n, 16n, 8n, 0n].map((shift) => String((v6 >> shift) & 0xffn)).join(\".\"),\n );\n }\n return true;\n}\n\n/** RFC 6761 section 6.3: these names are loopback and are never looked up. */\nfunction isLocalhostName(hostname: string): boolean {\n const name = (hostname.endsWith(\".\") ? hostname.slice(0, -1) : hostname).toLowerCase();\n return name === \"localhost\" || name.endsWith(\".localhost\");\n}\n\n/** A literal or `localhost` host's class without a lookup; null for a name that must be resolved. */\nfunction literalReach(hostname: string): \"public\" | \"private\" | null {\n if (hostname.startsWith(\"[\") && hostname.endsWith(\"]\")) {\n return isPublicAddress(hostname.slice(1, -1)) ? \"public\" : \"private\";\n }\n if (parseIpv4(hostname) !== null) return isPublicAddress(hostname) ? \"public\" : \"private\";\n if (isLocalhostName(hostname)) return \"private\";\n return null;\n}\n\n/**\n * A name's class from one resolution, or null when the lookup rejects or answers nothing. A name\n * re-pointed between this check and the request (DNS rebinding) is not caught here.\n */\nasync function nameReach(\n hostname: string,\n lookup: HostLookup,\n): Promise<\"public\" | \"private\" | \"mixed\" | null> {\n let answers: readonly { address: string }[];\n try {\n answers = await lookup(hostname, { all: true });\n } catch {\n return null;\n }\n if (answers.length === 0) return null;\n const publicCount = answers.filter(({ address }) => isPublicAddress(address)).length;\n if (publicCount === answers.length) return \"public\";\n return publicCount === 0 ? \"private\" : \"mixed\";\n}\n\n/**\n * Whether a pay action may reach `url`, before any request, signature or funding: on any cluster\n * but devnet an `http:` URL to a host the operator has not admitted as private is refused, and\n * without the opt-in any host that is not public is refused. Null admits, and leaves a URL that does\n * not parse, or is not http or https, to pay()'s own refusal. Resolves the host at most once, and\n * only when the answer decides.\n */\nexport async function payUrlRefusal(\n url: string,\n options: {\n cluster: EscroOptions[\"cluster\"] | undefined;\n allowPrivateHosts: boolean;\n lookup: HostLookup;\n },\n): Promise<PayUrlRefusal | null> {\n if (!URL.canParse(url)) return null;\n const { protocol, hostname } = new URL(url);\n if (protocol !== \"http:\" && protocol !== \"https:\") return null;\n const allowPrivate = options.allowPrivateHosts;\n const mainnetHttp = options.cluster !== \"devnet\" && protocol === \"http:\";\n if (mainnetHttp && !allowPrivate) return \"mainnet_http\";\n if (allowPrivate && !mainnetHttp) return null;\n const literal = literalReach(hostname);\n if (!allowPrivate && literal === \"private\") return \"private_host\";\n const reach = literal ?? (await nameReach(hostname, options.lookup));\n if (reach === null) return \"unresolved_host\";\n if (!allowPrivate) return reach === \"public\" ? null : \"private_host\";\n // https: is required on mainnet for a public network path; a host the operator declared local has none.\n return reach === \"private\" ? null : \"mainnet_http\";\n}\n\n/**\n * The address rule a surface passes as PayParams.admitAddress, for the URL it checked with\n * {@link payUrlRefusal}. Without the opt-in both targets admit exactly the public addresses. With it,\n * on any cluster but devnet over http:, the resource admits exactly the addresses that are not\n * public (a host the operator declared local has no public network path) and the spec host, always\n * https:, admits every address. With the opt-in otherwise there is no rule (undefined). A URL that\n * does not parse, or is not http or https, takes the rule without the opt-in.\n */\nexport function payAddressRule(options: {\n cluster: EscroOptions[\"cluster\"] | undefined;\n allowPrivateHosts: boolean;\n url: string;\n}): PayParams[\"admitAddress\"] {\n const publicOnly = (address: string): boolean => isPublicAddress(address);\n if (!URL.canParse(options.url)) return publicOnly;\n const { protocol } = new URL(options.url);\n if (protocol !== \"http:\" && protocol !== \"https:\") return publicOnly;\n if (!options.allowPrivateHosts) return publicOnly;\n if (options.cluster !== \"devnet\" && protocol === \"http:\") {\n return (address, target) => target === \"spec\" || !isPublicAddress(address);\n }\n return undefined;\n}\n\nconst ESCROW_RAIL_SCHEMES: readonly string[] = [\"on-delivery\", \"job-escrow\"];\n\n/**\n * pay()'s own rail choice with a deadline bound added: an escrow entry on the caller's terms is\n * returned only when its deadline is at most now plus `maxDeadlineSeconds`, and is never passed over\n * for an `exact` entry; an `exact` entry is returned only when no escrow entry is on the terms, and\n * never with `escrowOnly`. Only entries on the cluster's network are on the terms: devnet's for\n * `\"devnet\"`, mainnet's for any other value, as {@link payUrlRefusal} reads a cluster. Refusals carry\n * the caller's values only, never the 402's text. The clock (`now`, milliseconds, default\n * `Date.now`) is read each time the policy runs, which pay() does before its first chain read, spec\n * fetch or signature.\n */\nexport function deadlineBoundedPolicy(terms: {\n to: string;\n amountMicroUsdc: number;\n cluster: EscroOptions[\"cluster\"] | undefined;\n maxDeadlineSeconds: number;\n escrowOnly?: boolean;\n now?: () => number;\n}): PayPolicy {\n const bound = terms.maxDeadlineSeconds;\n if (!Number.isSafeInteger(bound) || bound < 1) {\n throw new EscroError(\n `maxDeadlineSeconds must be a positive whole number of seconds, got ${String(bound)}`,\n \"VALIDATION_ERROR\",\n );\n }\n const escrowOnly: unknown = terms.escrowOnly;\n if (escrowOnly !== undefined && typeof escrowOnly !== \"boolean\") {\n throw new EscroError(\n `escrowOnly must be true, false or absent, got ${typeof escrowOnly}`,\n \"VALIDATION_ERROR\",\n );\n }\n // Date is looked up on each run, not captured here, so a Date replaced after the build is the one read.\n const now = terms.now ?? (() => Date.now());\n const amount = String(terms.amountMicroUsdc);\n const network = terms.cluster === \"devnet\" ? SOLANA_CAIP2_DEVNET : SOLANA_CAIP2_MAINNET;\n return (accepts) => {\n const reading: unknown = now();\n if (typeof reading !== \"number\" || !Number.isSafeInteger(reading)) {\n throw new EscroError(\n \"The pay policy's clock must return whole milliseconds; nothing was signed or funded\",\n \"VALIDATION_ERROR\",\n );\n }\n const latest = Math.floor(reading / 1000) + bound;\n const onTerms = accepts.filter(\n (entry) => entry.payTo === terms.to && entry.amount === amount && entry.network === network,\n );\n const escrowEntries = onTerms.filter((entry) => ESCROW_RAIL_SCHEMES.includes(entry.scheme));\n if (escrowEntries.length > 0) {\n const inBound = escrowEntries.find((entry) => {\n const deadline = entry.extra?.deadline;\n return typeof deadline === \"number\" && Number.isSafeInteger(deadline) && deadline <= latest;\n });\n if (inBound !== undefined) return inBound;\n throw new EscroPayError(\n \"no_eligible_entry\",\n \"The 402 offers no escrow entry paying this worker this amount with a deadline at or before \" +\n `${String(latest)} (Unix seconds: now plus ${String(bound)}). Nothing was signed or funded.`,\n { detail: \"deadline\" },\n );\n }\n if (escrowOnly === true) {\n throw new EscroPayError(\n \"no_eligible_entry\",\n `The 402 offers no escrow entry paying ${amount} micro-USDC to ${terms.to}. Nothing was signed or funded.`,\n { detail: \"escrow_only\" },\n );\n }\n const exact = onTerms.find((entry) => entry.scheme === \"exact\");\n if (exact !== undefined) return exact;\n const [first] = onTerms;\n // An unknown scheme is never returned: the router's refusal would repeat the 402's scheme text.\n if (first !== undefined && onTerms.every((entry) => entry.scheme === \"upto\")) return first;\n throw new EscroPayError(\n \"no_eligible_entry\",\n `The 402 offers no entry paying ${amount} micro-USDC to ${terms.to}`,\n );\n };\n}\n","// A route's `bazaar` declaration (x402 `specs/extensions/bazaar.md` at e4a086819f419e9395acbbdc1679fe6627029ff7),\n// built by hand: a discovery catalog reads `info` to call the endpoint and checks it against `schema`.\nimport type { BazaarDeclaration } from \"@escro/shared\";\n\nconst DRAFT_2020_12 = \"https://json-schema.org/draft/2020-12/schema\";\nconst BODY_METHODS = [\"POST\", \"PUT\", \"PATCH\"];\nconst QUERY_METHODS = [\"GET\", \"HEAD\", \"DELETE\"];\n\nexport interface BuildBazaarDeclarationOptions {\n method: \"GET\" | \"POST\";\n /** The example request: the JSON body of a POST, the query parameters of a GET. */\n example: Record<string, unknown>;\n /** The example response. */\n output?: { type: string; example?: unknown };\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\n/** Where `value` would not come back deep-equal from a JSON round trip; undefined when it would. */\nfunction jsonFault(value: unknown, at: string): string | undefined {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return undefined;\n if (typeof value === \"number\") {\n return Number.isFinite(value) && !Object.is(value, -0)\n ? undefined\n : `${at} is ${String(value)}`;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i += 1) {\n if (!(i in value)) return `${at}[${String(i)}] is a hole`;\n const fault = jsonFault(value[i], `${at}[${String(i)}]`);\n if (fault !== undefined) return fault;\n }\n return undefined;\n }\n if (isPlainObject(value)) {\n if (Object.getOwnPropertySymbols(value).length > 0) return `${at} has a symbol key`;\n for (const [key, member] of Object.entries(value)) {\n const fault = jsonFault(member, `${at}.${key}`);\n if (fault !== undefined) return fault;\n }\n return undefined;\n }\n return `${at} is not JSON (${typeof value})`;\n}\n\nconst copy = <T>(value: T): T => JSON.parse(JSON.stringify(value)) as T;\n\n/**\n * The `bazaar` declaration of an HTTP route: a POST takes `example` as its JSON body, a GET as its query parameters;\n * the schema requires `input.type` \"http\" and a method of the route's family. Throws an Error naming `example` when it\n * is not a plain object that survives a JSON round trip, and naming `output.type` when that is empty. The declaration\n * is a copy: a later change to `example` or `output` does not reach it.\n */\nexport function buildBazaarDeclaration(options: BuildBazaarDeclarationOptions): BazaarDeclaration {\n const { method, example, output } = options;\n if (!isPlainObject(example)) {\n throw new Error(\"buildBazaarDeclaration: example must be a plain object\");\n }\n const exampleFault = jsonFault(example, \"example\");\n if (exampleFault !== undefined) {\n throw new Error(\n `buildBazaarDeclaration: example must survive a JSON round trip: ${exampleFault}`,\n );\n }\n if (output !== undefined) {\n if (typeof output.type !== \"string\" || output.type === \"\") {\n throw new Error(\"buildBazaarDeclaration: output.type must be a non-empty string\");\n }\n const outputFault = jsonFault(output.example, \"output.example\");\n if (output.example !== undefined && outputFault !== undefined) {\n throw new Error(\n `buildBazaarDeclaration: output.example must survive a JSON round trip: ${outputFault}`,\n );\n }\n }\n const input: BazaarDeclaration[\"info\"][\"input\"] =\n method === \"POST\"\n ? { type: \"http\", method: \"POST\", bodyType: \"json\", body: copy(example) }\n : { type: \"http\", method: \"GET\", queryParams: copy(example) };\n return {\n info: { input, ...(output === undefined ? {} : { output: copy(output) }) },\n schema: {\n $schema: DRAFT_2020_12,\n type: \"object\",\n properties: {\n input: {\n type: \"object\",\n properties: {\n type: { const: \"http\" },\n method: { enum: method === \"POST\" ? [...BODY_METHODS] : [...QUERY_METHODS] },\n },\n required: [\"type\", \"method\"],\n },\n },\n required: [\"input\"],\n },\n };\n}\n","// The worker's own `exact` entry: the cluster's USDC paid straight to the worker, the transaction fee paid by the\n// facilitator's fee payer. Network and asset come from config, never from the caller.\nimport {\n getCaip2Network,\n getUsdcMint,\n type PaymentRequirements,\n type SolanaCluster,\n type SupportedResponse,\n} from \"@escro/shared\";\nimport { isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { ExactAcceptError } from \"./errors.js\";\n\nconst U64_MAX = 2n ** 64n - 1n;\n/** Below this a facilitator's verify and settle cannot both land inside the buyer's window. */\nconst MIN_MAX_TIMEOUT_SECONDS = 10;\n/** An hour: the menu times the paid answer with `setTimeout`, which overflows above about 2 147 483 s. */\nconst MAX_MAX_TIMEOUT_SECONDS = 3_600;\n\nexport interface BuildExactAcceptOptions {\n cluster: SolanaCluster;\n amountMicroUsdc: bigint;\n /** The worker's own wallet. */\n payTo: string;\n /** The facilitator's fee payer, from its `/supported` answer ({@link exactFeePayer}). */\n feePayer: string;\n maxTimeoutSeconds: number;\n}\n\n/**\n * The `exact` entry a worker offers beside its `on-delivery` entry. Throws {@link ExactAcceptError} for a `payTo` or\n * `feePayer` that is not a canonical key, a fee payer that is the worker itself, an amount outside 1..2^64-1, or a\n * `maxTimeoutSeconds` that is not a whole number from 10 to 3600.\n */\nexport function buildExactAccept(options: BuildExactAcceptOptions): PaymentRequirements {\n const { cluster, amountMicroUsdc, payTo, feePayer, maxTimeoutSeconds } = options;\n if (!isCanonicalPubkey(payTo)) {\n throw new ExactAcceptError(\"pay_to\", \"payTo is not a canonical public key\");\n }\n if (!isCanonicalPubkey(feePayer)) {\n throw new ExactAcceptError(\"fee_payer\", \"The fee payer is not a canonical public key\");\n }\n if (feePayer === payTo) {\n throw new ExactAcceptError(\"fee_payer\", \"The fee payer is the worker's own wallet\");\n }\n if (amountMicroUsdc < 1n || amountMicroUsdc > U64_MAX) {\n throw new ExactAcceptError(\"amount\", \"The amount is not between 1 and 2^64 - 1 micro-USDC\");\n }\n if (\n !Number.isSafeInteger(maxTimeoutSeconds) ||\n maxTimeoutSeconds < MIN_MAX_TIMEOUT_SECONDS ||\n maxTimeoutSeconds > MAX_MAX_TIMEOUT_SECONDS\n ) {\n throw new ExactAcceptError(\n \"max_timeout\",\n `maxTimeoutSeconds must be a whole number from ${String(MIN_MAX_TIMEOUT_SECONDS)} to ${String(MAX_MAX_TIMEOUT_SECONDS)}`,\n );\n }\n return {\n scheme: \"exact\",\n network: getCaip2Network(cluster),\n amount: amountMicroUsdc.toString(),\n asset: getUsdcMint(cluster),\n payTo,\n maxTimeoutSeconds,\n extra: { feePayer },\n };\n}\n\n/**\n * The `extra.feePayer` of the first x402 V2 `exact` kind on the cluster's network in a facilitator's `/supported`\n * answer; undefined when none names one. Its validity is {@link buildExactAccept}'s to check.\n */\nexport function exactFeePayer(\n supported: SupportedResponse,\n cluster: SolanaCluster,\n): string | undefined {\n const network = getCaip2Network(cluster);\n for (const kind of supported.kinds) {\n if (kind.x402Version !== 2 || kind.scheme !== \"exact\" || kind.network !== network) continue;\n const feePayer = kind.extra?.feePayer;\n if (typeof feePayer === \"string\") return feePayer;\n }\n return undefined;\n}\n","// A facilitator over HTTP: @x402/core's HTTPFacilitatorClient, at the SDK's exact pin, reached only through the one\n// lazy import below, so a process that never settles an `exact` payment never executes it. Its refusals that carry an\n// answer resolve as that answer; every other failure is an EscroFacilitatorError with the URL redacted.\nimport {\n redactRpcUrl,\n type Facilitator,\n type PaymentPayload,\n type PaymentRequirements,\n type SettlementResponse,\n type SupportedResponse,\n type VerifyResponse,\n} from \"@escro/shared\";\nimport type {\n PaymentPayload as CorePaymentPayload,\n PaymentRequirements as CorePaymentRequirements,\n} from \"@x402/core/types\";\nimport type { HTTPFacilitatorClient } from \"@x402/core/http\";\n\nimport { EscroFacilitatorError, type FacilitatorOperation } from \"./errors.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst URL_RULE =\n \"A facilitator URL must be an https: URL with no username, password, query or fragment\";\n\nexport interface HttpFacilitatorOptions {\n /** `https:`, with no userinfo, query or fragment; a path is allowed. */\n url: string;\n /** Per request. Default 30 000. */\n timeoutMs?: number;\n}\n\n/** Throws a TypeError naming the rule, never the URL. */\nfunction requireFacilitatorUrl(url: string): void {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new TypeError(URL_RULE);\n }\n if (\n parsed.protocol !== \"https:\" ||\n parsed.username !== \"\" ||\n parsed.password !== \"\" ||\n parsed.href.includes(\"?\") ||\n parsed.href.includes(\"#\")\n ) {\n throw new TypeError(URL_RULE);\n }\n}\n\nconst isError = (value: unknown): value is Error & Record<string, unknown> =>\n value instanceof Error;\n\nconst stringMember = (value: Record<string, unknown>, name: string): string | undefined => {\n const member = value[name];\n return typeof member === \"string\" ? member : undefined;\n};\n\n/**\n * A facilitator at `url`. Synchronous and offline: the client is loaded and built on the first call, once per\n * facilitator. Throws a TypeError, naming the rule and never the URL, for a URL that is not `https:` or carries a\n * username, password, query or fragment.\n */\nexport function createHttpFacilitator(options: HttpFacilitatorOptions): Facilitator {\n const { url } = options;\n requireFacilitatorUrl(url);\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n let client: Promise<HTTPFacilitatorClient> | undefined;\n\n const load = (): Promise<HTTPFacilitatorClient> => {\n if (client !== undefined) return client;\n const loading = import(\"@x402/core/http\").then(\n (http) => new http.HTTPFacilitatorClient({ url, timeoutMs }),\n );\n // A failed load is retried by the next call, not remembered.\n loading.catch(() => {\n if (client === loading) client = undefined;\n });\n client = loading;\n return loading;\n };\n\n const unavailable = (operation: FacilitatorOperation, err: unknown): EscroFacilitatorError => {\n const upstream = isError(err) ? err.message : String(err);\n return new EscroFacilitatorError(\n operation,\n `The facilitator's ${operation} failed: ${redactRpcUrl(upstream, [url], \"<facilitatorUrl>\")}`,\n );\n };\n\n return {\n async verify(payment: PaymentPayload, requirements: PaymentRequirements) {\n try {\n const http = await load();\n const answer: VerifyResponse = await http.verify(\n payment as CorePaymentPayload,\n requirements as CorePaymentRequirements,\n );\n return answer;\n } catch (err) {\n const invalidReason = isError(err) ? stringMember(err, \"invalidReason\") : undefined;\n if (isError(err) && err.name === \"VerifyError\" && invalidReason !== undefined) {\n return { isValid: false, invalidReason };\n }\n throw unavailable(\"verify\", err);\n }\n },\n async settle(payment: PaymentPayload, requirements: PaymentRequirements) {\n try {\n const http = await load();\n const answer: SettlementResponse = await http.settle(\n payment as CorePaymentPayload,\n requirements as CorePaymentRequirements,\n );\n return answer;\n } catch (err) {\n const errorReason = isError(err) ? stringMember(err, \"errorReason\") : undefined;\n if (isError(err) && err.name === \"SettleError\" && errorReason !== undefined) {\n // A pending settlement's signature is kept: the transfer may already have been sent.\n return {\n success: false,\n errorReason,\n transaction: stringMember(err, \"transaction\") ?? \"\",\n network: stringMember(err, \"network\") ?? \"\",\n };\n }\n throw unavailable(\"settle\", err);\n }\n },\n async getSupported() {\n try {\n const http = await load();\n const answer: SupportedResponse = await http.getSupported();\n return answer;\n } catch (err) {\n throw unavailable(\"supported\", err);\n }\n },\n };\n}\n","// The worker's check of a presented `on-delivery` payload, over RPC alone\n// (docs/specs/scheme_on_delivery_svm.md, \"Server, per paid request\"), against requirements the\n// server derives itself and never against the payment's `accepted`.\nimport bs58 from \"bs58\";\nimport nacl from \"tweetnacl\";\nimport { PublicKey, SystemProgram, type Connection } from \"@solana/web3.js\";\nimport {\n clusterOfCaip2,\n getProgramId,\n isRecord,\n type OnDeliveryAccept,\n type OnDeliveryPayloadFields,\n type PaymentPayload,\n} from \"@escro/shared\";\nimport { deriveEscrowPda, isCanonicalPubkey } from \"@escro/shared/solana\";\n\nimport { ChainReadError, decodeEscrowAccount, type DecodedEscrowAccount } from \"../chain-read.js\";\nimport { EscroError } from \"../errors.js\";\nimport { amountOf, isOnDeliveryScheme, isSpecHash } from \"./accept.js\";\nimport { buyerMessage, isAbsoluteHttpUrl, isSignedAt } from \"./buyer-signature.js\";\nimport { hasMembers } from \"./extension.js\";\n\n/**\n * The record of accepted presentations a server keeps; one per server, never module state.\n */\nexport interface ReplayStore {\n /**\n * Records `key` until `expiresAtMs` (inclusive) and returns true; returns false when `key` is held and unexpired at\n * `nowMs`. Atomic per key (a shared store: Redis `SET NX PX`, Postgres `INSERT ... ON CONFLICT DO NOTHING`). A claim\n * is spent before the account read: a presentation that fails a later step is re-signed.\n */\n claim(key: string, expiresAtMs: number, nowMs: number): boolean | Promise<boolean>;\n}\n\n/**\n * An in-memory {@link ReplayStore}: one map per call, held by this process only, so it suits a\n * single-process server; servers behind a load balancer share a store. Each claim drops the keys\n * expired at its `nowMs`. `size` is the number of keys held.\n */\nexport function memoryReplayStore(): ReplayStore & { readonly size: number } {\n const held = new Map<string, number>();\n return {\n claim(key: string, expiresAtMs: number, nowMs: number): boolean {\n for (const [stale, expiry] of held) {\n if (expiry < nowMs) held.delete(stale);\n }\n if (held.has(key)) return false;\n held.set(key, expiresAtMs);\n return true;\n },\n get size(): number {\n return held.size;\n },\n };\n}\n\n/** The binding's error-code table, in its order. */\nexport const ON_DELIVERY_SVM_INVALID_REASONS = [\n \"invalid_on_delivery_svm_payload\",\n \"invalid_on_delivery_svm_escrow_address_mismatch\",\n \"invalid_on_delivery_svm_buyer_signature\",\n \"invalid_on_delivery_svm_signature_expired\",\n \"invalid_on_delivery_svm_escrow_not_found\",\n \"invalid_on_delivery_svm_escrow_owner\",\n \"invalid_on_delivery_svm_escrow_version\",\n \"invalid_on_delivery_svm_wrong_state\",\n \"invalid_on_delivery_svm_buyer_mismatch\",\n \"invalid_on_delivery_svm_worker_mismatch\",\n \"invalid_on_delivery_svm_amount_mismatch\",\n \"invalid_on_delivery_svm_spec_hash_mismatch\",\n \"invalid_on_delivery_svm_deadline\",\n \"invalid_on_delivery_svm_claim_failed\",\n] as const;\n\nexport type OnDeliveryInvalidReason =\n | (typeof ON_DELIVERY_SVM_INVALID_REASONS)[number]\n | \"invalid_x402_version\"\n | \"invalid_scheme\"\n | \"invalid_network\"\n | \"invalid_payment_requirements\";\n\nexport interface VerifyPresentationContext {\n /** The absolute URL this server is serving: the paid route, or the poll URL for a poll. */\n resourceUrl: string;\n replay: ReplayStore;\n /** Unix milliseconds. */\n now?: () => number;\n}\n\nexport interface VerifyEscrowContext extends VerifyPresentationContext {\n rpc: Pick<Connection, \"getAccountInfo\">;\n}\n\nexport type BuyerPresentationResult =\n | { isValid: true; payer: string }\n | { isValid: false; invalidReason: OnDeliveryInvalidReason };\n\n/** `payer` is set on an invalid verdict exactly when the buyer's signature verified. */\nexport type OnDeliveryVerifyResult =\n | { isValid: true; payer: string; job: \"new\" | \"retry\"; escrow: DecodedEscrowAccount }\n | { isValid: false; invalidReason: OnDeliveryInvalidReason; payer?: string };\n\nconst WINDOW_MS = 30_000;\nconst MAX_TASK_ID_BYTES = 32;\n// The longest base58 text of 32 and of 64 bytes. Base58 decoding is quadratic in the text's\n// length, so longer text is refused before it is decoded.\nconst MAX_KEY_CHARS = 44;\nconst MAX_SIGNATURE_CHARS = 88;\nconst PAYLOAD_FIELDS = [\n \"escrow\",\n \"buyer\",\n \"taskId\",\n \"createSignature\",\n \"signedAt\",\n \"buyerSignature\",\n];\n/** RFC 8032's group order: a signature's S must be below it (section 5.1.7). */\nconst ED25519_L = 2n ** 252n + 27742317777372353535851937790883648493n;\n\nconst refused = (\n invalidReason: OnDeliveryInvalidReason,\n): { isValid: false; invalidReason: OnDeliveryInvalidReason } => ({\n isValid: false,\n invalidReason,\n});\n\nfunction isSignature(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length > MAX_SIGNATURE_CHARS) return false;\n try {\n return bs58.decode(value).length === 64;\n } catch {\n return false;\n }\n}\n\n/** S, bytes 32 to 63 little-endian, is below L. */\nfunction canonicalS(signature: Uint8Array): boolean {\n let s = 0n;\n for (let i = 63; i >= 32; i -= 1) s = (s << 8n) | BigInt(signature[i] ?? 0);\n return s < ED25519_L;\n}\n\n/** The server's own entry is one it can verify against: its program is the one pinned for its network. */\nfunction wellFormedEntry(entry: unknown): boolean {\n if (!isRecord(entry) || !isOnDeliveryScheme(entry.scheme) || typeof entry.network !== \"string\") {\n return false;\n }\n const cluster = clusterOfCaip2(entry.network);\n const extra = entry.extra;\n return (\n cluster !== undefined &&\n isRecord(extra) &&\n extra.program === getProgramId(cluster) &&\n typeof entry.payTo === \"string\" &&\n isCanonicalPubkey(entry.payTo) &&\n amountOf(entry.amount) !== undefined &&\n isSpecHash(extra.specHash) &&\n typeof extra.deadline === \"number\" &&\n Number.isSafeInteger(extra.deadline)\n );\n}\n\nconst isKeyText = (value: unknown): value is string =>\n typeof value === \"string\" && value.length <= MAX_KEY_CHARS && isCanonicalPubkey(value);\n\n/** The six payload fields, each well formed (binding server step 1); undefined otherwise. */\nfunction payloadFields(payload: unknown): OnDeliveryPayloadFields | undefined {\n if (!hasMembers(payload, PAYLOAD_FIELDS)) return undefined;\n const { escrow, buyer, taskId, createSignature, signedAt, buyerSignature } = payload;\n if (!isKeyText(escrow) || !isKeyText(buyer)) return undefined;\n if (typeof taskId !== \"string\" || new TextEncoder().encode(taskId).length > MAX_TASK_ID_BYTES) {\n return undefined;\n }\n if (!isSignature(createSignature) || !isSignature(buyerSignature) || !isSignedAt(signedAt)) {\n return undefined;\n }\n return { escrow, buyer, taskId, createSignature, signedAt, buyerSignature };\n}\n\nfunction requireContext(ctx: unknown): void {\n const replay = isRecord(ctx) ? ctx.replay : undefined;\n if (!isRecord(replay) || typeof replay.claim !== \"function\") {\n throw new EscroError(\n \"Verification needs ctx.replay: the ReplayStore that records each accepted presentation\",\n \"VALIDATION_ERROR\",\n );\n }\n const resourceUrl = isRecord(ctx) ? ctx.resourceUrl : undefined;\n if (typeof resourceUrl !== \"string\" || !isAbsoluteHttpUrl(resourceUrl)) {\n throw new EscroError(\n \"Verification needs ctx.resourceUrl: the absolute http: or https: URL being served\",\n \"VALIDATION_ERROR\",\n );\n }\n}\n\n/** Binding server steps 1 to 3, after the requirement and core checks. */\nasync function presentation(\n payment: PaymentPayload,\n entry: OnDeliveryAccept,\n ctx: VerifyPresentationContext,\n): Promise<\n { fields: OnDeliveryPayloadFields } | { isValid: false; invalidReason: OnDeliveryInvalidReason }\n> {\n requireContext(ctx);\n if (!wellFormedEntry(entry)) return refused(\"invalid_payment_requirements\");\n const presented: unknown = payment;\n if (!isRecord(presented) || presented.x402Version !== 2) return refused(\"invalid_x402_version\");\n const accepted = presented.accepted;\n if (!isRecord(accepted) || !isOnDeliveryScheme(accepted.scheme)) return refused(\"invalid_scheme\");\n if (accepted.network !== entry.network) return refused(\"invalid_network\");\n const fields = payloadFields(presented.payload);\n if (fields === undefined) return refused(\"invalid_on_delivery_svm_payload\");\n const program = new PublicKey(entry.extra.program);\n const pda = deriveEscrowPda(program, new PublicKey(fields.buyer), fields.taskId);\n if (pda.toBase58() !== fields.escrow) {\n return refused(\"invalid_on_delivery_svm_escrow_address_mismatch\");\n }\n // One clock reading judges the window and the record.\n const nowMs = ctx.now?.() ?? Date.now();\n if (Math.abs(nowMs - fields.signedAt) > WINDOW_MS) {\n return refused(\"invalid_on_delivery_svm_signature_expired\");\n }\n const message = buyerMessage(fields.signedAt, ctx.resourceUrl, fields.escrow);\n const signature = bs58.decode(fields.buyerSignature);\n const verified =\n canonicalS(signature) &&\n nacl.sign.detached.verify(\n new TextEncoder().encode(message),\n signature,\n new PublicKey(fields.buyer).toBytes(),\n );\n if (!verified) return refused(\"invalid_on_delivery_svm_buyer_signature\");\n const claimed = await ctx.replay.claim(\n `${fields.buyer}:${message}`,\n fields.signedAt + WINDOW_MS,\n nowMs,\n );\n if (!claimed) return refused(\"invalid_on_delivery_svm_buyer_signature\");\n return { fields };\n}\n\n/**\n * Binding server steps 1 to 3, with no RPC call: what a poll runs, `ctx.resourceUrl` being the poll\n * URL. Throws {@link EscroError} `VALIDATION_ERROR` before any work when `ctx.replay` is missing or\n * `ctx.resourceUrl` is not an absolute http: or https: URL.\n */\nexport async function verifyBuyerPresentation(\n payment: PaymentPayload,\n entry: OnDeliveryAccept,\n ctx: VerifyPresentationContext,\n): Promise<BuyerPresentationResult> {\n const result = await presentation(payment, entry, ctx);\n if (\"isValid\" in result) return result;\n return { isValid: true, payer: result.fields.buyer };\n}\n\n/**\n * Binding server steps 1 to 6 against the server's own `entry`: the payload, the escrow PDA, the\n * buyer's signature within 30 s, claimed once in `ctx.replay`, then the escrow account read at\n * `confirmed`. A Funded escrow is a new job; InProgress or Submitted a retry. Throws\n * {@link ChainReadError} `CHAIN_RPC_FAILED` when the RPC fails, and {@link EscroError}\n * `VALIDATION_ERROR` before any work when `ctx.replay` is missing or `ctx.resourceUrl` is not an\n * absolute http: or https: URL.\n */\nexport async function verifyEscrowPayload(\n payment: PaymentPayload,\n entry: OnDeliveryAccept,\n ctx: VerifyEscrowContext,\n): Promise<OnDeliveryVerifyResult> {\n const result = await presentation(payment, entry, ctx);\n if (\"isValid\" in result) return result;\n const { fields } = result;\n const payer = fields.buyer;\n const invalid = (invalidReason: OnDeliveryInvalidReason): OnDeliveryVerifyResult => ({\n isValid: false,\n invalidReason,\n payer,\n });\n let account: Awaited<ReturnType<Connection[\"getAccountInfo\"]>>;\n try {\n account = await ctx.rpc.getAccountInfo(new PublicKey(fields.escrow), {\n commitment: \"confirmed\",\n });\n } catch (cause) {\n throw new ChainReadError(\"CHAIN_RPC_FAILED\", \"The RPC's getAccountInfo call failed.\", {\n cause,\n });\n }\n if (\n account === null ||\n (account.owner.equals(SystemProgram.programId) && account.data.length === 0)\n ) {\n return invalid(\"invalid_on_delivery_svm_escrow_not_found\");\n }\n if (account.owner.toBase58() !== entry.extra.program) {\n return invalid(\"invalid_on_delivery_svm_escrow_owner\");\n }\n let escrow: DecodedEscrowAccount;\n try {\n escrow = decodeEscrowAccount(account.data);\n } catch (err) {\n if (!(err instanceof ChainReadError)) throw err;\n return invalid(\n err.reason === \"version\"\n ? \"invalid_on_delivery_svm_escrow_version\"\n : \"invalid_on_delivery_svm_escrow_owner\",\n );\n }\n const { buyer, assigned_worker, amount_usdc, spec_hash, deadline, state } = escrow;\n if (typeof buyer !== \"string\" || buyer !== fields.buyer) {\n return invalid(\"invalid_on_delivery_svm_buyer_mismatch\");\n }\n if (typeof assigned_worker !== \"string\" || assigned_worker !== entry.payTo) {\n return invalid(\"invalid_on_delivery_svm_worker_mismatch\");\n }\n if (typeof amount_usdc !== \"bigint\" || amount_usdc !== BigInt(entry.amount)) {\n return invalid(\"invalid_on_delivery_svm_amount_mismatch\");\n }\n if (typeof spec_hash !== \"string\" || spec_hash !== entry.extra.specHash) {\n return invalid(\"invalid_on_delivery_svm_spec_hash_mismatch\");\n }\n if (typeof deadline !== \"number\" || deadline < entry.extra.deadline) {\n return invalid(\"invalid_on_delivery_svm_deadline\");\n }\n if (state === \"Funded\") return { isValid: true, payer, job: \"new\", escrow };\n if (state === \"InProgress\" || state === \"Submitted\") {\n return { isValid: true, payer, job: \"retry\", escrow };\n }\n return invalid(\"invalid_on_delivery_svm_wrong_state\");\n}\n"],"mappings":"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","names":["Connection","PublicKey","createHash","nacl","bs58","EscrowState","spec","createHash","bs58","nacl","disc","bs58","bs58","byte","bs58","retryAfterMs","field","body","predicate","PublicKey","bs58","PublicKey","bs58","ONCHAIN_REFUND_GRACE_SECONDS","ONCHAIN_TIMEOUT_SECONDS","CLOCK_SKEW_SECONDS","SCANNER_REFUND_GRACE_SECONDS","SCANNER_TIMEOUT_SECONDS","Reader","bs58","spec","ESCROW_INSTRUCTIONS","bs58","decoded","field","PublicKey","refuse","unreadable","PublicKey","copy","PublicKey","TOKEN_PROGRAM_ID","getAssociatedTokenAddressSync","nacl","PublicKey","bs58","PublicKey","PublicKey","ix","spec","bs58","refuse","TOKEN_PROGRAM_ID","PublicKey","getAssociatedTokenAddressSync","matches","nacl","refuse","buildRefusal","PublicKey","bs58","nacl","nacl","bs58","admit","name","MAX_TASK_ID_BYTES","PublicKey","chosen","createHash","createHash","SHA256_HEX","refused","predicate","field","call","utf8","predicate","utf8","matches","utf8","predicate","predicate","isObject","refuse","predicate","utf8","refused","predicate","field","predicate","bs58","nacl","PublicKey","predicate","PublicKey","bs58","nacl","field","predicate","optional","predicate","sleep","Connection","refuse","PublicKey","retryAfterMs","createHash","sha256Hex","createHash","createHash","sha256Hex","spec","matches","spec","createHash","sha256Hex","createHash","referencePlaceholder","spec","defaultPin","DEFAULT_SUBNET","DEFAULT_TASK_BUDGET_MICRO_USDC","referencePlaceholder","spec","defaultCallSubnet","DEFAULT_SUBNET","DEFAULT_TASK_BUDGET_MICRO_USDC","sha256Hex","parseDemoDeliverable","referencePlaceholder","spec","createHash","sha256Hex","createHash","DEFAULT_TASK_BUDGET_MICRO_USDC","defaultSwap","defaultPin","DEMO_SEED","DEMO_ROUNDS","parseDemoDeliverable","referencePlaceholder","spec","createHash","DEFAULT_SERVICE","DEFAULT_TASK_BUDGET_MICRO_USDC","sha256Hex","createHash","defaultSwap","defaultPin","parseDemoDeliverable","referencePlaceholder","spec","defaultRunJob","createHash","sha256Hex","createHash","spec","defaultPin","createHash","sha256Hex","createHash","encoded","spec","field","lookup","isPlainObject","http","bs58","nacl","PublicKey","SystemProgram","MAX_TASK_ID_BYTES","bs58","PublicKey","nacl","invalid","SystemProgram"]}
|