@escro/sdk 0.4.2 → 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 +5628 -515
- 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 +5572 -533
- package/dist/index.js.map +1 -1
- package/package.json +8 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,21 +1,51 @@
|
|
|
1
|
-
import { Keypair } from '@solana/web3.js';
|
|
1
|
+
import { Keypair, Connection } from '@solana/web3.js';
|
|
2
|
+
|
|
3
|
+
interface PlatformConfigAccount {
|
|
4
|
+
version: number;
|
|
5
|
+
feeBps: number;
|
|
6
|
+
oracleAuthority: string;
|
|
7
|
+
usdcMint: string;
|
|
8
|
+
treasury: string;
|
|
9
|
+
bump: number;
|
|
10
|
+
}
|
|
2
11
|
|
|
3
12
|
type SolanaCluster = "devnet" | "mainnet";
|
|
13
|
+
/**
|
|
14
|
+
* The minimum escrow `amount` in micro-USDC ($5.00): the worker's net, not the buyer's deposit
|
|
15
|
+
* (amount plus the additive fee). Mirrors `MIN_ESCROW_AMOUNT` in the program; a test reads the
|
|
16
|
+
* program source and fails on drift.
|
|
17
|
+
*/
|
|
18
|
+
declare const MIN_ESCROW_AMOUNT: 5000000;
|
|
19
|
+
/**
|
|
20
|
+
* The most UTF-8 bytes `submit_deliverable`'s `proof_uri` may hold. MIRROR of the `#[max_len]` on
|
|
21
|
+
* `proof_uri` in the program's `EscrowAccount`; a test reads the program source and fails on
|
|
22
|
+
* drift. The program bounds the field only by the account's allocation; the
|
|
23
|
+
* API's submit builder enforces this cap. Checked off chain by `proofUriError`.
|
|
24
|
+
*/
|
|
25
|
+
declare const MAX_PROOF_URI_BYTES: 128;
|
|
26
|
+
declare const ONCHAIN_REFUND_GRACE_SECONDS: 900;
|
|
27
|
+
/**
|
|
28
|
+
* The furthest escrow deadline, in seconds from now, an agent-driven pay surface accepts (7 days): the
|
|
29
|
+
* ceiling and the default of the MCP's, SAK's and Eliza's pay bound.
|
|
30
|
+
*/
|
|
31
|
+
declare const PAY_MAX_DEADLINE_SECONDS: 604800;
|
|
4
32
|
|
|
5
33
|
/**
|
|
6
|
-
*
|
|
34
|
+
* Lifecycle states of an escrow, each transition validated by the on-chain program.
|
|
7
35
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
36
|
+
* Happy path: FUNDED → IN_PROGRESS → SUBMITTED → COMPLETED (buyer release or the 24h
|
|
37
|
+
* timeout release).
|
|
10
38
|
*
|
|
11
39
|
* Exception paths:
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* IN_PROGRESS → REFUNDED (deadline expiry auto-refund to buyer)
|
|
40
|
+
* IN_PROGRESS | SUBMITTED → DISPUTED (resolved only by arbitration, to COMPLETED or REFUNDED)
|
|
41
|
+
* FUNDED → CANCELLED (buyer cancels before the claim; on chain the account is REFUNDED)
|
|
42
|
+
* FUNDED | IN_PROGRESS → REFUNDED (deadline plus grace passed before a submission)
|
|
16
43
|
*/
|
|
17
44
|
declare enum EscrowState {
|
|
18
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* An unconfirmed intent: the API's create build recorded it and no landed create_escrow has
|
|
47
|
+
* funded it yet. Never persisted on chain and never served by a read.
|
|
48
|
+
*/
|
|
19
49
|
CREATED = "CREATED",
|
|
20
50
|
/** Maker deposited tokens into the vault; open for agent acceptance. */
|
|
21
51
|
FUNDED = "FUNDED",
|
|
@@ -42,15 +72,15 @@ type Network = "mainnet-beta" | "devnet" | "localnet";
|
|
|
42
72
|
* - `amount` is in the SPL token's smallest denomination (e.g. μUSDC = 10⁻⁶ USDC).
|
|
43
73
|
* - timestamps are Unix seconds as stored in the Anchor account.
|
|
44
74
|
*
|
|
45
|
-
* When serialising over HTTP, `amount` is represented as a
|
|
46
|
-
*
|
|
75
|
+
* When serialising over HTTP (the API's escrow responses), `amount` is represented as a
|
|
76
|
+
* decimal `string` of the smallest denomination to avoid JSON `number` precision loss.
|
|
47
77
|
*/
|
|
48
78
|
interface EscrowAccount {
|
|
49
79
|
/** Base-58 public key of the escrow PDA. */
|
|
50
80
|
address: string;
|
|
51
81
|
/** Base-58 public key of the task creator (the party paying for the work). */
|
|
52
82
|
maker: string;
|
|
53
|
-
/** Base-58 public key of the assigned
|
|
83
|
+
/** Base-58 public key of the worker assigned at creation (every escrow has one). */
|
|
54
84
|
taker: string | null;
|
|
55
85
|
/** Base-58 public key of the SPL token mint used for payment (e.g. USDC mint). */
|
|
56
86
|
mint: string;
|
|
@@ -64,24 +94,28 @@ interface EscrowAccount {
|
|
|
64
94
|
/**
|
|
65
95
|
* SHA-256 hex digest of the canonical UTF-8 JSON serialisation of the {@link TaskSpec}.
|
|
66
96
|
* Recorded on-chain (the account's `spec_hash` holds this hash, bare, or as `ipfs://<hash>` on
|
|
67
|
-
* escrows
|
|
97
|
+
* older escrows), so the buyer and worker (and an arbitrator) can check that a
|
|
68
98
|
* spec is the one the escrow was created for.
|
|
69
99
|
*/
|
|
70
100
|
taskSpecHash: string;
|
|
71
101
|
/**
|
|
72
102
|
* The exact string the escrow's on-chain `spec_hash` holds: the bare 64-hex `taskSpecHash`
|
|
73
|
-
* (
|
|
74
|
-
*
|
|
75
|
-
* stores no spec body; the buyer shares the spec).
|
|
103
|
+
* (current creates), `ipfs://<taskSpecHash>` (older escrows), or `null` where the API's record
|
|
104
|
+
* of an older escrow lacks it. A label for the {@link TaskSpec}'s hash, not a fetchable copy
|
|
105
|
+
* (Escro stores no spec body; the buyer shares the spec).
|
|
76
106
|
*/
|
|
77
107
|
taskSpecUri: string | null;
|
|
78
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Base-58 public key of the oracle authority permitted to sign timeout_release
|
|
110
|
+
* (refund_buyer is permissionless).
|
|
111
|
+
*/
|
|
79
112
|
oracle: string;
|
|
80
113
|
/**
|
|
81
|
-
* Platform fee in basis points.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
114
|
+
* Platform fee in basis points. Once the API has read the escrow's `create_escrow` from chain,
|
|
115
|
+
* it serves the escrow's on-chain `fee_bps` from its `EscrowCreated` event (PlatformConfig's
|
|
116
|
+
* value, stored per escrow at creation); on a CREATED intent not yet read it serves its
|
|
117
|
+
* `PLATFORM_FEE_BPS` mirror. Additive: the buyer deposits `amount` plus the fee and the
|
|
118
|
+
* worker receives the full `amount`.
|
|
85
119
|
*/
|
|
86
120
|
oracleFeeBps: number;
|
|
87
121
|
/** Unix timestamp (seconds) when the escrow PDA was initialised. */
|
|
@@ -115,6 +149,21 @@ interface EscrowAccount {
|
|
|
115
149
|
/** Solana cluster this account belongs to. */
|
|
116
150
|
network: Network;
|
|
117
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* `GET /v1/escrows/outstanding?maker=`: the maker's open deposits, the escrows whose vault still
|
|
154
|
+
* holds the buyer's money (FUNDED, IN_PROGRESS, SUBMITTED, DISPUTED; never CREATED).
|
|
155
|
+
*/
|
|
156
|
+
interface OutstandingDeposits {
|
|
157
|
+
/** Base-58 public key of the buyer the figures are for. */
|
|
158
|
+
maker: string;
|
|
159
|
+
/** Number of open escrows counted. */
|
|
160
|
+
count: number;
|
|
161
|
+
/**
|
|
162
|
+
* Sum over those escrows of `amount` plus the program's fee at the escrow's stored rate, in
|
|
163
|
+
* micro-USDC, as a decimal u64 string (it can exceed `Number.MAX_SAFE_INTEGER`).
|
|
164
|
+
*/
|
|
165
|
+
depositsMicroUsdc: string;
|
|
166
|
+
}
|
|
118
167
|
/** One set of `GET /v1/stats` figures: the public block, or the operator block. */
|
|
119
168
|
interface ProtocolStatsFigures {
|
|
120
169
|
totalEscrows: number;
|
|
@@ -139,7 +188,7 @@ interface ProtocolStats extends ProtocolStatsFigures {
|
|
|
139
188
|
/** That cluster's one USDC mint (`getUsdcMint`): every figure here is in this token. */
|
|
140
189
|
usdcMint: string;
|
|
141
190
|
/**
|
|
142
|
-
* Escro-operated fleet figures
|
|
191
|
+
* Escro-operated fleet figures: the same fields over
|
|
143
192
|
* escrows whose buyer and assigned worker are both in the API's operator
|
|
144
193
|
* allowlist. They are real settlements but not third-party demand, so every
|
|
145
194
|
* public field excludes them; never sum this block with the public fields.
|
|
@@ -215,7 +264,7 @@ interface AcceptanceCriterion {
|
|
|
215
264
|
* This object is:
|
|
216
265
|
* 1. Serialised to canonical UTF-8 JSON (sorted keys, no trailing whitespace).
|
|
217
266
|
* 2. Hashed with SHA-256 → stored on-chain as `EscrowAccount.taskSpecHash`.
|
|
218
|
-
* 3. Written into `create_escrow`'s `spec_hash` bare (
|
|
267
|
+
* 3. Written into `create_escrow`'s `spec_hash` bare (`ipfs://<hash>` on older escrows) and
|
|
219
268
|
* recorded as `EscrowAccount.taskSpecUri` (a label for the hash; Escro stores no spec body,
|
|
220
269
|
* and the buyer shares the spec itself).
|
|
221
270
|
*
|
|
@@ -261,8 +310,8 @@ interface TaskSpec {
|
|
|
261
310
|
|
|
262
311
|
/**
|
|
263
312
|
* Every machine-readable error code the escro.ai REST API's route handlers send in the `code`
|
|
264
|
-
* field of an error response
|
|
265
|
-
*
|
|
313
|
+
* field of an error response, and no other. A request Fastify refuses before a handler runs
|
|
314
|
+
* carries Fastify's own `FST_ERR_*` code instead.
|
|
266
315
|
*
|
|
267
316
|
* Consumers should switch on this value to handle errors programmatically
|
|
268
317
|
* rather than parsing the human-readable `error` string.
|
|
@@ -272,13 +321,15 @@ type EscrowErrorCode =
|
|
|
272
321
|
"ESCROW_NOT_FOUND"
|
|
273
322
|
/** The requested operation is not permitted in the escrow's current state. */
|
|
274
323
|
| "ESCROW_INVALID_STATE"
|
|
275
|
-
/** Release:
|
|
324
|
+
/** Release: no settlement of the escrow is recorded or listed yet; retry once the release lands. */
|
|
276
325
|
| "ESCROW_NOT_SETTLED"
|
|
277
|
-
/** Confirm:
|
|
326
|
+
/** Confirm: the escrow PDA was initialised again and the transaction acts on that later lifecycle, which the escrow does not record. */
|
|
327
|
+
| "ESCROW_PDA_REUSED"
|
|
328
|
+
/** Confirm: the transaction cannot be recorded yet (not visible at `confirmed`, an earlier transaction on its escrow unrecorded, or more escrows than a hint records); retry. */
|
|
278
329
|
| "TX_NOT_FOUND"
|
|
279
330
|
/** Confirm: the transaction landed with an error. */
|
|
280
331
|
| "TX_FAILED"
|
|
281
|
-
/** Confirm: the transaction holds no
|
|
332
|
+
/** Confirm: the transaction holds no instruction of the program on the escrow, or one the API does not classify. */
|
|
282
333
|
| "TX_MISMATCH"
|
|
283
334
|
/** The Solana RPC read failed; retry. */
|
|
284
335
|
| "RPC_UNAVAILABLE"
|
|
@@ -308,19 +359,19 @@ type EscrowErrorCode =
|
|
|
308
359
|
| "VALIDATION_ERROR";
|
|
309
360
|
|
|
310
361
|
/**
|
|
311
|
-
* EscroBots v0 - the permissionless capability directory
|
|
362
|
+
* EscroBots v0 - the permissionless capability directory.
|
|
312
363
|
*
|
|
313
364
|
* A bot advertises itself by publishing a wallet-signed capability descriptor.
|
|
314
365
|
* The descriptor is a *claim*, not a verified fact - on-chain history is the
|
|
315
|
-
* verification (surfaced in the
|
|
366
|
+
* verification (surfaced in the v1 directory). The registry performs no
|
|
316
367
|
* approval, review, or ranking; fraud against the protocol is the only removal
|
|
317
368
|
* criterion. The descriptor document itself is independently verifiable: anyone
|
|
318
369
|
* holding it can check `signature` against `wallet` without trusting the API.
|
|
319
370
|
*/
|
|
320
371
|
/**
|
|
321
372
|
* The advertisable roles. Single source for both the `BotRole` type and the API's
|
|
322
|
-
*
|
|
323
|
-
*
|
|
373
|
+
* validation of a role, so the accepted values and the type cannot drift: a role
|
|
374
|
+
* added here flows into validation automatically.
|
|
324
375
|
*/
|
|
325
376
|
declare const BOT_ROLES: readonly ["worker", "buyer", "both"];
|
|
326
377
|
/** Whether the bot hires work, performs work, or both. */
|
|
@@ -384,6 +435,184 @@ interface ReviewPolicy {
|
|
|
384
435
|
evaluate(deliverable: ReviewDeliverable): ReviewResult | Promise<ReviewResult>;
|
|
385
436
|
}
|
|
386
437
|
|
|
438
|
+
interface ResourceInfo {
|
|
439
|
+
url: string;
|
|
440
|
+
description?: string;
|
|
441
|
+
mimeType?: string;
|
|
442
|
+
/** Service metadata a discovery catalog lists (x402 `specs/extensions/bazaar.md` at e4a08681). */
|
|
443
|
+
serviceName?: string;
|
|
444
|
+
tags?: string[];
|
|
445
|
+
iconUrl?: string;
|
|
446
|
+
[member: string]: unknown;
|
|
447
|
+
}
|
|
448
|
+
/** How a discovery catalog calls an HTTP endpoint: `info.input` of a `bazaar` declaration. */
|
|
449
|
+
interface BazaarHttpInput {
|
|
450
|
+
type: "http";
|
|
451
|
+
method: "GET" | "HEAD" | "DELETE" | "POST" | "PUT" | "PATCH";
|
|
452
|
+
bodyType?: "json" | "form-data" | "text";
|
|
453
|
+
body?: unknown;
|
|
454
|
+
queryParams?: Record<string, unknown>;
|
|
455
|
+
headers?: Record<string, string>;
|
|
456
|
+
}
|
|
457
|
+
/** `extensions.bazaar` of a 402 (x402 `specs/extensions/bazaar.md` at e4a08681). */
|
|
458
|
+
interface BazaarDeclaration {
|
|
459
|
+
info: {
|
|
460
|
+
input: BazaarHttpInput;
|
|
461
|
+
output?: {
|
|
462
|
+
type: string;
|
|
463
|
+
format?: string;
|
|
464
|
+
example?: unknown;
|
|
465
|
+
};
|
|
466
|
+
};
|
|
467
|
+
schema: Record<string, unknown>;
|
|
468
|
+
}
|
|
469
|
+
interface PaymentRequirements {
|
|
470
|
+
scheme: string;
|
|
471
|
+
network: string;
|
|
472
|
+
amount: string;
|
|
473
|
+
asset: string;
|
|
474
|
+
payTo: string;
|
|
475
|
+
maxTimeoutSeconds: number;
|
|
476
|
+
extra?: Record<string, unknown>;
|
|
477
|
+
}
|
|
478
|
+
interface PaymentRequired {
|
|
479
|
+
x402Version: 2;
|
|
480
|
+
error?: string;
|
|
481
|
+
resource: ResourceInfo;
|
|
482
|
+
accepts: PaymentRequirements[];
|
|
483
|
+
extensions?: Record<string, unknown>;
|
|
484
|
+
}
|
|
485
|
+
interface PaymentPayload<P = Record<string, unknown>> {
|
|
486
|
+
x402Version: 2;
|
|
487
|
+
resource?: ResourceInfo;
|
|
488
|
+
accepted: PaymentRequirements;
|
|
489
|
+
payload: P;
|
|
490
|
+
extensions?: Record<string, unknown>;
|
|
491
|
+
}
|
|
492
|
+
interface SettlementResponse {
|
|
493
|
+
success: boolean;
|
|
494
|
+
transaction: string;
|
|
495
|
+
network: string;
|
|
496
|
+
payer?: string;
|
|
497
|
+
errorReason?: string;
|
|
498
|
+
errorMessage?: string;
|
|
499
|
+
/** The amount settled, where the scheme reports one (`upto`). */
|
|
500
|
+
amount?: string;
|
|
501
|
+
extensions?: Record<string, unknown>;
|
|
502
|
+
}
|
|
503
|
+
/** A facilitator's `/verify` answer. */
|
|
504
|
+
interface VerifyResponse {
|
|
505
|
+
isValid: boolean;
|
|
506
|
+
invalidReason?: string;
|
|
507
|
+
invalidMessage?: string;
|
|
508
|
+
payer?: string;
|
|
509
|
+
}
|
|
510
|
+
/** One scheme and network a facilitator settles, from its `/supported` answer. */
|
|
511
|
+
interface SupportedKind {
|
|
512
|
+
x402Version: number;
|
|
513
|
+
scheme: string;
|
|
514
|
+
network: string;
|
|
515
|
+
extra?: Record<string, unknown>;
|
|
516
|
+
}
|
|
517
|
+
/** A facilitator's `/supported` answer. */
|
|
518
|
+
interface SupportedResponse {
|
|
519
|
+
kinds: SupportedKind[];
|
|
520
|
+
extensions: string[];
|
|
521
|
+
signers: Record<string, string[]>;
|
|
522
|
+
}
|
|
523
|
+
/** What a worker's menu settles an `exact` payment through: the SDK's `createHttpFacilitator`, or any equivalent. */
|
|
524
|
+
interface Facilitator {
|
|
525
|
+
verify(payment: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
|
|
526
|
+
settle(payment: PaymentPayload, requirements: PaymentRequirements): Promise<SettlementResponse>;
|
|
527
|
+
getSupported(): Promise<SupportedResponse>;
|
|
528
|
+
}
|
|
529
|
+
type OnDeliveryScheme = "on-delivery" | "job-escrow";
|
|
530
|
+
type SettlementMode = "release" | "refund";
|
|
531
|
+
type OnDeliveryExtra = Readonly<{
|
|
532
|
+
program: string;
|
|
533
|
+
specHash: string;
|
|
534
|
+
specUri: string;
|
|
535
|
+
deadline: number;
|
|
536
|
+
reviewWindowSeconds: number;
|
|
537
|
+
feeBps: number;
|
|
538
|
+
feePayer: "client";
|
|
539
|
+
settlementMode: SettlementMode;
|
|
540
|
+
paymentFlow: "upfront" | "escrow";
|
|
541
|
+
}>;
|
|
542
|
+
interface OnDeliveryAccept extends PaymentRequirements {
|
|
543
|
+
scheme: OnDeliveryScheme;
|
|
544
|
+
extra: OnDeliveryExtra;
|
|
545
|
+
}
|
|
546
|
+
interface OnDeliveryPayloadFields {
|
|
547
|
+
escrow: string;
|
|
548
|
+
buyer: string;
|
|
549
|
+
taskId: string;
|
|
550
|
+
createSignature: string;
|
|
551
|
+
/** Unix milliseconds. */
|
|
552
|
+
signedAt: number;
|
|
553
|
+
buyerSignature: string;
|
|
554
|
+
}
|
|
555
|
+
interface OnDeliveryPaymentPayload extends PaymentPayload<OnDeliveryPayloadFields> {
|
|
556
|
+
accepted: OnDeliveryAccept;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* The `escro` x402 extension's `acceptance` (docs/specs/escro-extension.md "acceptance";
|
|
560
|
+
* `$defs.acceptance` in escro-extension.schema.json): the predicate a judge applies to a delivery.
|
|
561
|
+
* `paramsHash` is the SHA-256 hex of the RFC 8785 canonical JSON of the predicate's parameters.
|
|
562
|
+
*/
|
|
563
|
+
interface Acceptance {
|
|
564
|
+
name: string;
|
|
565
|
+
paramsHash: string;
|
|
566
|
+
fixtureHashes?: string[];
|
|
567
|
+
}
|
|
568
|
+
interface EscroReceipt {
|
|
569
|
+
schema: string;
|
|
570
|
+
verifierUrl?: string;
|
|
571
|
+
}
|
|
572
|
+
interface EscroSettlementTerms {
|
|
573
|
+
reviewWindowSeconds: number;
|
|
574
|
+
settlementMode: SettlementMode;
|
|
575
|
+
feePayer: "client" | "worker";
|
|
576
|
+
}
|
|
577
|
+
type EscroNextAction = {
|
|
578
|
+
channel: "onchain";
|
|
579
|
+
action: string;
|
|
580
|
+
actor: string;
|
|
581
|
+
notBefore?: number;
|
|
582
|
+
network: string;
|
|
583
|
+
instruction: string;
|
|
584
|
+
address?: string;
|
|
585
|
+
args?: Record<string, unknown>;
|
|
586
|
+
} | {
|
|
587
|
+
channel: "server";
|
|
588
|
+
action: string;
|
|
589
|
+
actor: string;
|
|
590
|
+
notBefore?: number;
|
|
591
|
+
method: "GET" | "POST";
|
|
592
|
+
url: string;
|
|
593
|
+
} | {
|
|
594
|
+
channel: "mcp";
|
|
595
|
+
action: string;
|
|
596
|
+
actor: string;
|
|
597
|
+
notBefore?: number;
|
|
598
|
+
server: string;
|
|
599
|
+
tool: string;
|
|
600
|
+
args?: Record<string, unknown>;
|
|
601
|
+
};
|
|
602
|
+
interface EscroExtensionInfo {
|
|
603
|
+
acceptance?: Acceptance;
|
|
604
|
+
receipt?: EscroReceipt;
|
|
605
|
+
settlement?: EscroSettlementTerms;
|
|
606
|
+
nextActions?: EscroNextAction[];
|
|
607
|
+
}
|
|
608
|
+
/** The hex SHA-256 of a TaskSpec's canonical JSON: what an escrow's `spec_hash` holds. */
|
|
609
|
+
declare function computeTaskSpecHash(spec: TaskSpec): string;
|
|
610
|
+
/**
|
|
611
|
+
* Why `uri` cannot be submitted as a deliverable's `proofUri`, or null when it can. The on-chain
|
|
612
|
+
* `proof_uri` allocation counts UTF-8 bytes, so a URI whose UTF-16 length fits can still be too long.
|
|
613
|
+
*/
|
|
614
|
+
declare function proofUriError(uri: string): string | null;
|
|
615
|
+
|
|
387
616
|
/** Dispute tally with its outcome split (from the wallet's perspective). */
|
|
388
617
|
interface DisputeRecord {
|
|
389
618
|
/** Total disputes this wallet was party to (raised by either side). */
|
|
@@ -473,14 +702,20 @@ interface ServedWalletReputation extends SerializedWalletReputation {
|
|
|
473
702
|
walletAgeSeconds: number | null;
|
|
474
703
|
}
|
|
475
704
|
|
|
705
|
+
/** Docs for the payment rails, linked from the rail-not-enabled error and the kit config's rejection
|
|
706
|
+
* message so both point to the same place. Re-exported from `payments.ts`. */
|
|
707
|
+
declare const RAILS_DOCS_URL = "https://escro.ai/rails";
|
|
476
708
|
/**
|
|
477
709
|
* Base class for all errors thrown by the @escro/sdk. `retryAfterMs` is the
|
|
478
|
-
* server's Retry-After delay, when it sent one in seconds.
|
|
710
|
+
* server's Retry-After delay, when it sent one in seconds; `options.cause` is the
|
|
711
|
+
* failure this error reports.
|
|
479
712
|
*/
|
|
480
713
|
declare class EscroError extends Error {
|
|
481
714
|
readonly code: string;
|
|
482
715
|
readonly retryAfterMs?: number | undefined;
|
|
483
|
-
constructor(message: string, code?: string, retryAfterMs?: number | undefined
|
|
716
|
+
constructor(message: string, code?: string, retryAfterMs?: number | undefined, options?: {
|
|
717
|
+
cause?: unknown;
|
|
718
|
+
});
|
|
484
719
|
}
|
|
485
720
|
/** The requested escrow was not found (HTTP 404). */
|
|
486
721
|
declare class EscrowNotFoundError extends EscroError {
|
|
@@ -522,13 +757,55 @@ declare class UnauthorizedError extends EscroError {
|
|
|
522
757
|
constructor(message?: string);
|
|
523
758
|
}
|
|
524
759
|
/**
|
|
525
|
-
* A payment rail
|
|
526
|
-
*
|
|
527
|
-
*
|
|
760
|
+
* A payment rail is not available. {@link Escro.pay} throws this for the `x402` rail when its
|
|
761
|
+
* packages fail to load (`cause` is the load failure); nothing was signed and nothing is counted.
|
|
762
|
+
* `rail` names the unavailable rail.
|
|
528
763
|
*/
|
|
529
764
|
declare class EscroRailNotEnabledError extends EscroError {
|
|
530
765
|
readonly rail: string;
|
|
531
|
-
constructor(rail: string
|
|
766
|
+
constructor(rail: string, options?: {
|
|
767
|
+
cause?: unknown;
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
/** Why {@link Escro.pay} refused a payment; see {@link EscroPayError}. */
|
|
771
|
+
type PayRefusal = "no_offer" | "both_offers" | "url" | "request_header" | "request" | "redirect" | "not_402" | "resource_mismatch" | "no_eligible_entry" | "timeout_ceiling" | "policy_choice" | "unsupported_scheme" | "scheme_conflict" | "presentation" | "settlement" | "timeout" | "requirements" | "transaction" | "host";
|
|
772
|
+
/**
|
|
773
|
+
* {@link Escro.pay} refused, or the payment router refused a scheme; `reason` names the check and
|
|
774
|
+
* `detail` the offending value where there is one. Once the escrow is created, `escrowPda` and
|
|
775
|
+
* `createSignature` are set: the escrow is funded, and `cancelEscrow(escrowPda)` recovers the
|
|
776
|
+
* deposit while it is Funded. `status` is the paid request's HTTP status when it answered. On the
|
|
777
|
+
* x402 rail a failure after the payment left the process carries `payment`, and no `escrowPda`. A
|
|
778
|
+
* paid request answered with an error status carries `settlement` when the answer's
|
|
779
|
+
* `PAYMENT-RESPONSE` decodes with a boolean `success` and a string `transaction` and `network`:
|
|
780
|
+
* the worker's own unverified report, whatever its `success`.
|
|
781
|
+
*/
|
|
782
|
+
declare class EscroPayError extends EscroError {
|
|
783
|
+
readonly reason: PayRefusal;
|
|
784
|
+
readonly detail?: string;
|
|
785
|
+
readonly escrowPda?: string;
|
|
786
|
+
readonly createSignature?: string;
|
|
787
|
+
readonly status?: number;
|
|
788
|
+
/**
|
|
789
|
+
* What a failed x402 settlement can be matched by against the wallet's token-account history, in
|
|
790
|
+
* case the resource server still lands the transfer: the Memo instruction's text (byte-exact),
|
|
791
|
+
* the amount and `payTo`. Never the partially signed transaction.
|
|
792
|
+
*/
|
|
793
|
+
readonly payment?: {
|
|
794
|
+
readonly memo: string;
|
|
795
|
+
readonly amountMicroUsdc: number;
|
|
796
|
+
readonly payTo: string;
|
|
797
|
+
};
|
|
798
|
+
/** The `PAYMENT-RESPONSE` a worker sent beside an error status: its unverified word, as sent. */
|
|
799
|
+
readonly settlement?: SettlementResponse;
|
|
800
|
+
constructor(reason: PayRefusal, message: string, options?: {
|
|
801
|
+
detail?: string;
|
|
802
|
+
escrowPda?: string;
|
|
803
|
+
createSignature?: string;
|
|
804
|
+
status?: number;
|
|
805
|
+
payment?: EscroPayError["payment"];
|
|
806
|
+
settlement?: SettlementResponse;
|
|
807
|
+
cause?: unknown;
|
|
808
|
+
});
|
|
532
809
|
}
|
|
533
810
|
|
|
534
811
|
/** Constructor options for the {@link Escro} client. */
|
|
@@ -536,7 +813,7 @@ interface EscroOptions {
|
|
|
536
813
|
/**
|
|
537
814
|
* Which Solana cluster this client talks to. Required so the program ID and
|
|
538
815
|
* USDC mint resolve correctly. Pass `"devnet"` for testing, `"mainnet"` for
|
|
539
|
-
* production.
|
|
816
|
+
* production.
|
|
540
817
|
*/
|
|
541
818
|
cluster: SolanaCluster;
|
|
542
819
|
/** Solana RPC endpoint URL. */
|
|
@@ -545,6 +822,92 @@ interface EscroOptions {
|
|
|
545
822
|
apiUrl: string;
|
|
546
823
|
/** Ed25519 keypair used to sign transactions and API requests. */
|
|
547
824
|
wallet: Keypair;
|
|
825
|
+
/**
|
|
826
|
+
* The most micro-USDC this wallet may hold locked in open escrows, each counted as its
|
|
827
|
+
* deposit: amount plus fee. {@link Escro.createEscrow} refuses (`SPEND_CAP_EXCEEDED`), before
|
|
828
|
+
* the create is sent, a create whose deposit would pass it. Required for `createEscrow` on
|
|
829
|
+
* `"mainnet"`, which refuses without it; the other methods never read it. Copied at
|
|
830
|
+
* construction.
|
|
831
|
+
*
|
|
832
|
+
* Outstanding is the API's total of the wallet's FUNDED, IN_PROGRESS, SUBMITTED and DISPUTED
|
|
833
|
+
* deposits (one `GET /v1/escrows/outstanding` per create), plus this process's own creates in
|
|
834
|
+
* flight: a create holds its deposit from the API's answer to its POST. A create that throws
|
|
835
|
+
* before its transaction is sent (the SDK's refusal of the server's transaction as not the
|
|
836
|
+
* create it asked for, `UNEXPECTED_TRANSACTION`; an undecodable server transaction; a failed
|
|
837
|
+
* blockhash read) holds nothing. Once sent, the hold lasts until a successful
|
|
838
|
+
* {@link Escro.confirm} of its address, until a later create's admission reads the escrow from
|
|
839
|
+
* the API (one `GET /v1/escrows/:address` per create in flight; a read that fails keeps the
|
|
840
|
+
* hold and refuses nothing), or until evidence shows the transaction never took effect: the
|
|
841
|
+
* RPC rejected it (a `SendTransactionError`) other than as already processed, or it failed at
|
|
842
|
+
* execution (`TX_FAILED`, from the send's confirmation or a confirm). A create that throws
|
|
843
|
+
* after its transaction is sent for any other reason (a transport error, a confirmation
|
|
844
|
+
* timeout, an `EscroConfirmError`) keeps counting, and shrinks the cap's room, until
|
|
845
|
+
* `confirm(address, signature)` succeeds or the process exits. An "already processed" rejection carries no signature to confirm with, so its
|
|
846
|
+
* hold lasts until the process exits. An outstanding read that fails, answers something
|
|
847
|
+
* malformed or takes longer than 15 s refuses the create (`SPEND_CAP_UNREADABLE`, a failed or
|
|
848
|
+
* timed-out read as its `cause`); a PlatformConfig read that fails or takes longer than 15 s
|
|
849
|
+
* throws its own error, with no code.
|
|
850
|
+
*
|
|
851
|
+
* The cap holds per process: every capped `Escro` for one wallet and cluster in the process
|
|
852
|
+
* shares one admission queue and one in-flight set. Two processes or hosts on one wallet each
|
|
853
|
+
* enforce it and together can pass it by the other's in-flight deposits; run one buyer process
|
|
854
|
+
* per wallet, or give each process its share.
|
|
855
|
+
*/
|
|
856
|
+
spendCap?: {
|
|
857
|
+
/** The cap, in integer micro-USDC (1 USDC = 1_000_000); deposits equal to it are allowed. */
|
|
858
|
+
maxOutstandingMicroUsdc: number;
|
|
859
|
+
/**
|
|
860
|
+
* Replaces the API read: the micro-USDC already locked in this wallet's open escrows,
|
|
861
|
+
* deposits counted. The process's in-flight creates are added to its answer. Called with the
|
|
862
|
+
* `spendCap` object given at construction as `this`. Bound like the API read: one that has
|
|
863
|
+
* not answered within 15 s is abandoned (it is passed no signal, so it is not cancelled) and
|
|
864
|
+
* the create refused with `SPEND_CAP_UNREADABLE`.
|
|
865
|
+
*/
|
|
866
|
+
outstanding?: () => Promise<number>;
|
|
867
|
+
};
|
|
868
|
+
/**
|
|
869
|
+
* The most micro-USDC {@link Escro.pay} may spend over the x402 rail, separate from
|
|
870
|
+
* {@link EscroOptions.spendCap}: neither cap draws on the other. Required for an `exact` payment
|
|
871
|
+
* on `"mainnet"`, which refuses without it (`SPEND_CAP_REQUIRED`); a payment that would pass it
|
|
872
|
+
* refuses (`SPEND_CAP_EXCEEDED`). Copied at construction.
|
|
873
|
+
*
|
|
874
|
+
* A payment counts at its full amount from admission, before it is signed, and is credited back
|
|
875
|
+
* only if it is refused before its signature exists: once signed it stays counted, because the
|
|
876
|
+
* resource server can still land the transfer. The budget is per process, per cluster and wallet,
|
|
877
|
+
* and RESETS WHEN THE PROCESS RESTARTS; give `spent` to carry a budget across restarts.
|
|
878
|
+
*/
|
|
879
|
+
x402SpendCap?: {
|
|
880
|
+
/** The cap, in integer micro-USDC (1 USDC = 1_000_000); spending up to it is allowed. */
|
|
881
|
+
maxMicroUsdc: number;
|
|
882
|
+
/**
|
|
883
|
+
* The micro-USDC the operator records as already spent on this wallet's x402 rail, added to the
|
|
884
|
+
* process's own total. A reader that also counts this process's payments double-counts them,
|
|
885
|
+
* which refuses early and never overspends. Called with the `x402SpendCap` object given at
|
|
886
|
+
* construction as `this`. One that fails, answers anything but a whole non-negative number or
|
|
887
|
+
* takes longer than 15 s refuses the payment (`SPEND_CAP_UNREADABLE`).
|
|
888
|
+
*/
|
|
889
|
+
spent?: () => Promise<number>;
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
/** The {@link EscroOptions.spendCap} option. */
|
|
893
|
+
type SpendCap = NonNullable<EscroOptions["spendCap"]>;
|
|
894
|
+
/** The {@link EscroOptions.x402SpendCap} option. */
|
|
895
|
+
type X402SpendCap = NonNullable<EscroOptions["x402SpendCap"]>;
|
|
896
|
+
/** How a lifecycle call (create, claim, submit, cancel, dispute, release) sends its transaction. */
|
|
897
|
+
interface SendOptions {
|
|
898
|
+
/**
|
|
899
|
+
* `true` (the default): send, wait for the transaction to confirm on chain, then have the API
|
|
900
|
+
* record it. `false`: check and sign the transaction exactly as the default does, send it and
|
|
901
|
+
* return its signature without waiting or notifying the API. The caller learns the outcome by
|
|
902
|
+
* `getEscrow(address)` (the API records every landed transaction within about a minute plus
|
|
903
|
+
* finality), by the signature's status on chain, or by
|
|
904
|
+
* `confirm(address, signature)` as a hint. A dispute's evidence travels
|
|
905
|
+
* only with the disputant's confirm, so `raiseDispute` with `evidence` refuses `wait: false`.
|
|
906
|
+
* Under {@link EscroOptions.spendCap}, a create sent this way stays counted as in flight until
|
|
907
|
+
* a later create's admission reads the escrow from the API, a confirm records it, or a confirm
|
|
908
|
+
* of its signature shows it failed on chain.
|
|
909
|
+
*/
|
|
910
|
+
wait?: boolean;
|
|
548
911
|
}
|
|
549
912
|
/** Parameters for creating a new escrow. */
|
|
550
913
|
interface CreateEscrowParams {
|
|
@@ -559,7 +922,7 @@ interface CreateEscrowParams {
|
|
|
559
922
|
/** Unix timestamp (seconds) at which the escrow deadline expires. */
|
|
560
923
|
deadlineUnix: number;
|
|
561
924
|
/**
|
|
562
|
-
* Base-58 public key of the worker assigned to this task. Required
|
|
925
|
+
* Base-58 public key of the worker assigned to this task. Required:
|
|
563
926
|
* every escrow is created against a specific worker (open tasks are
|
|
564
927
|
* not supported).
|
|
565
928
|
*/
|
|
@@ -589,6 +952,10 @@ interface ReleasePaymentOutcome {
|
|
|
589
952
|
error: EscroConfirmError;
|
|
590
953
|
};
|
|
591
954
|
}
|
|
955
|
+
/** {@link ReleasePaymentOutcome} of a predicate release, with the decision memo it carried. */
|
|
956
|
+
type ReleaseWithPredicateOutcome = ReleasePaymentOutcome & {
|
|
957
|
+
memo: string;
|
|
958
|
+
};
|
|
592
959
|
/** Parameters for submitting a deliverable. */
|
|
593
960
|
interface SubmitDeliverableParams {
|
|
594
961
|
/** SHA-256 hex digest (or content-addressed hash) of the deliverable content. */
|
|
@@ -607,9 +974,9 @@ interface RaiseDisputeParams {
|
|
|
607
974
|
interface PollOptions {
|
|
608
975
|
/**
|
|
609
976
|
* Enable polling with exponential backoff.
|
|
610
|
-
* - 0
|
|
611
|
-
* - 5
|
|
612
|
-
* - 30 min
|
|
977
|
+
* - 0 to 5 min: poll every 15 s
|
|
978
|
+
* - 5 to 30 min: poll every 30 s
|
|
979
|
+
* - 30 min to 24 h: poll every 60 s
|
|
613
980
|
* - After 24 h: throws {@link EscrowTimeoutError}
|
|
614
981
|
* @default false
|
|
615
982
|
*/
|
|
@@ -648,9 +1015,9 @@ interface ListBotsParams {
|
|
|
648
1015
|
}
|
|
649
1016
|
/**
|
|
650
1017
|
* One candidate returned by {@link Escro.findWorkers}. The `descriptor` is a
|
|
651
|
-
* self-reported CLAIM
|
|
1018
|
+
* self-reported CLAIM; `signatureValid` attests only that the
|
|
652
1019
|
* claim was genuinely signed by `descriptor.wallet` (authorship), NOT that its
|
|
653
|
-
* capabilities are true. On-chain history (EscroRep
|
|
1020
|
+
* capabilities are true. On-chain history (EscroRep) is the verification
|
|
654
1021
|
* of the claim, deliberately kept separate here, never merged into one flag.
|
|
655
1022
|
*/
|
|
656
1023
|
interface WorkerCandidate {
|
|
@@ -661,30 +1028,26 @@ interface WorkerCandidate {
|
|
|
661
1028
|
}
|
|
662
1029
|
|
|
663
1030
|
/**
|
|
664
|
-
*
|
|
1031
|
+
* The dual-path payment surface: the escrow rail and the x402 rail behind one `pay()`.
|
|
665
1032
|
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
* Phase 9 may add only OPTIONAL fields.
|
|
1033
|
+
* `pay()` reaches the escrow rail from a 402's `on-delivery` or `job-escrow` entry and
|
|
1034
|
+
* the x402 rail from an `exact` entry. Every name here is a FREEZE CONTRACT: a new rail
|
|
1035
|
+
* or field must not be a breaking change for any kit-generated bot.
|
|
1036
|
+
* The shapes below are pinned by a type-level test; fields are added only as
|
|
1037
|
+
* OPTIONAL fields.
|
|
672
1038
|
*/
|
|
1039
|
+
|
|
673
1040
|
/** Single source for the rail identifiers. The {@link Rail} type is derived from
|
|
674
1041
|
* this list (drift-safe, mirroring the BOT_ROLES pattern in @escro/shared). */
|
|
675
1042
|
declare const RAILS: readonly ["escrow", "x402"];
|
|
676
|
-
/** The payment rails Escro can route across.
|
|
677
|
-
* `x402` is RESERVED and not enabled until Phase 9. */
|
|
1043
|
+
/** The payment rails Escro can route across. */
|
|
678
1044
|
type Rail = (typeof RAILS)[number];
|
|
679
|
-
/** The rails enabled in this build.
|
|
680
|
-
*
|
|
681
|
-
*
|
|
1045
|
+
/** The rails enabled in this build. Typed `readonly Rail[]` (not the literal tuple) so
|
|
1046
|
+
* runtime membership checks stay honest: `ENABLED_RAILS.includes(rail)` narrows nothing
|
|
1047
|
+
* away. */
|
|
682
1048
|
declare const ENABLED_RAILS: readonly Rail[];
|
|
683
|
-
/** Docs for the payment rails, linked from the reserved-rail error and the kit
|
|
684
|
-
* config's rejection message so both point to the same place. */
|
|
685
|
-
declare const RAILS_DOCS_URL = "https://docs.escro.ai/rails";
|
|
686
1049
|
/** The minimal payment shape a {@link PaymentRouter} inspects to choose a rail.
|
|
687
|
-
* FROZEN;
|
|
1050
|
+
* FROZEN; the x402 rail may add only optional fields. */
|
|
688
1051
|
interface TxShape {
|
|
689
1052
|
/** Recipient wallet address (base58). */
|
|
690
1053
|
readonly to: string;
|
|
@@ -692,26 +1055,76 @@ interface TxShape {
|
|
|
692
1055
|
readonly amountMicroUsdc: number;
|
|
693
1056
|
/** `async` (verification-needed) work routes to escrow; `sync` work is x402's territory. */
|
|
694
1057
|
readonly mode: "async" | "sync";
|
|
1058
|
+
/** The 402 entry being paid; its `scheme` routes when `scheme` is absent. */
|
|
1059
|
+
readonly accept?: PaymentRequirements;
|
|
1060
|
+
/** The x402 scheme being paid; given with `accept`, the two must be equal. */
|
|
1061
|
+
readonly scheme?: string;
|
|
695
1062
|
}
|
|
696
|
-
/** Chooses the rail for a payment
|
|
697
|
-
*
|
|
1063
|
+
/** Chooses the rail for a payment, throwing rather than return a rail that is not
|
|
1064
|
+
* enabled. FROZEN signature. */
|
|
698
1065
|
interface PaymentRouter {
|
|
699
1066
|
selectRail(tx: TxShape): Rail;
|
|
700
1067
|
}
|
|
701
|
-
/**
|
|
702
|
-
*
|
|
703
|
-
*
|
|
1068
|
+
/**
|
|
1069
|
+
* The router. With no scheme, async work routes to escrow and sync work prefers x402, falling back
|
|
1070
|
+
* to escrow when x402 is not enabled. With a scheme (`tx.scheme`, else `tx.accept.scheme`),
|
|
1071
|
+
* `on-delivery` and `job-escrow` route to escrow under `async`, `exact` and `upto` to x402 under
|
|
1072
|
+
* `sync`. It throws {@link EscroPayError} `scheme_conflict` when `scheme` and `accept.scheme`
|
|
1073
|
+
* differ or the mode is not the scheme's, `unsupported_scheme` for any other scheme, and
|
|
1074
|
+
* {@link EscroRailNotEnabledError} for a scheme whose rail is not enabled: a scheme's rail is never
|
|
1075
|
+
* swapped for another.
|
|
1076
|
+
*/
|
|
704
1077
|
declare class EscrowPaymentRouter implements PaymentRouter {
|
|
705
1078
|
selectRail(tx: TxShape): Rail;
|
|
706
1079
|
}
|
|
707
|
-
/**
|
|
708
|
-
|
|
709
|
-
|
|
1080
|
+
/** The HTTP request {@link Escro.pay} pays for: sent as given, plus `PAYMENT-SIGNATURE` once paid. */
|
|
1081
|
+
interface PayRequest {
|
|
1082
|
+
/** Default `GET`. */
|
|
1083
|
+
readonly method?: string;
|
|
1084
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
1085
|
+
readonly body?: string;
|
|
1086
|
+
}
|
|
1087
|
+
/** What a {@link PayPolicy} sees of the 402 beside its entries. */
|
|
1088
|
+
interface PayOffer {
|
|
1089
|
+
readonly resource: ResourceInfo;
|
|
1090
|
+
readonly extensions?: Readonly<Record<string, unknown>>;
|
|
1091
|
+
}
|
|
1092
|
+
/** Chooses the entry to pay from a deep-frozen copy of the 402's `accepts`; it returns one of those
|
|
1093
|
+
* elements. It can only narrow: the entry must still match the caller's `to` and amount. */
|
|
1094
|
+
type PayPolicy = (accepts: readonly PaymentRequirements[], offer: PayOffer) => PaymentRequirements;
|
|
1095
|
+
/** Parameters for {@link Escro.pay}. FROZEN: `to` and `amountMicroUsdc` stay
|
|
1096
|
+
* required and every other field optional; a required field added later would break
|
|
1097
|
+
* every kit-generated bot. Exactly one of `paymentRequired` and `url` is given. */
|
|
710
1098
|
interface PayParams {
|
|
711
|
-
/** Recipient wallet address (base58). */
|
|
1099
|
+
/** Recipient wallet address (base58): the only worker paid. */
|
|
712
1100
|
readonly to: string;
|
|
713
|
-
/** Amount to pay, in USDC micro-units (integer, 6 decimals). */
|
|
1101
|
+
/** Amount to pay, in USDC micro-units (integer, 6 decimals): the only amount paid. */
|
|
714
1102
|
readonly amountMicroUsdc: number;
|
|
1103
|
+
/** A 402 the caller already decoded; the paid request goes to its `resource.url`. */
|
|
1104
|
+
readonly paymentRequired?: PaymentRequired;
|
|
1105
|
+
/**
|
|
1106
|
+
* An absolute http: or https: URL without credentials, requested for its 402. A `url`, or with
|
|
1107
|
+
* `paymentRequired` the 402's `resource.url`, on a port `fetch` blocks is refused before any
|
|
1108
|
+
* lookup or request.
|
|
1109
|
+
*/
|
|
1110
|
+
readonly url?: string;
|
|
1111
|
+
/** The request being paid for; default a bare `GET`. */
|
|
1112
|
+
readonly request?: PayRequest;
|
|
1113
|
+
/**
|
|
1114
|
+
* Chooses among the entries. Absent, the escrow rail wins: when an `on-delivery` or `job-escrow`
|
|
1115
|
+
* entry matches the caller's terms an `exact` entry is never paid, whatever the 402's order, and
|
|
1116
|
+
* the 402's order decides only within a rail. A policy overrides that.
|
|
1117
|
+
*/
|
|
1118
|
+
readonly policy?: PayPolicy;
|
|
1119
|
+
/** Decides an `acceptance` predicate the 402 carries; absent, such a 402 is refused. */
|
|
1120
|
+
readonly admitAcceptance?: (acceptance: Acceptance) => boolean;
|
|
1121
|
+
/**
|
|
1122
|
+
* Decides each address pay() may connect to. Given, pay() resolves each host it requests (the 402's resource, and on
|
|
1123
|
+
* the escrow rail the job specification's host) once per call with lookup(host, { all: true }), passes every answer
|
|
1124
|
+
* (or the literal address) here with the request's target, and connects only to those answers; an address is admitted
|
|
1125
|
+
* only when this returns true, and one refused answer refuses the call.
|
|
1126
|
+
*/
|
|
1127
|
+
readonly admitAddress?: (address: string, target: "resource" | "spec") => boolean;
|
|
715
1128
|
}
|
|
716
1129
|
/** Result of a completed payment. FROZEN and rail-generic: `reference` is the
|
|
717
1130
|
* rail-native settlement id (a Solana signature for escrow, an x402 receipt for
|
|
@@ -719,9 +1132,157 @@ interface PayParams {
|
|
|
719
1132
|
interface PaymentResult {
|
|
720
1133
|
/** Which rail settled the payment. */
|
|
721
1134
|
readonly rail: Rail;
|
|
722
|
-
/** Rail-native settlement reference
|
|
1135
|
+
/** Rail-native settlement reference: on the escrow rail, the `create_escrow` signature; on the
|
|
1136
|
+
* x402 rail, the settlement's transaction. */
|
|
723
1137
|
readonly reference: string;
|
|
1138
|
+
/** Escrow rail: the escrow's PDA, the handle for `cancelEscrow` and every later call. */
|
|
1139
|
+
readonly escrow?: string;
|
|
1140
|
+
/** The paid request's `PAYMENT-RESPONSE`, decoded. */
|
|
1141
|
+
readonly settlement?: SettlementResponse;
|
|
1142
|
+
/** The paid request's response, its body unread. */
|
|
1143
|
+
readonly response?: Response;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
type PredicateName = "hash-matches" | "tests-pass" | "json-schema" | "file-format" | "pod-receipt" | "llm-rubric" | "ci-check" | "period-sla" | "attestation-valid";
|
|
1147
|
+
/** The job a decision record decides (docs/specs/escro-extension.md "Decision record", `job`). */
|
|
1148
|
+
interface DecisionJob {
|
|
1149
|
+
/** CAIP-2: `solana:<32 base58>` or `eip155:<decimal chain id>`. */
|
|
1150
|
+
network: string;
|
|
1151
|
+
/** Solana: the base58 program id; ERC-8183: the lowercase `0x` contract address. */
|
|
1152
|
+
program: string;
|
|
1153
|
+
/** Solana: the escrow PDA, base58; ERC-8183: the jobId in decimal. */
|
|
1154
|
+
id: string;
|
|
1155
|
+
}
|
|
1156
|
+
/** The one decision record the `escro` extension defines (docs/specs/escro-extension.md "Decision record"). */
|
|
1157
|
+
interface DecisionRecord {
|
|
1158
|
+
acceptance: Acceptance;
|
|
1159
|
+
decision: "pass" | "fail";
|
|
1160
|
+
deliverableHash: string;
|
|
1161
|
+
job: DecisionJob;
|
|
1162
|
+
}
|
|
1163
|
+
interface Delivery {
|
|
1164
|
+
/** The delivered bytes, as the deliverable derivation defines them. */
|
|
1165
|
+
bytes: Uint8Array;
|
|
1166
|
+
/** pod-receipt: a base58 ed25519 signature. */
|
|
1167
|
+
receipt?: string;
|
|
1168
|
+
/** attestation-valid: the attestation as the worker supplied it. */
|
|
1169
|
+
attestation?: Uint8Array;
|
|
1170
|
+
}
|
|
1171
|
+
/** Every external evaluator is the buyer's own function; the library calls nothing else. */
|
|
1172
|
+
interface PredicateContext {
|
|
1173
|
+
runTests?(i: {
|
|
1174
|
+
suite: string;
|
|
1175
|
+
delivery: Uint8Array;
|
|
1176
|
+
}): Promise<{
|
|
1177
|
+
passed: number;
|
|
1178
|
+
failed: number;
|
|
1179
|
+
}>;
|
|
1180
|
+
grade?(i: {
|
|
1181
|
+
rubric: string;
|
|
1182
|
+
model: string;
|
|
1183
|
+
delivery: Uint8Array;
|
|
1184
|
+
}): Promise<number>;
|
|
1185
|
+
ciStatus?(i: {
|
|
1186
|
+
repository: string;
|
|
1187
|
+
revision: string;
|
|
1188
|
+
check: string;
|
|
1189
|
+
}): Promise<"success" | "failure" | "pending" | "missing">;
|
|
1190
|
+
samples?(i: {
|
|
1191
|
+
metric: string;
|
|
1192
|
+
from: number;
|
|
1193
|
+
to: number;
|
|
1194
|
+
}): Promise<number[]>;
|
|
1195
|
+
verifyAttestation?(i: {
|
|
1196
|
+
kind: string;
|
|
1197
|
+
attestation: Uint8Array;
|
|
1198
|
+
}): Promise<{
|
|
1199
|
+
valid: boolean;
|
|
1200
|
+
subjectSha256: string;
|
|
1201
|
+
}>;
|
|
1202
|
+
}
|
|
1203
|
+
interface PredicateOutcome {
|
|
1204
|
+
decision: "pass" | "fail";
|
|
1205
|
+
reason: string;
|
|
1206
|
+
}
|
|
1207
|
+
interface Predicate<P = unknown> {
|
|
1208
|
+
readonly name: PredicateName;
|
|
1209
|
+
/** Throws {@link PredicateParamsError}; callable before funding. */
|
|
1210
|
+
parseParams(raw: unknown): P;
|
|
1211
|
+
evaluate(delivery: Delivery, params: P, ctx: PredicateContext): Promise<PredicateOutcome>;
|
|
1212
|
+
}
|
|
1213
|
+
/** Parameters a predicate does not accept, or that do not hash to the advertised `paramsHash`. */
|
|
1214
|
+
declare class PredicateParamsError extends EscroError {
|
|
1215
|
+
constructor(message: string, options?: {
|
|
1216
|
+
cause?: unknown;
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
/** A decision record, or an `acceptance`, the extension's schema refuses. */
|
|
1220
|
+
declare class PredicateRecordError extends EscroError {
|
|
1221
|
+
constructor(message: string, options?: {
|
|
1222
|
+
cause?: unknown;
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
/** No decision was reached: the buyer's evaluator is absent, failed, or cannot decide yet. */
|
|
1226
|
+
declare class PredicateEvaluationError extends EscroError {
|
|
1227
|
+
constructor(message: string, options?: {
|
|
1228
|
+
cause?: unknown;
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
/** RFC 8785 canonical JSON: a refusal pass ({@link PredicateParamsError}), then the shared `canonicalize`. */
|
|
1232
|
+
declare function jcs(value: unknown): string;
|
|
1233
|
+
/** The SHA-256 hex of the UTF-8 {@link jcs} of `params`: what `acceptance.paramsHash` carries. */
|
|
1234
|
+
declare function paramsHash(params: unknown): string;
|
|
1235
|
+
|
|
1236
|
+
declare const attestationValid: Predicate;
|
|
1237
|
+
|
|
1238
|
+
declare const ciCheck: Predicate;
|
|
1239
|
+
|
|
1240
|
+
declare const fileFormat: Predicate;
|
|
1241
|
+
|
|
1242
|
+
declare const hashMatches: Predicate;
|
|
1243
|
+
|
|
1244
|
+
declare const jsonSchema: Predicate;
|
|
1245
|
+
|
|
1246
|
+
declare const llmRubric: Predicate;
|
|
1247
|
+
|
|
1248
|
+
declare const periodSla: Predicate;
|
|
1249
|
+
|
|
1250
|
+
declare const podReceipt: Predicate;
|
|
1251
|
+
|
|
1252
|
+
declare const testsPass: Predicate;
|
|
1253
|
+
|
|
1254
|
+
/** The `escro` extension's predicate catalogue (docs/specs/escro-extension.md "Predicate catalogue"). */
|
|
1255
|
+
declare const PREDICATES: Readonly<Record<PredicateName, Predicate>>;
|
|
1256
|
+
interface PredicateCheck {
|
|
1257
|
+
acceptance: Acceptance;
|
|
1258
|
+
params: unknown;
|
|
1259
|
+
/** The job the record decides; build it with {@link predicateJob}. */
|
|
1260
|
+
job: DecisionJob;
|
|
1261
|
+
}
|
|
1262
|
+
interface PredicateResult {
|
|
1263
|
+
record: DecisionRecord;
|
|
1264
|
+
memo: string;
|
|
1265
|
+
reason: string;
|
|
724
1266
|
}
|
|
1267
|
+
/**
|
|
1268
|
+
* The job a record decides on Solana: this cluster's CAIP-2 network and Escro program, and the
|
|
1269
|
+
* escrow's address. Throws {@link PredicateRecordError} when `address` is not a canonical base58
|
|
1270
|
+
* key of 32 bytes.
|
|
1271
|
+
*/
|
|
1272
|
+
declare function predicateJob(cluster: SolanaCluster, address: string): DecisionJob;
|
|
1273
|
+
/** The SHA-256 hex of the UTF-8 {@link jcs} of a valid decision record. */
|
|
1274
|
+
declare function decisionRecordHash(record: DecisionRecord): string;
|
|
1275
|
+
/** `escro:predicate:<name>:<pass|fail>:<decisionRecordHash>`. Throws {@link PredicateRecordError}. */
|
|
1276
|
+
declare function predicateMemo(record: DecisionRecord): string;
|
|
1277
|
+
/**
|
|
1278
|
+
* Applies one advertised check to a delivery, in the buyer's process: refuses an `acceptance` the
|
|
1279
|
+
* extension refuses, a `job` the extension refuses, a name this library does not implement, params
|
|
1280
|
+
* the predicate refuses, and params that do not hash to `acceptance.paramsHash`, all before the
|
|
1281
|
+
* predicate runs; then returns the one decision record, naming `check.job`, its memo and the
|
|
1282
|
+
* predicate's reason. Throws {@link PredicateEvaluationError} when the buyer's evaluator reaches
|
|
1283
|
+
* no decision.
|
|
1284
|
+
*/
|
|
1285
|
+
declare function runPredicate(check: PredicateCheck, delivery: Delivery, ctx?: PredicateContext): Promise<PredicateResult>;
|
|
725
1286
|
|
|
726
1287
|
declare class Escro {
|
|
727
1288
|
private readonly connection;
|
|
@@ -729,24 +1290,37 @@ declare class Escro {
|
|
|
729
1290
|
private readonly options;
|
|
730
1291
|
private readonly cluster;
|
|
731
1292
|
private readonly router;
|
|
1293
|
+
private readonly spendCap;
|
|
1294
|
+
private readonly x402SpendCap;
|
|
732
1295
|
constructor(options: EscroOptions);
|
|
733
1296
|
/**
|
|
734
1297
|
* Create a new escrow: registers with the API, signs and submits the
|
|
735
1298
|
* on-chain `create_escrow` transaction, then confirms it with the API.
|
|
1299
|
+
* Before any request it refuses (`VALIDATION_ERROR`) an `assignedWorker` that is not a
|
|
1300
|
+
* base-58 public key or an `amountUsdc` that is not a positive whole number and, on
|
|
1301
|
+
* `"mainnet"`, a client constructed without the `spendCap` option (`SPEND_CAP_REQUIRED`).
|
|
1302
|
+
* With a `spendCap` it refuses (`SPEND_CAP_EXCEEDED`), before the create is sent, a create
|
|
1303
|
+
* whose deposit would pass the cap; see {@link EscroOptions.spendCap}. With
|
|
1304
|
+
* `{ wait: false }` it returns once the create is sent; see {@link SendOptions.wait}.
|
|
1305
|
+
* An error thrown after the transaction was handed to the RPC, unless it shows the transaction
|
|
1306
|
+
* never took effect, is the original error with two own string properties set, `escrowPda` and
|
|
1307
|
+
* `signature`: the create may have landed, and those name it. A rejection that is not an `Error`
|
|
1308
|
+
* becomes a new `Error` carrying the two properties, with the original value as its `cause`.
|
|
736
1309
|
*
|
|
737
|
-
* @returns `{ escrowId, escrowPda, signature }
|
|
1310
|
+
* @returns `{ escrowId, escrowPda, signature }`; use `escrowPda` for all subsequent calls.
|
|
738
1311
|
*/
|
|
739
|
-
createEscrow(params: CreateEscrowParams): Promise<CreateEscrowResult>;
|
|
1312
|
+
createEscrow(params: CreateEscrowParams, options?: SendOptions): Promise<CreateEscrowResult>;
|
|
740
1313
|
/**
|
|
741
1314
|
* Release payment to the worker. Buyer must be the wallet in the constructor.
|
|
742
1315
|
* Builds and submits the `release_payment` on-chain tx FIRST (the chain is the
|
|
743
1316
|
* source of truth), then has the API record it, retrying as
|
|
744
1317
|
* {@link Escro.releasePaymentWithOutcome} does. Use that method to see whether the
|
|
745
|
-
* API recorded the release.
|
|
1318
|
+
* API recorded the release. With `{ wait: false }` it returns once the release is sent and
|
|
1319
|
+
* asks the API to record nothing; see {@link SendOptions.wait}.
|
|
746
1320
|
*
|
|
747
1321
|
* @returns Solana transaction signature.
|
|
748
1322
|
*/
|
|
749
|
-
releasePayment(address: string): Promise<string>;
|
|
1323
|
+
releasePayment(address: string, options?: SendOptions): Promise<string>;
|
|
750
1324
|
/**
|
|
751
1325
|
* {@link Escro.releasePayment}, reporting whether the API recorded the release.
|
|
752
1326
|
* `ESCROW_NOT_SETTLED` (the API's RPC does not yet show the escrow closed), the codes
|
|
@@ -760,47 +1334,93 @@ declare class Escro {
|
|
|
760
1334
|
* @returns `{ signature, confirm }`.
|
|
761
1335
|
*/
|
|
762
1336
|
releasePaymentWithOutcome(address: string): Promise<ReleasePaymentOutcome>;
|
|
1337
|
+
/**
|
|
1338
|
+
* Release payment on a passing predicate result, with its decision memo
|
|
1339
|
+
* (`escro:predicate:<name>:pass:<record hash>`) as one SPL Memo instruction, last, in the
|
|
1340
|
+
* buyer's own `release_payment`. Before anything is signed it refuses, with an
|
|
1341
|
+
* {@link EscroError}, an `address` that is not a base-58 public key (`VALIDATION_ERROR`, before
|
|
1342
|
+
* any read), then a result whose decision is not `pass` (`PREDICATE_NOT_PASSED`), a record the
|
|
1343
|
+
* extension refuses, a record with no `job` included (`PREDICATE_RECORD`), then a record whose
|
|
1344
|
+
* `job` names another network (`PREDICATE_NETWORK_MISMATCH`), another program
|
|
1345
|
+
* (`PREDICATE_PROGRAM_MISMATCH`) or another escrow (`PREDICATE_JOB_MISMATCH`) than this
|
|
1346
|
+
* client's cluster and `address`, all before any read; and, from the escrow's account read on
|
|
1347
|
+
* chain, an escrow that is not on chain, not owned by the Escro program, not SUBMITTED, or whose
|
|
1348
|
+
* committed `deliverable_hash` is not the record's `deliverableHash`
|
|
1349
|
+
* (`PREDICATE_DELIVERABLE_MISMATCH`). The memo is computed from `result.record`, never taken
|
|
1350
|
+
* from `result.memo`. The release then runs and is recorded as
|
|
1351
|
+
* {@link Escro.releasePaymentWithOutcome} does.
|
|
1352
|
+
*
|
|
1353
|
+
* @returns `{ signature, confirm, memo }`.
|
|
1354
|
+
*/
|
|
1355
|
+
releaseWithPredicate(address: string, result: PredicateResult): Promise<ReleaseWithPredicateOutcome>;
|
|
1356
|
+
private assertOwnJob;
|
|
1357
|
+
private assertCommitted;
|
|
1358
|
+
private release;
|
|
1359
|
+
private sendRelease;
|
|
763
1360
|
/**
|
|
764
1361
|
* Raise a dispute for an escrow. Either the buyer or the assigned worker
|
|
765
1362
|
* may call this. Signs and submits the `raise_dispute` on-chain tx, then confirms it with the API.
|
|
1363
|
+
* With `{ wait: false }` it returns once the dispute is sent; `evidence` then is refused
|
|
1364
|
+
* (`VALIDATION_ERROR`) before any request: attach it later with
|
|
1365
|
+
* `confirm(address, signature, { evidence })`. See {@link SendOptions.wait}.
|
|
766
1366
|
*
|
|
767
1367
|
* @returns Solana transaction signature.
|
|
768
1368
|
*/
|
|
769
|
-
raiseDispute(address: string, params: RaiseDisputeParams): Promise<string>;
|
|
1369
|
+
raiseDispute(address: string, params: RaiseDisputeParams, options?: SendOptions): Promise<string>;
|
|
770
1370
|
/**
|
|
771
1371
|
* Cancel a funded escrow before any worker has claimed it.
|
|
772
1372
|
* Buyer must be the wallet in the constructor. Only valid when state is `FUNDED`.
|
|
773
1373
|
* Signs and submits the `cancel_escrow` on-chain tx, then confirms it with the API; full USDC refund to buyer.
|
|
1374
|
+
* With `{ wait: false }` it returns once the cancel is sent; see {@link SendOptions.wait}.
|
|
774
1375
|
*
|
|
775
1376
|
* @returns Solana transaction signature.
|
|
776
1377
|
*/
|
|
777
|
-
cancelEscrow(address: string): Promise<string>;
|
|
1378
|
+
cancelEscrow(address: string, options?: SendOptions): Promise<string>;
|
|
778
1379
|
/**
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
1380
|
+
* Pays an x402 V2 402: `params.url`, which the SDK requests for its 402, or
|
|
1381
|
+
* `params.paymentRequired`, a 402 the caller already decoded. Only an entry paying exactly
|
|
1382
|
+
* `params.amountMicroUsdc` to `params.to` on this client's cluster is paid; `params.policy` can
|
|
1383
|
+
* only narrow the choice. An `on-delivery` (or `job-escrow`) entry is funded through
|
|
1384
|
+
* {@link createEscrow}, with `to` as the assigned worker and its spend cap unchanged, and the
|
|
1385
|
+
* payment is presented once to the URL that answered the 402 (no redirect followed, nothing
|
|
1386
|
+
* retried); the result carries the `create_escrow` signature as `reference`, the escrow PDA, and
|
|
1387
|
+
* the paid request's decoded `PAYMENT-RESPONSE` and response.
|
|
784
1388
|
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
1389
|
+
* Without a `policy` the escrow rail wins: when an `on-delivery` or `job-escrow` entry matches
|
|
1390
|
+
* the caller's terms it is the one paid, whatever the 402's order. An `exact` entry is paid over
|
|
1391
|
+
* the x402 rail, from this wallet, under {@link EscroOptions.x402SpendCap} (required on mainnet):
|
|
1392
|
+
* the official client builds the transaction, a guarded signer checks it against the entry and
|
|
1393
|
+
* the caller's terms before the key runs, and the payment header goes once to the 402's resource
|
|
1394
|
+
* URL, never to a facilitator. The result's `reference` is the settlement's transaction. An `upto`
|
|
1395
|
+
* entry is never paid ({@link EscroPayError} `unsupported_scheme`). A failure after the payment
|
|
1396
|
+
* left the process (`settlement`, `presentation`, `redirect`, `timeout`) carries `payment`, the
|
|
1397
|
+
* Memo text, amount and `payTo`, to match against the wallet's token-account history; the amount
|
|
1398
|
+
* stays counted. x402 V2 has no idempotency key: two calls are two payments, each counted.
|
|
1399
|
+
*
|
|
1400
|
+
* The first request is bounded by 30 s, the paid request by the entry's `maxTimeoutSeconds`; an
|
|
1401
|
+
* entry over 3600 seconds is not paid. A network failure of the first request rejects
|
|
1402
|
+
* {@link EscroError} `NETWORK_ERROR`, with nothing funded. Refusals are {@link EscroPayError}s; a
|
|
1403
|
+
* failure after the escrow is funded carries `escrowPda` and `createSignature`, and
|
|
1404
|
+
* `cancelEscrow(escrowPda)` recovers the deposit while it is Funded. There is no idempotency key:
|
|
1405
|
+
* two calls fund two escrows. The signature is FROZEN.
|
|
788
1406
|
*/
|
|
789
1407
|
pay(params: PayParams): Promise<PaymentResult>;
|
|
790
1408
|
/**
|
|
791
1409
|
* Claim an assigned task. Worker must be the wallet in the constructor.
|
|
792
1410
|
* Signs and submits the `claim_task` on-chain tx, then confirms it with the API.
|
|
1411
|
+
* With `{ wait: false }` it returns once the claim is sent; see {@link SendOptions.wait}.
|
|
793
1412
|
*
|
|
794
1413
|
* @returns Solana transaction signature.
|
|
795
1414
|
*/
|
|
796
|
-
claimTask(address: string): Promise<string>;
|
|
1415
|
+
claimTask(address: string, options?: SendOptions): Promise<string>;
|
|
797
1416
|
/**
|
|
798
1417
|
* Submit a deliverable for the buyer to review. Worker must be the wallet.
|
|
799
1418
|
* Signs and submits the `submit_deliverable` on-chain tx, then confirms it with the API.
|
|
1419
|
+
* With `{ wait: false }` it returns once the submit is sent; see {@link SendOptions.wait}.
|
|
800
1420
|
*
|
|
801
1421
|
* @returns Solana transaction signature.
|
|
802
1422
|
*/
|
|
803
|
-
submitDeliverable(address: string, params: SubmitDeliverableParams): Promise<string>;
|
|
1423
|
+
submitDeliverable(address: string, params: SubmitDeliverableParams, options?: SendOptions): Promise<string>;
|
|
804
1424
|
/**
|
|
805
1425
|
* List tasks assigned to the wallet's public key.
|
|
806
1426
|
* Optionally filter by state(s) and paginate results.
|
|
@@ -808,10 +1428,26 @@ declare class Escro {
|
|
|
808
1428
|
* If `options.poll` is true, polls with exponential backoff until at least
|
|
809
1429
|
* one task is returned.
|
|
810
1430
|
*
|
|
1431
|
+
* Serves open tasks only (FUNDED, IN_PROGRESS, SUBMITTED); a DISPUTED or settled
|
|
1432
|
+
* escrow assigned to the wallet comes from {@link getMyAssignedEscrows}.
|
|
1433
|
+
*
|
|
811
1434
|
* @param state - Filter by one or more states (first state used as API filter).
|
|
812
1435
|
* @param options - Polling, pagination (limit/offset).
|
|
813
1436
|
*/
|
|
814
1437
|
getMyTasks(state?: EscrowState[], options?: PollOptions & ListOptions): Promise<PaginatedResult<EscrowAccount>>;
|
|
1438
|
+
/**
|
|
1439
|
+
* List every escrow assigned to the wallet's public key in any served state,
|
|
1440
|
+
* DISPUTED and the settled states (COMPLETED, REFUNDED) included, unlike
|
|
1441
|
+
* {@link getMyTasks}, which serves open tasks only. Optionally filter by state
|
|
1442
|
+
* and paginate. Never polls.
|
|
1443
|
+
*
|
|
1444
|
+
* A Worker Bot uses this to read its DISPUTED escrows, whose fronted cost stays
|
|
1445
|
+
* committed until arbitration settles them.
|
|
1446
|
+
*
|
|
1447
|
+
* @param state - Filter by one or more states (first state used as API filter).
|
|
1448
|
+
* @param options - Pagination (limit/offset).
|
|
1449
|
+
*/
|
|
1450
|
+
getMyAssignedEscrows(state?: EscrowState[], options?: ListOptions): Promise<PaginatedResult<EscrowAccount>>;
|
|
815
1451
|
/**
|
|
816
1452
|
* List escrows CREATED by the wallet's public key (the maker / buyer), the
|
|
817
1453
|
* mirror of {@link getMyTasks} for the buyer side. Optionally filter by state
|
|
@@ -829,20 +1465,20 @@ declare class Escro {
|
|
|
829
1465
|
* Find worker bots in the EscroBots registry, optionally filtered by
|
|
830
1466
|
* capability. Queries `GET /v1/bots?role=worker` (the API includes `both`
|
|
831
1467
|
* bots) and returns candidates in REGISTRY ORDER: this method does no
|
|
832
|
-
* ranking, scoring, or reordering
|
|
833
|
-
* marketplace
|
|
1468
|
+
* ranking, scoring, or reordering: the directory is an open index with no
|
|
1469
|
+
* curation, not a marketplace. Escro-shipped code never ranks; the caller's own bot decides.
|
|
834
1470
|
*
|
|
835
1471
|
* Each candidate keeps the CLAIM (`descriptor`) separate from the AUTHORSHIP
|
|
836
1472
|
* check (`signatureValid`, verified locally so a third party need not trust the
|
|
837
|
-
* API). Capabilities remain unverified claims; on-chain history (EscroRep
|
|
838
|
-
*
|
|
1473
|
+
* API). Capabilities remain unverified claims; on-chain history (EscroRep)
|
|
1474
|
+
* is their verification, deliberately not merged in here.
|
|
839
1475
|
*/
|
|
840
1476
|
findWorkers(params?: {
|
|
841
1477
|
capability?: string;
|
|
842
1478
|
} & ListOptions): Promise<WorkerCandidate[]>;
|
|
843
1479
|
/**
|
|
844
1480
|
* Fetch the EscroRep bulk export: every indexed wallet's RAW reputation
|
|
845
|
-
* components
|
|
1481
|
+
* components, each wallet exactly once, in one fetch. Returns
|
|
846
1482
|
* the raw components verbatim - this method does NO ranking, scoring, or default
|
|
847
1483
|
* weighting (Escro-shipped code never ranks; the caller's own bot weights and
|
|
848
1484
|
* decides). Selection layers join these components to {@link findWorkers}
|
|
@@ -862,18 +1498,27 @@ declare class Escro {
|
|
|
862
1498
|
* not-yet-visible transaction, an RPC failure, a gateway error or a rate limit
|
|
863
1499
|
* for about 30 s (waiting at least a sent Retry-After), never a rejection. Throws
|
|
864
1500
|
* {@link EscroConfirmError}; calling again is safe (a replay of a recorded
|
|
865
|
-
* transition succeeds).
|
|
1501
|
+
* transition succeeds). An `address` that is not a base-58 public key throws an
|
|
1502
|
+
* {@link EscroError} with code `VALIDATION_ERROR` before any request, not an
|
|
1503
|
+
* `EscroConfirmError`. A successful confirm of a create, or a confirm of its signature
|
|
1504
|
+
* refused `TX_FAILED` (the create landed and failed), ends its in-flight hold under
|
|
1505
|
+
* {@link EscroOptions.spendCap}.
|
|
866
1506
|
*/
|
|
867
1507
|
confirm(address: string, signature: string, opts?: {
|
|
868
1508
|
evidence?: string;
|
|
869
1509
|
}): Promise<EscrowAccount>;
|
|
870
1510
|
private retryRecord;
|
|
1511
|
+
private admitCreate;
|
|
1512
|
+
private dropServed;
|
|
1513
|
+
private readOutstanding;
|
|
871
1514
|
private send;
|
|
872
1515
|
private sendAndConfirm;
|
|
873
1516
|
/**
|
|
874
1517
|
* Fetch an escrow by its PDA address.
|
|
875
1518
|
* If `options.poll` is true, polls with exponential backoff until the escrow
|
|
876
|
-
* appears (useful immediately after a create tx before the API
|
|
1519
|
+
* appears (useful immediately after a create tx before the API records it).
|
|
1520
|
+
* An `address` that is not a base-58 public key throws an {@link EscroError} with code
|
|
1521
|
+
* `VALIDATION_ERROR` at once, with or without `poll`.
|
|
877
1522
|
*/
|
|
878
1523
|
getEscrow(address: string, options?: PollOptions): Promise<EscrowAccount>;
|
|
879
1524
|
}
|
|
@@ -885,10 +1530,11 @@ declare class ApiClient {
|
|
|
885
1530
|
private url;
|
|
886
1531
|
/** GET /v1/escrows/:address */
|
|
887
1532
|
getEscrow(address: string): Promise<EscrowAccount>;
|
|
888
|
-
/** GET /v1/escrows?assignedTo=...&maker=...&state=... */
|
|
1533
|
+
/** GET /v1/escrows?assignedTo=...&maker=...&taker=...&state=... */
|
|
889
1534
|
listEscrows(params: {
|
|
890
1535
|
assignedTo?: string;
|
|
891
1536
|
maker?: string;
|
|
1537
|
+
taker?: string;
|
|
892
1538
|
state?: EscrowState;
|
|
893
1539
|
limit?: number;
|
|
894
1540
|
offset?: number;
|
|
@@ -900,7 +1546,7 @@ declare class ApiClient {
|
|
|
900
1546
|
*/
|
|
901
1547
|
listBots(params: ListBotsParams): Promise<PaginatedResult<BotDescriptor>>;
|
|
902
1548
|
/**
|
|
903
|
-
* GET /rep : EscroRep bulk export
|
|
1549
|
+
* GET /rep : EscroRep bulk export. Unauthenticated public
|
|
904
1550
|
* read (no auth headers). Returns every indexed wallet's RAW components exactly
|
|
905
1551
|
* once (no composite score). Ranking layers join against this ONE bulk fetch:
|
|
906
1552
|
* the per-wallet endpoint shares a 10/min public-metrics budget, so a
|
|
@@ -910,7 +1556,7 @@ declare class ApiClient {
|
|
|
910
1556
|
*/
|
|
911
1557
|
listReputations(): Promise<ServedWalletReputation[]>;
|
|
912
1558
|
/**
|
|
913
|
-
* GET /rep/:wallet : one wallet's EscroRep RAW components
|
|
1559
|
+
* GET /rep/:wallet : one wallet's EscroRep RAW components.
|
|
914
1560
|
* Unauthenticated public read (no auth headers). Unknown wallets return zeroed
|
|
915
1561
|
* components, never 404; a 404 means the deployment mounted no reputation
|
|
916
1562
|
* source and surfaces as {@link ReputationUnavailableError}. Shares the public
|
|
@@ -919,8 +1565,15 @@ declare class ApiClient {
|
|
|
919
1565
|
*/
|
|
920
1566
|
getReputation(wallet: string): Promise<ServedWalletReputation>;
|
|
921
1567
|
/**
|
|
922
|
-
*
|
|
923
|
-
*
|
|
1568
|
+
* GET /v1/escrows/outstanding?maker=: the maker's open deposits (FUNDED, IN_PROGRESS,
|
|
1569
|
+
* SUBMITTED, DISPUTED; never CREATED). Unauthenticated. Abandoned with code `API_TIMEOUT`
|
|
1570
|
+
* after {@link API_REQUEST_TIMEOUT_MS}.
|
|
1571
|
+
*/
|
|
1572
|
+
getOutstandingDeposits(maker: string): Promise<OutstandingDeposits>;
|
|
1573
|
+
/**
|
|
1574
|
+
* POST /v1/escrows: registers the escrow and returns its ids and the unsigned
|
|
1575
|
+
* `create_escrow`. Requires auth. Abandoned with code `API_TIMEOUT` after
|
|
1576
|
+
* {@link API_REQUEST_TIMEOUT_MS}.
|
|
924
1577
|
*/
|
|
925
1578
|
createEscrow(params: CreateEscrowParams): Promise<{
|
|
926
1579
|
escrowId: string;
|
|
@@ -928,14 +1581,14 @@ declare class ApiClient {
|
|
|
928
1581
|
unsignedTx: string;
|
|
929
1582
|
}>;
|
|
930
1583
|
/**
|
|
931
|
-
* POST /v1/escrows/:address/claim
|
|
1584
|
+
* POST /v1/escrows/:address/claim: returns unsigned tx.
|
|
932
1585
|
* Requires auth (worker).
|
|
933
1586
|
*/
|
|
934
1587
|
claimTask(address: string): Promise<{
|
|
935
1588
|
unsignedTx: string;
|
|
936
1589
|
}>;
|
|
937
1590
|
/**
|
|
938
|
-
* POST /v1/escrows/:address/submit
|
|
1591
|
+
* POST /v1/escrows/:address/submit: returns unsigned tx.
|
|
939
1592
|
* Requires auth (worker).
|
|
940
1593
|
*/
|
|
941
1594
|
submitDeliverable(address: string, params: SubmitDeliverableParams): Promise<{
|
|
@@ -950,14 +1603,14 @@ declare class ApiClient {
|
|
|
950
1603
|
*/
|
|
951
1604
|
releasePaymentDb(address: string): Promise<void>;
|
|
952
1605
|
/**
|
|
953
|
-
* POST /v1/escrows/:address/cancel
|
|
1606
|
+
* POST /v1/escrows/:address/cancel: returns unsigned tx.
|
|
954
1607
|
* Requires auth (buyer). Only valid when state is FUNDED.
|
|
955
1608
|
*/
|
|
956
1609
|
cancelEscrow(address: string): Promise<{
|
|
957
1610
|
unsignedTx: string;
|
|
958
1611
|
}>;
|
|
959
1612
|
/**
|
|
960
|
-
* POST /v1/escrows/:address/dispute
|
|
1613
|
+
* POST /v1/escrows/:address/dispute: returns unsigned tx.
|
|
961
1614
|
* Requires auth (buyer or worker).
|
|
962
1615
|
*/
|
|
963
1616
|
raiseDispute(address: string, params: Pick<RaiseDisputeParams, "reason">): Promise<{
|
|
@@ -972,20 +1625,45 @@ declare class ApiClient {
|
|
|
972
1625
|
*/
|
|
973
1626
|
confirm(address: string, signature: string, evidence?: string): Promise<EscrowAccount>;
|
|
974
1627
|
/**
|
|
975
|
-
* GET /v1/stats
|
|
1628
|
+
* GET /v1/stats: public protocol-wide stats.
|
|
976
1629
|
* No auth required. Upstream typing in {@link Escro.getStats} narrows the
|
|
977
1630
|
* return shape.
|
|
978
1631
|
*/
|
|
979
1632
|
getStats(): Promise<unknown>;
|
|
980
1633
|
}
|
|
981
1634
|
|
|
1635
|
+
/** The `code` of each {@link EscroError} the spend cap throws. */
|
|
1636
|
+
declare const SPEND_CAP_ERROR_CODES: {
|
|
1637
|
+
/** A mainnet `createEscrow` on a client constructed without the `spendCap` option. */
|
|
1638
|
+
readonly required: "SPEND_CAP_REQUIRED";
|
|
1639
|
+
/** The create's deposit would pass the cap. */
|
|
1640
|
+
readonly exceeded: "SPEND_CAP_EXCEEDED";
|
|
1641
|
+
/** The outstanding deposits could not be read. */
|
|
1642
|
+
readonly unreadable: "SPEND_CAP_UNREADABLE";
|
|
1643
|
+
};
|
|
1644
|
+
/**
|
|
1645
|
+
* Throws an {@link EscroError} with code `SPEND_CAP_EXCEEDED` when the outstanding deposits plus
|
|
1646
|
+
* the proposed one would pass the cap. All three are integer micro-USDC; reaching the cap exactly
|
|
1647
|
+
* is allowed.
|
|
1648
|
+
*/
|
|
1649
|
+
declare function assertWithinSpendCap(check: {
|
|
1650
|
+
maxOutstandingMicroUsdc: number;
|
|
1651
|
+
outstandingMicroUsdc: number;
|
|
1652
|
+
proposedMicroUsdc: number;
|
|
1653
|
+
}): void;
|
|
1654
|
+
/**
|
|
1655
|
+
* A plain decimal USDC amount (`"12.5"`, at most six decimals, no sign or exponent) as integer
|
|
1656
|
+
* micro-USDC. Throws an {@link EscroError} with code `VALIDATION_ERROR` otherwise.
|
|
1657
|
+
*/
|
|
1658
|
+
declare function parseUsdc(text: string): number;
|
|
1659
|
+
|
|
982
1660
|
/**
|
|
983
1661
|
* The result a {@link ServiceAdapter} returns from `execute`. Escro is agnostic
|
|
984
1662
|
* to what produced it: `content` is the deliverable itself, `contentHash` is the
|
|
985
1663
|
* SHA-256 hex digest the Buyer verifies the deliverable against, and `proofUri`
|
|
986
1664
|
* optionally points at where the content is pinned (IPFS/Arweave) or at a proof.
|
|
987
|
-
* No currency or token field appears here; token conversion is adapter-internal
|
|
988
|
-
*
|
|
1665
|
+
* No currency or token field appears here; token conversion is adapter-internal,
|
|
1666
|
+
* since the escrow vault holds USDC only.
|
|
989
1667
|
*/
|
|
990
1668
|
interface ServiceResult {
|
|
991
1669
|
/** The deliverable itself. */
|
|
@@ -1001,7 +1679,7 @@ interface ServiceResult {
|
|
|
1001
1679
|
* A Worker Bot implements ServiceAdapter to wrap any async service (a Bittensor
|
|
1002
1680
|
* subnet, an Akash deployment, a Render job, ...). Escro never sees what is
|
|
1003
1681
|
* underneath and never sees a non-USDC token: the adapter handles any token
|
|
1004
|
-
* conversion internally
|
|
1682
|
+
* conversion internally. Every pre-built adapter reuses
|
|
1005
1683
|
* this interface and is validated by `assertServiceAdapterContract`.
|
|
1006
1684
|
*/
|
|
1007
1685
|
interface ServiceAdapter {
|
|
@@ -1014,6 +1692,12 @@ interface ServiceAdapter {
|
|
|
1014
1692
|
/** Report whether the underlying service is reachable and ready. */
|
|
1015
1693
|
healthCheck(): Promise<boolean>;
|
|
1016
1694
|
}
|
|
1695
|
+
/**
|
|
1696
|
+
* The buyer's port that fetches the bytes a `proofUri` names (an IPFS or Arweave gateway,
|
|
1697
|
+
* a storage bucket). A throw or rejection is an infrastructure failure that propagates to
|
|
1698
|
+
* the caller, which retries it; it is never a verdict on the deliverable.
|
|
1699
|
+
*/
|
|
1700
|
+
type ResolveProofUri = (proofUri: string) => Promise<string | Buffer> | string | Buffer;
|
|
1017
1701
|
/**
|
|
1018
1702
|
* Map a {@link ServiceResult} onto {@link SubmitDeliverableParams}, surfacing the
|
|
1019
1703
|
* `contentHash` (and `proofUri`, when present) that `submit_deliverable` records.
|
|
@@ -1041,8 +1725,8 @@ declare class AdapterContractError extends EscroError {
|
|
|
1041
1725
|
* ServiceResult produced by `execute(sampleSpec)` when the adapter conforms;
|
|
1042
1726
|
* rejects with an {@link AdapterContractError} listing every violation otherwise.
|
|
1043
1727
|
*
|
|
1044
|
-
* Reusable across adapters (
|
|
1045
|
-
*
|
|
1728
|
+
* Reusable across adapters (the Bittensor subnets, the compute networks, the proof
|
|
1729
|
+
* adapters): a conforming adapter passes, a malformed one fails. The parameter is
|
|
1046
1730
|
* typed `ServiceAdapter`, but the harness validates at runtime: JS callers and
|
|
1047
1731
|
* `as`-cast objects reach this too, so every field is checked defensively.
|
|
1048
1732
|
*/
|
|
@@ -1072,13 +1756,13 @@ type PinContent$3 = (content: string | Buffer) => Promise<string>;
|
|
|
1072
1756
|
|
|
1073
1757
|
/**
|
|
1074
1758
|
* Gradients (Bittensor SN56) ServiceAdapter: the first SHIPPED, supported adapter
|
|
1075
|
-
* (the reference pattern
|
|
1759
|
+
* (the reference pattern the other subnet adapters replicate). A Worker Bot wraps the Gradients
|
|
1076
1760
|
* fine-tuning subnet behind the `ServiceAdapter` interface: it swaps a per-task
|
|
1077
1761
|
* USDC budget into TAO internally, pays subnet miners in TAO to fine-tune, collects
|
|
1078
1762
|
* a checkpoint + eval deliverable, and returns a currency-free `ServiceResult`. The
|
|
1079
1763
|
* Buyer and the escrow contract only ever see USDC; no TAO-typed value crosses this
|
|
1080
|
-
* boundary into SDK core (
|
|
1081
|
-
*
|
|
1764
|
+
* boundary into SDK core (the branded `Tao` type of ../bittensor/index.ts keeps it out
|
|
1765
|
+
* at compile time for the Bittensor trio).
|
|
1082
1766
|
*
|
|
1083
1767
|
* The swap, subnet call, and pinning are injectable ports so the reference runs (and
|
|
1084
1768
|
* is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
|
|
@@ -1087,11 +1771,11 @@ type PinContent$3 = (content: string | Buffer) => Promise<string>;
|
|
|
1087
1771
|
* RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (checkpoint
|
|
1088
1772
|
* + eval JSON). Whether the eval clears the threshold is decided by the BUYER's
|
|
1089
1773
|
* review.ts, which independently recomputes the score (see `scoreGradientsDemoDeliverable`).
|
|
1090
|
-
* The worker never scores-for-release and never releases
|
|
1774
|
+
* The worker never scores-for-release and never releases: the buyer is the judge.
|
|
1091
1775
|
*
|
|
1092
1776
|
* Relationship to `examples/worker-bot/bittensor-adapter.ts`: that example is
|
|
1093
1777
|
* pedagogy ("author your own adapter against the public interface", driven by e2e
|
|
1094
|
-
* scenario 13
|
|
1778
|
+
* scenario 13); THIS module is the shipped, importable
|
|
1095
1779
|
* surface a generated bot uses. The USDC->TAO port skeleton and the execute shape are
|
|
1096
1780
|
* shared with the other Bittensor adapters via `../bittensor/index.js`; this module
|
|
1097
1781
|
* supplies only its subnet identity, capabilities, budget, and demo logic.
|
|
@@ -1166,8 +1850,7 @@ interface RidgesAdapterConfig {
|
|
|
1166
1850
|
}
|
|
1167
1851
|
/**
|
|
1168
1852
|
* Stable id/capabilities. Locked against `ADAPTER_DESCRIPTORS.ridges` by a kit test
|
|
1169
|
-
*
|
|
1170
|
-
* package, and is landed with the barrel wiring — LANE-NOTES merge step 3).
|
|
1853
|
+
* (the lock lives in create-escro-bot, which depends on this package).
|
|
1171
1854
|
*/
|
|
1172
1855
|
declare const RIDGES_ADAPTER_ID = "ridges";
|
|
1173
1856
|
declare const RIDGES_CAPABILITIES: readonly ["code-generation"];
|
|
@@ -1213,8 +1896,8 @@ declare function createRidgesAdapter(config?: RidgesAdapterConfig): ServiceAdapt
|
|
|
1213
1896
|
* it swaps a per-task USDC budget into TAO internally, pays subnet miners in TAO to
|
|
1214
1897
|
* generate a batch of 3D assets, collects the batch deliverable, and returns a
|
|
1215
1898
|
* currency-free `ServiceResult`. The Buyer and the escrow contract only ever see USDC;
|
|
1216
|
-
* no TAO-typed value crosses this boundary into SDK core (
|
|
1217
|
-
* ../bittensor/
|
|
1899
|
+
* no TAO-typed value crosses this boundary into SDK core (the branded `Tao` type of
|
|
1900
|
+
* ../bittensor/index.ts keeps it out at compile time for the Bittensor trio).
|
|
1218
1901
|
*
|
|
1219
1902
|
* The swap, subnet call, and pinning are injectable ports so the reference runs (and
|
|
1220
1903
|
* is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
|
|
@@ -1229,7 +1912,7 @@ declare function createRidgesAdapter(config?: RidgesAdapterConfig): ServiceAdapt
|
|
|
1229
1912
|
* completeness). That recompute reads the DECLARED descriptors, not the asset bytes: a
|
|
1230
1913
|
* production 404gen buyer generating novel assets must derive the container from the
|
|
1231
1914
|
* fetched asset's magic bytes and the polygon count from its parsed geometry before
|
|
1232
|
-
* releasing. The worker never scores-for-release and never releases
|
|
1915
|
+
* releasing. The worker never scores-for-release and never releases: the buyer is the judge.
|
|
1233
1916
|
*
|
|
1234
1917
|
* The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor
|
|
1235
1918
|
* adapters via `../bittensor/index.js`; this module supplies only its subnet identity,
|
|
@@ -1297,13 +1980,13 @@ declare function create404genAdapter(config?: Gen404AdapterConfig): ServiceAdapt
|
|
|
1297
1980
|
|
|
1298
1981
|
/**
|
|
1299
1982
|
* Lium (Bittensor SN51) ServiceAdapter: a SHIPPED, supported adapter following the
|
|
1300
|
-
*
|
|
1983
|
+
* Gradients pattern. A Worker Bot wraps the Lium GPU-compute subnet behind the
|
|
1301
1984
|
* `ServiceAdapter` interface: it swaps a per-task USDC budget into TAO internally,
|
|
1302
1985
|
* rents GPU compute from subnet miners in TAO to run the job, collects the output
|
|
1303
1986
|
* artifact, and returns a currency-free `ServiceResult`. The Buyer and the escrow
|
|
1304
1987
|
* contract only ever see USDC; no TAO-typed value crosses this boundary into SDK core
|
|
1305
|
-
* (
|
|
1306
|
-
*
|
|
1988
|
+
* (the branded `Tao` type of ../bittensor/index.ts keeps it out at compile time for the
|
|
1989
|
+
* Bittensor trio).
|
|
1307
1990
|
*
|
|
1308
1991
|
* The swap, GPU-job call, and pinning are injectable ports so the reference runs (and
|
|
1309
1992
|
* is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
|
|
@@ -1315,7 +1998,7 @@ declare function create404genAdapter(config?: Gen404AdapterConfig): ServiceAdapt
|
|
|
1315
1998
|
* the BUYER's review.ts, which independently recomputes the scripted job's output and
|
|
1316
1999
|
* compares hashes (see `scoreLiumDemoDeliverable`). The worker never scores-for-release
|
|
1317
2000
|
* and never releases, and its self-reported `artifactHash` is never trusted
|
|
1318
|
-
* (
|
|
2001
|
+
* (the buyer is the judge).
|
|
1319
2002
|
*
|
|
1320
2003
|
* The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor
|
|
1321
2004
|
* adapters via `../bittensor/index.js`; this module supplies only its subnet identity,
|
|
@@ -1354,8 +2037,8 @@ declare const LIUM_DEMO_ACCEPT_FLOOR = 1;
|
|
|
1354
2037
|
*/
|
|
1355
2038
|
declare function computeLiumDemoArtifact(): string;
|
|
1356
2039
|
/**
|
|
1357
|
-
* The canned Lium demo job. Deterministic; its specHash is pinned by a test
|
|
1358
|
-
*
|
|
2040
|
+
* The canned Lium demo job. Deterministic; its specHash is pinned by a test because
|
|
2041
|
+
* the buyer journey depends on hash stability.
|
|
1359
2042
|
*/
|
|
1360
2043
|
declare const liumDemoJobSpec: TaskSpec;
|
|
1361
2044
|
/**
|
|
@@ -1370,8 +2053,8 @@ declare function solveLiumDemo(): string;
|
|
|
1370
2053
|
* when the deliverable satisfies all three criteria and 0 otherwise. It checks
|
|
1371
2054
|
* completion (status), artifact presence, and hash match by RECOMPUTING the scripted
|
|
1372
2055
|
* job's output and comparing the substantive artifact; it deliberately IGNORES any
|
|
1373
|
-
* self-reported `artifactHash`, so release can never be worker-controlled
|
|
1374
|
-
*
|
|
2056
|
+
* self-reported `artifactHash`, so release can never be worker-controlled.
|
|
2057
|
+
* Malformed or unparseable content scores 0 and never throws.
|
|
1375
2058
|
*/
|
|
1376
2059
|
declare function scoreLiumDemoDeliverable(content: string | Buffer): number;
|
|
1377
2060
|
/**
|
|
@@ -1404,8 +2087,8 @@ type RunAkashDeployment = (spec: TaskSpec, budget: Akt) => Promise<string | Buff
|
|
|
1404
2087
|
type PinContent$1 = (content: string | Buffer) => Promise<string>;
|
|
1405
2088
|
/**
|
|
1406
2089
|
* Stable id/capabilities. The adapter's own tests pin its runtime output to these
|
|
1407
|
-
* constants; the EscroBots registry descriptor for `akash` is registered separately
|
|
1408
|
-
*
|
|
2090
|
+
* constants; the EscroBots registry descriptor for `akash` is registered separately (the
|
|
2091
|
+
* capability taxonomy).
|
|
1409
2092
|
*/
|
|
1410
2093
|
declare const AKASH_ADAPTER_ID = "akash";
|
|
1411
2094
|
declare const AKASH_CAPABILITIES: readonly ["cloud-compute"];
|
|
@@ -1539,7 +2222,7 @@ declare function scoreRenderDemoDeliverable(content: string | Buffer): number;
|
|
|
1539
2222
|
*/
|
|
1540
2223
|
declare function createRenderAdapter(config?: RenderAdapterConfig): ServiceAdapter;
|
|
1541
2224
|
|
|
1542
|
-
/** Stable adapter identity + EscroBots capability (
|
|
2225
|
+
/** Stable adapter identity + EscroBots capability (pinned by a test). */
|
|
1543
2226
|
declare const GENSYN_ADAPTER_ID = "gensyn";
|
|
1544
2227
|
declare const GENSYN_CAPABILITIES: readonly ["verifiable-compute"];
|
|
1545
2228
|
/** REE proof scheme tag. A verifier accepts only proofs carrying this exact scheme. */
|
|
@@ -1627,20 +2310,53 @@ interface AutoReleaseDecision {
|
|
|
1627
2310
|
/**
|
|
1628
2311
|
* The buyer bot's auto-release decision for a Gensyn deliverable. Releases ONLY when
|
|
1629
2312
|
* the REE proof verifies against the delivered content and the commissioned spec;
|
|
1630
|
-
* an invalid or malformed proof never releases. This is the whole
|
|
2313
|
+
* an invalid or malformed proof never releases. This is the whole acceptance
|
|
1631
2314
|
* mechanism, and it lives entirely at the buyer layer.
|
|
1632
2315
|
*/
|
|
1633
2316
|
declare function gensynAutoRelease(bundle: GensynDeliverableBundle, ctx: {
|
|
1634
2317
|
spec: TaskSpec;
|
|
1635
2318
|
reproduce?: ReproduceCompute;
|
|
1636
2319
|
}): AutoReleaseDecision;
|
|
2320
|
+
/** Encode the document a Gensyn worker pins: the deliverable content and its REE proof. */
|
|
2321
|
+
declare function encodeGensynBundle(bundle: {
|
|
2322
|
+
content: string;
|
|
2323
|
+
proof: ReeProof;
|
|
2324
|
+
}): string;
|
|
2325
|
+
/**
|
|
2326
|
+
* Decode the document a `proofUri` resolves to. Returns null unless it parses to an object
|
|
2327
|
+
* with a string `content` and an object `proof` (the proof itself is verified later).
|
|
2328
|
+
*/
|
|
2329
|
+
declare function decodeGensynBundle(document: string | Buffer): GensynDeliverableBundle | null;
|
|
2330
|
+
/** Options for {@link gensynProofAutoRelease}. */
|
|
2331
|
+
interface GensynProofAutoReleaseOptions {
|
|
2332
|
+
/**
|
|
2333
|
+
* Fetch the bundle document the submitted `proofUri` names. A throw or rejection
|
|
2334
|
+
* propagates (retried), never a verdict.
|
|
2335
|
+
*/
|
|
2336
|
+
resolveProofUri: ResolveProofUri;
|
|
2337
|
+
/** The task spec the buyer commissioned; the proof must bind it. */
|
|
2338
|
+
spec: TaskSpec;
|
|
2339
|
+
/** The reproducible compute; defaults to the reference {@link reproduceGensynCompute}. */
|
|
2340
|
+
reproduce?: ReproduceCompute;
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Buyer-layer auto-release over the pinned Gensyn bundle. It resolves `proofUri` through
|
|
2344
|
+
* `resolveProofUri`, requires the bundle's content to re-hash to the worker-submitted
|
|
2345
|
+
* `contentHash`, then releases only when {@link gensynAutoRelease} does; anything else
|
|
2346
|
+
* DISPUTES. A resolver that throws propagates: an infrastructure failure is not a verdict.
|
|
2347
|
+
* Construction throws `ADAPTER_CONFIG_ERROR` when `resolveProofUri` or `spec` is missing.
|
|
2348
|
+
*/
|
|
2349
|
+
declare function gensynProofAutoRelease(opts: GensynProofAutoReleaseOptions): ReviewPolicy;
|
|
1637
2350
|
/** Configuration and injectable ports for {@link createGensynAdapter}. */
|
|
1638
2351
|
interface GensynAdapterConfig {
|
|
1639
2352
|
/** Advertised capabilities for EscroBots discovery. Defaults to `["verifiable-compute"]`. */
|
|
1640
2353
|
capabilities?: string[];
|
|
1641
2354
|
/** The reproducible compute the worker runs. Default: the reference LCG walk. */
|
|
1642
2355
|
runCompute?: ReproduceCompute;
|
|
1643
|
-
/**
|
|
2356
|
+
/**
|
|
2357
|
+
* Pinning port: receives the bundle document ({@link encodeGensynBundle}) and returns its
|
|
2358
|
+
* reference. Default: a deterministic `ipfs://` placeholder URI over those bytes.
|
|
2359
|
+
*/
|
|
1644
2360
|
pin?: (content: string | Buffer) => Promise<string>;
|
|
1645
2361
|
/** Health-check port. Default: resolves `true`. */
|
|
1646
2362
|
checkHealth?: () => Promise<boolean>;
|
|
@@ -1649,8 +2365,8 @@ interface GensynAdapterConfig {
|
|
|
1649
2365
|
declare const gensynDemoJobSpec: TaskSpec;
|
|
1650
2366
|
/**
|
|
1651
2367
|
* Build a Gensyn {@link ServiceAdapter}. `execute` runs the reproducible compute,
|
|
1652
|
-
* serializes the deliverable,
|
|
1653
|
-
* buyer verifies with {@link
|
|
2368
|
+
* serializes the deliverable, builds its REE proof and pins the bundle of both; `proofUri`
|
|
2369
|
+
* names that bundle, which the buyer verifies with {@link gensynProofAutoRelease}. Passes
|
|
1654
2370
|
* `assertServiceAdapterContract` with the default ports; supply real ports (a real
|
|
1655
2371
|
* Gensyn job runner, a real pinner) for production.
|
|
1656
2372
|
*/
|
|
@@ -1663,7 +2379,7 @@ declare const ZKML_CAPABILITIES: readonly ["zk-verified-inference"];
|
|
|
1663
2379
|
declare const ZKML_DEMO_MARKER = "zkml-demo-v1";
|
|
1664
2380
|
/** The reference proving scheme this verifier understands. Unknown schemes are malformed to it. */
|
|
1665
2381
|
declare const ZKML_PROOF_SCHEME = "escro-zkml-ref-v1";
|
|
1666
|
-
/** Prefix marking
|
|
2382
|
+
/** Prefix marking a ZKML bundle document, the bytes a worker pins: `zkml-proof:<base64url(json)>`. */
|
|
1667
2383
|
declare const ZKML_PROOF_URI_PREFIX = "zkml-proof:";
|
|
1668
2384
|
/**
|
|
1669
2385
|
* A ZKML proof: its public inputs plus a `verificationTag` binding them. In the
|
|
@@ -1690,15 +2406,21 @@ declare function buildZkmlProof(args: {
|
|
|
1690
2406
|
inputCommitment: string;
|
|
1691
2407
|
outputHash: string;
|
|
1692
2408
|
}): ZkmlProof;
|
|
1693
|
-
/**
|
|
1694
|
-
|
|
2409
|
+
/** The document a ZKML worker pins: the deliverable content and the proof over it. */
|
|
2410
|
+
interface ZkmlProofBundle {
|
|
2411
|
+
/** The deliverable content; its SHA-256 is the escrow's on-chain `contentHash`. */
|
|
2412
|
+
content: string;
|
|
2413
|
+
/** The proof binding `content` to the committed model and input. */
|
|
2414
|
+
proof: ZkmlProof;
|
|
2415
|
+
}
|
|
2416
|
+
/** Encode a bundle as the document a worker pins; `proofUri` is that document's reference. */
|
|
2417
|
+
declare function encodeZkmlProofUri(bundle: ZkmlProofBundle): string;
|
|
1695
2418
|
/**
|
|
1696
|
-
* Decode
|
|
1697
|
-
*
|
|
1698
|
-
*
|
|
1699
|
-
* {@link verifyZkmlProof} directly).
|
|
2419
|
+
* Decode the document a `proofUri` resolves to back to a {@link ZkmlProofBundle}. Returns
|
|
2420
|
+
* null for a document without the prefix, an undecodable payload, a `content` that is not
|
|
2421
|
+
* a string or a `proof` that is not proof-shaped.
|
|
1700
2422
|
*/
|
|
1701
|
-
declare function decodeZkmlProofUri(
|
|
2423
|
+
declare function decodeZkmlProofUri(document: string | Buffer): ZkmlProofBundle | null;
|
|
1702
2424
|
/**
|
|
1703
2425
|
* The outcome of verifying a proof. `malformed` = the verifier cannot understand the
|
|
1704
2426
|
* proof (missing/wrong-typed fields, unsupported scheme, undecodable URI); `invalid`
|
|
@@ -1712,24 +2434,29 @@ type ZkmlVerification = {
|
|
|
1712
2434
|
category: "invalid" | "malformed";
|
|
1713
2435
|
reason: string;
|
|
1714
2436
|
};
|
|
1715
|
-
/** What the Buyer expects the proof to attest to. */
|
|
2437
|
+
/** What the Buyer expects the proof to attest to: values the Buyer computes itself. */
|
|
1716
2438
|
interface ZkmlExpectation {
|
|
1717
2439
|
/** The submitted deliverable's contentHash; the proof's outputHash must equal it. */
|
|
1718
2440
|
contentHash: string;
|
|
1719
|
-
/**
|
|
1720
|
-
modelCommitment
|
|
2441
|
+
/** The model the Buyer hired; the proof's modelCommitment must equal it. */
|
|
2442
|
+
modelCommitment: string;
|
|
2443
|
+
/** The Buyer's commitment over its own input; the proof's inputCommitment must equal it. */
|
|
2444
|
+
inputCommitment: string;
|
|
1721
2445
|
}
|
|
1722
2446
|
/**
|
|
1723
2447
|
* Verify a decoded proof against the Buyer's expectation. NOTE: this is the REFERENCE
|
|
1724
2448
|
* verifier and is NOT cryptographically sound -- the tag is a keyless hash, so a `valid`
|
|
1725
|
-
* result means only that the proof is internally consistent and bound to
|
|
1726
|
-
*
|
|
2449
|
+
* result means only that the proof is internally consistent and bound to the expected
|
|
2450
|
+
* output, model and input, not that a trustworthy party produced it. Pass a real verifier
|
|
1727
2451
|
* to {@link zkmlProofAutoRelease} for production. `malformed` = an unusable proof;
|
|
1728
2452
|
* `invalid` = a usable proof that fails the checks.
|
|
1729
2453
|
*/
|
|
1730
2454
|
declare function verifyZkmlProof(proof: unknown, expected: ZkmlExpectation): ZkmlVerification;
|
|
1731
|
-
/**
|
|
1732
|
-
|
|
2455
|
+
/**
|
|
2456
|
+
* Decode the document a `proofUri` resolved to (or reject an absent or foreign one),
|
|
2457
|
+
* require its content to hash to `expected.contentHash`, then verify its proof.
|
|
2458
|
+
*/
|
|
2459
|
+
declare function verifyZkmlProofUri(document: string | Buffer | null | undefined, expected: ZkmlExpectation): ZkmlVerification;
|
|
1733
2460
|
/** The submitted deliverable as the Buyer's review reads it off the escrow read model. */
|
|
1734
2461
|
type ZkmlDeliverable = ReviewDeliverable;
|
|
1735
2462
|
/** A release decision: release, and if not, whether to contest via dispute. */
|
|
@@ -1739,40 +2466,35 @@ type ZkmlReviewPolicy = ReviewPolicy;
|
|
|
1739
2466
|
/** Options for {@link zkmlProofAutoRelease}. */
|
|
1740
2467
|
interface ZkmlProofAutoReleaseOptions {
|
|
1741
2468
|
/**
|
|
1742
|
-
* Fetch the
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1745
|
-
* buyer template's `evalThresholdReview`). Required: without the artifact the predicate
|
|
1746
|
-
* would be trusting a worker-chosen number.
|
|
2469
|
+
* Fetch the bundle document the submitted `proofUri` names. Required: the content and
|
|
2470
|
+
* its proof come only from that document. A throw or rejection propagates (retried),
|
|
2471
|
+
* never a verdict.
|
|
1747
2472
|
*/
|
|
1748
|
-
|
|
1749
|
-
/**
|
|
1750
|
-
modelCommitment
|
|
2473
|
+
resolveProofUri: ResolveProofUri;
|
|
2474
|
+
/** The model the Buyer hired; the proof's modelCommitment must equal it. */
|
|
2475
|
+
modelCommitment: string;
|
|
2476
|
+
/** The Buyer's commitment over its own spec ({@link computeZkmlInputCommitment}). */
|
|
2477
|
+
inputCommitment: string;
|
|
1751
2478
|
/**
|
|
1752
2479
|
* The proof verifier. DEFAULT is {@link verifyZkmlProof}, the reference verifier, which
|
|
1753
2480
|
* is NOT cryptographically sound. A production buyer MUST pass a real SNARK/STARK
|
|
1754
2481
|
* verifier here; the default is for demos only.
|
|
1755
2482
|
*/
|
|
1756
2483
|
verify?: (proof: ZkmlProof, expected: ZkmlExpectation) => ZkmlVerification;
|
|
1757
|
-
/**
|
|
1758
|
-
* Resolve a non-inline (pinned) proof URI to a proof. Default: only inline
|
|
1759
|
-
* `zkml-proof:` URIs are understood; a pinned `ipfs://` proof needs this port.
|
|
1760
|
-
*/
|
|
1761
|
-
fetchProof?: (uri: string) => Promise<ZkmlProof | null> | ZkmlProof | null;
|
|
1762
2484
|
}
|
|
1763
2485
|
/**
|
|
1764
|
-
* Buyer-layer auto-release predicate for zk-verified jobs.
|
|
1765
|
-
*
|
|
1766
|
-
* `
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
2486
|
+
* Buyer-layer auto-release predicate for zk-verified jobs. It resolves `proofUri` through
|
|
2487
|
+
* `resolveProofUri` to the pinned bundle, requires the bundle's content to re-hash to the
|
|
2488
|
+
* worker-submitted `contentHash`, and requires the proof's output, model and input to equal
|
|
2489
|
+
* that hash, the pinned model and the Buyer's input commitment (checked here, whatever
|
|
2490
|
+
* `verify` returns); `verify` then decides. Anything else DISPUTES. Disputing rather than
|
|
2491
|
+
* holding is deliberate -- a held SUBMITTED escrow is auto-released to the worker by the
|
|
2492
|
+
* 24h protocol timeout, so a buyer who required a proof contests a missing/invalid one
|
|
1770
2493
|
* instead of letting it time out to release. This is the Buyer's judgment, not the
|
|
1771
|
-
* protocol's. Soundness
|
|
1772
|
-
*
|
|
1773
|
-
*
|
|
1774
|
-
*
|
|
1775
|
-
* dispute.
|
|
2494
|
+
* protocol's. Soundness lives in the `verify` option; the default reference verifier is a
|
|
2495
|
+
* demo and proves nothing on its own. A resolver that throws PROPAGATES: a transient infra
|
|
2496
|
+
* failure is not a verdict, so the caller retries it -- it is never silently converted into
|
|
2497
|
+
* a dispute. Construction throws `ADAPTER_CONFIG_ERROR` when a required option is missing.
|
|
1776
2498
|
*/
|
|
1777
2499
|
declare function zkmlProofAutoRelease(opts: ZkmlProofAutoReleaseOptions): ZkmlReviewPolicy;
|
|
1778
2500
|
/** What an inference run yields: the output plus the commitments the proof binds. */
|
|
@@ -1798,29 +2520,578 @@ interface ZkmlAdapterConfig {
|
|
|
1798
2520
|
output: ZkmlInferenceOutput;
|
|
1799
2521
|
outputHash: string;
|
|
1800
2522
|
}) => Promise<ZkmlProof> | ZkmlProof;
|
|
1801
|
-
/**
|
|
1802
|
-
|
|
2523
|
+
/**
|
|
2524
|
+
* Pinning port: receives the bundle document ({@link encodeZkmlProofUri}) and returns its
|
|
2525
|
+
* reference. Default: `ipfs://placeholder-<16 hex of the document's sha256>`, which stores
|
|
2526
|
+
* nothing; a production worker pins the document to IPFS/Arweave.
|
|
2527
|
+
*/
|
|
2528
|
+
pin?: (document: string) => Promise<string> | string;
|
|
1803
2529
|
/** Health-check port. Default: resolves `true`. */
|
|
1804
2530
|
checkHealth?: () => Promise<boolean>;
|
|
1805
2531
|
}
|
|
1806
2532
|
/**
|
|
1807
|
-
* The canned zk-verified-inference demo job
|
|
1808
|
-
* classification the buyer template's
|
|
2533
|
+
* The canned zk-verified-inference demo job: a deterministic
|
|
2534
|
+
* classification the buyer template's demo journey hires this bot for.
|
|
1809
2535
|
* Acceptance is machine-checkable by the buyer via {@link zkmlProofAutoRelease}.
|
|
1810
2536
|
*/
|
|
1811
2537
|
declare const zkmlDemoJobSpec: TaskSpec;
|
|
2538
|
+
/** Commitment to the demo model: the value a buyer of the demo job pins. */
|
|
2539
|
+
declare const ZKML_DEMO_MODEL_COMMITMENT: string;
|
|
2540
|
+
/** The buyer's commitment over its own spec: the `inputCommitment` a proof must attest. */
|
|
2541
|
+
declare function computeZkmlInputCommitment(spec: TaskSpec): string;
|
|
1812
2542
|
/**
|
|
1813
2543
|
* The reference solution to the demo job: the classifier's output as canonical JSON.
|
|
1814
2544
|
* Deterministic. Exposed so the demo journey and tests share one source of truth.
|
|
1815
2545
|
*/
|
|
1816
2546
|
declare function solveZkmlDemo(): string;
|
|
1817
2547
|
/**
|
|
1818
|
-
* Build a ZKML {@link ServiceAdapter}.
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
2548
|
+
* Build a ZKML {@link ServiceAdapter}. `execute` pins the bundle of the delivered content and
|
|
2549
|
+
* its proof and returns that document's reference as `proofUri`. Passes
|
|
2550
|
+
* `assertServiceAdapterContract` with the default ports; the default pin stores nothing, so
|
|
2551
|
+
* a release needs a real pin and the buyer's `resolveProofUri` in {@link zkmlProofAutoRelease}.
|
|
2552
|
+
* Supply real ports (a genuine inference call, a real prover, a pin to IPFS/Arweave) for
|
|
2553
|
+
* production use.
|
|
1822
2554
|
*/
|
|
1823
2555
|
declare function createZkmlAdapter(config?: ZkmlAdapterConfig): ServiceAdapter;
|
|
1824
2556
|
|
|
1825
|
-
|
|
1826
|
-
|
|
2557
|
+
/**
|
|
2558
|
+
* The RPC methods the reader calls; a web3.js Connection satisfies it. A history holding a
|
|
2559
|
+
* version-1 transaction reads only through a connection {@link chainReadConnection} builds; a
|
|
2560
|
+
* custom transport (headers, a proxy, a test double) goes in as its `fetchFn`. A connection built
|
|
2561
|
+
* any other way fails a version-1 history with `CHAIN_RPC_FAILED`, whose archival advice does not
|
|
2562
|
+
* apply to that failure.
|
|
2563
|
+
*/
|
|
2564
|
+
type ChainReadRpc = Pick<Connection, "getAccountInfo" | "getSignaturesForAddress" | "getTransaction">;
|
|
2565
|
+
type ChainReadTarget = {
|
|
2566
|
+
address: string;
|
|
2567
|
+
} | {
|
|
2568
|
+
buyer: string;
|
|
2569
|
+
taskId: string;
|
|
2570
|
+
};
|
|
2571
|
+
interface ReadEscrowFromChainOptions {
|
|
2572
|
+
/** Selects the program id through `getProgramId`; a localnet run of the devnet build is "devnet". */
|
|
2573
|
+
cluster: SolanaCluster;
|
|
2574
|
+
/**
|
|
2575
|
+
* The RPC read. A history holding a version-1 transaction reads only through a connection
|
|
2576
|
+
* {@link chainReadConnection} builds; a custom transport (headers, a proxy, a test double) goes
|
|
2577
|
+
* in as its `fetchFn`. A connection built any other way fails a version-1 history with
|
|
2578
|
+
* `CHAIN_RPC_FAILED`, whose archival advice does not apply to that failure.
|
|
2579
|
+
*/
|
|
2580
|
+
rpc: ChainReadRpc;
|
|
2581
|
+
/** The most getTransaction calls one read makes; default {@link CHAIN_READ_MAX_TRANSACTIONS}. */
|
|
2582
|
+
maxTransactions?: number;
|
|
2583
|
+
}
|
|
2584
|
+
/** Every EscrowAccount field by its IDL name (snake_case), u64 as bigint, i64 as number, pubkeys base58. */
|
|
2585
|
+
type DecodedEscrowAccount = Record<string, string | number | bigint | null>;
|
|
2586
|
+
interface ChainEscrowFigures {
|
|
2587
|
+
address: string;
|
|
2588
|
+
buyer: string;
|
|
2589
|
+
worker: string | null;
|
|
2590
|
+
taskId: string;
|
|
2591
|
+
amountMicro: bigint;
|
|
2592
|
+
feeBps: number;
|
|
2593
|
+
/** `escrowFee(amountMicro, feeBps)`, the escrow's own stored rate. */
|
|
2594
|
+
feeMicro: bigint;
|
|
2595
|
+
/** What the buyer deposited: amount plus fee. */
|
|
2596
|
+
depositMicro: bigint;
|
|
2597
|
+
deadline: number;
|
|
2598
|
+
specHash: string;
|
|
2599
|
+
createdAt: number;
|
|
2600
|
+
deliverableHash: string | null;
|
|
2601
|
+
proofUri: string | null;
|
|
2602
|
+
submittedAt: number | null;
|
|
2603
|
+
}
|
|
2604
|
+
interface ChainSettlement {
|
|
2605
|
+
kind: "released" | "refunded" | "cancelled";
|
|
2606
|
+
/** PaymentReleased.worker_amount. */
|
|
2607
|
+
workerAmountMicro: bigint | null;
|
|
2608
|
+
/** PaymentReleased.fee_amount. */
|
|
2609
|
+
feeAmountMicro: bigint | null;
|
|
2610
|
+
/** BuyerRefunded or EscrowCancelled refund_amount. */
|
|
2611
|
+
refundAmountMicro: bigint | null;
|
|
2612
|
+
/** The event's resolved_at, or cancelled_at for a cancel. */
|
|
2613
|
+
resolvedAt: number;
|
|
2614
|
+
/** The settling transaction. */
|
|
2615
|
+
signature: string;
|
|
2616
|
+
}
|
|
2617
|
+
interface ChainEscrowReading {
|
|
2618
|
+
source: "account" | "history";
|
|
2619
|
+
cluster: SolanaCluster;
|
|
2620
|
+
programId: string;
|
|
2621
|
+
/** FUNDED to DISPUTED while open; COMPLETED, REFUNDED or CANCELLED once closed. */
|
|
2622
|
+
state: EscrowState;
|
|
2623
|
+
/** From an account, the state is DISPUTED; from history, a DisputeRaised is in the lifecycle. */
|
|
2624
|
+
disputed: boolean;
|
|
2625
|
+
figures: ChainEscrowFigures;
|
|
2626
|
+
/** Null while open. */
|
|
2627
|
+
settlement: ChainSettlement | null;
|
|
2628
|
+
/** From history, the lifecycle's successful transactions, oldest first; from an account, none. */
|
|
2629
|
+
signatures: string[];
|
|
2630
|
+
}
|
|
2631
|
+
type ChainReadErrorCode = "CHAIN_ESCROW_NOT_FOUND" | "CHAIN_HISTORY_INCOMPLETE" | "CHAIN_HISTORY_BUDGET" | "CHAIN_LOGS_TRUNCATED" | "CHAIN_ACCOUNT_INVALID" | "CHAIN_RPC_FAILED" | "CHAIN_TRANSACTION_VERSION" | "INVALID_INPUT";
|
|
2632
|
+
type ChainAccountInvalidReason = "owner" | "discriminator" | "version" | "layout" | "pda";
|
|
2633
|
+
/**
|
|
2634
|
+
* A chain read that gave no reading. `reason` names the failed account check on
|
|
2635
|
+
* `CHAIN_ACCOUNT_INVALID`. A `CHAIN_RPC_FAILED` message is fixed text naming the RPC method, a
|
|
2636
|
+
* `CHAIN_TRANSACTION_VERSION` one the transaction and the address; the transport's own error, which
|
|
2637
|
+
* may echo the RPC URL, is only the `cause`.
|
|
2638
|
+
*/
|
|
2639
|
+
declare class ChainReadError extends EscroError {
|
|
2640
|
+
readonly reason: ChainAccountInvalidReason | undefined;
|
|
2641
|
+
constructor(code: ChainReadErrorCode, message: string, options?: {
|
|
2642
|
+
reason?: ChainAccountInvalidReason;
|
|
2643
|
+
cause?: unknown;
|
|
2644
|
+
});
|
|
2645
|
+
}
|
|
2646
|
+
declare const ARCHIVAL_RPC_NOTE = "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.";
|
|
2647
|
+
/** getTransaction calls per read: one lifecycle takes at most five, so about ten reuses or spam. */
|
|
2648
|
+
declare const CHAIN_READ_MAX_TRANSACTIONS = 50;
|
|
2649
|
+
/** getSignaturesForAddress pages per read, of {@link SIGNATURE_PAGE} signatures each. */
|
|
2650
|
+
declare const CHAIN_READ_MAX_SIGNATURE_PAGES = 5;
|
|
2651
|
+
declare const ESCROW_ACCOUNT_DISCRIMINATOR: readonly number[];
|
|
2652
|
+
type FieldKind = "pubkey" | "u8" | "u16" | "u64" | "i64" | "string" | "option<pubkey>" | "option<string>" | "option<i64>" | "enum";
|
|
2653
|
+
/** The EscrowAccount fields in on-chain order (escrow_account.rs, the committed IDL). */
|
|
2654
|
+
declare const ESCROW_ACCOUNT_LAYOUT: readonly {
|
|
2655
|
+
name: string;
|
|
2656
|
+
kind: FieldKind;
|
|
2657
|
+
}[];
|
|
2658
|
+
/** The program's allocation: 8 + EscrowAccount::INIT_SPACE. The tail past the content is zero. */
|
|
2659
|
+
declare const ESCROW_ACCOUNT_SIZE = 537;
|
|
2660
|
+
/**
|
|
2661
|
+
* Decode EscrowAccount bytes as the program allocates them. Throws {@link ChainReadError}
|
|
2662
|
+
* `CHAIN_ACCOUNT_INVALID` (reason `discriminator`, `version` or `layout`) on anything else.
|
|
2663
|
+
* `state` is the IDL variant name (`Funded`, `InProgress`, ...).
|
|
2664
|
+
*/
|
|
2665
|
+
declare function decodeEscrowAccount(data: Uint8Array): DecodedEscrowAccount;
|
|
2666
|
+
/**
|
|
2667
|
+
* A connection at `rpcUrl` and `confirmed` through which a history holding version-1 transactions
|
|
2668
|
+
* reads, a custom transport (headers, a proxy, a test double) going in as `fetchFn` (default
|
|
2669
|
+
* `globalThis.fetch`, resolved when called); a connection built any other way fails a version-1
|
|
2670
|
+
* history with `CHAIN_RPC_FAILED`, whose archival advice does not apply to that failure.
|
|
2671
|
+
*/
|
|
2672
|
+
declare function chainReadConnection(rpcUrl: string, fetchFn?: typeof globalThis.fetch): Connection;
|
|
2673
|
+
/**
|
|
2674
|
+
* What the program recorded for one escrow, read from `options.rpc` alone. An open escrow reads
|
|
2675
|
+
* from its account and makes no history call; a closed one is rebuilt from the program's events
|
|
2676
|
+
* in the address's history, its newest lifecycle only. Throws {@link ChainReadError}.
|
|
2677
|
+
*/
|
|
2678
|
+
declare function readEscrowFromChain(target: ChainReadTarget, options: ReadEscrowFromChainOptions): Promise<ChainEscrowReading>;
|
|
2679
|
+
|
|
2680
|
+
/** The SPL Memo program (the current one; the legacy `Memo1Uhk...` program is not admitted). */
|
|
2681
|
+
declare const MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
|
|
2682
|
+
|
|
2683
|
+
/** Why {@link payUrlRefusal} refuses a URL; each surface turns a kind into its own sentence. */
|
|
2684
|
+
type PayUrlRefusal = "private_host" | "unresolved_host" | "mainnet_http";
|
|
2685
|
+
/** node:dns/promises' lookup satisfies it; the SDK resolves nothing itself. */
|
|
2686
|
+
type HostLookup = (hostname: string, options: {
|
|
2687
|
+
all: true;
|
|
2688
|
+
}) => Promise<readonly {
|
|
2689
|
+
address: string;
|
|
2690
|
+
}[]>;
|
|
2691
|
+
/**
|
|
2692
|
+
* True only for text that parses as an IPv4 or IPv6 address (no brackets, no zone id) outside the
|
|
2693
|
+
* refused set, so an unknown form (a name, a zone id, a non-strict quad) is never public.
|
|
2694
|
+
*/
|
|
2695
|
+
declare function isPublicAddress(address: string): boolean;
|
|
2696
|
+
/**
|
|
2697
|
+
* Whether a pay action may reach `url`, before any request, signature or funding: on any cluster
|
|
2698
|
+
* but devnet an `http:` URL to a host the operator has not admitted as private is refused, and
|
|
2699
|
+
* without the opt-in any host that is not public is refused. Null admits, and leaves a URL that does
|
|
2700
|
+
* not parse, or is not http or https, to pay()'s own refusal. Resolves the host at most once, and
|
|
2701
|
+
* only when the answer decides.
|
|
2702
|
+
*/
|
|
2703
|
+
declare function payUrlRefusal(url: string, options: {
|
|
2704
|
+
cluster: EscroOptions["cluster"] | undefined;
|
|
2705
|
+
allowPrivateHosts: boolean;
|
|
2706
|
+
lookup: HostLookup;
|
|
2707
|
+
}): Promise<PayUrlRefusal | null>;
|
|
2708
|
+
/**
|
|
2709
|
+
* The address rule a surface passes as PayParams.admitAddress, for the URL it checked with
|
|
2710
|
+
* {@link payUrlRefusal}. Without the opt-in both targets admit exactly the public addresses. With it,
|
|
2711
|
+
* on any cluster but devnet over http:, the resource admits exactly the addresses that are not
|
|
2712
|
+
* public (a host the operator declared local has no public network path) and the spec host, always
|
|
2713
|
+
* https:, admits every address. With the opt-in otherwise there is no rule (undefined). A URL that
|
|
2714
|
+
* does not parse, or is not http or https, takes the rule without the opt-in.
|
|
2715
|
+
*/
|
|
2716
|
+
declare function payAddressRule(options: {
|
|
2717
|
+
cluster: EscroOptions["cluster"] | undefined;
|
|
2718
|
+
allowPrivateHosts: boolean;
|
|
2719
|
+
url: string;
|
|
2720
|
+
}): PayParams["admitAddress"];
|
|
2721
|
+
/**
|
|
2722
|
+
* pay()'s own rail choice with a deadline bound added: an escrow entry on the caller's terms is
|
|
2723
|
+
* returned only when its deadline is at most now plus `maxDeadlineSeconds`, and is never passed over
|
|
2724
|
+
* for an `exact` entry; an `exact` entry is returned only when no escrow entry is on the terms, and
|
|
2725
|
+
* never with `escrowOnly`. Only entries on the cluster's network are on the terms: devnet's for
|
|
2726
|
+
* `"devnet"`, mainnet's for any other value, as {@link payUrlRefusal} reads a cluster. Refusals carry
|
|
2727
|
+
* the caller's values only, never the 402's text. The clock (`now`, milliseconds, default
|
|
2728
|
+
* `Date.now`) is read each time the policy runs, which pay() does before its first chain read, spec
|
|
2729
|
+
* fetch or signature.
|
|
2730
|
+
*/
|
|
2731
|
+
declare function deadlineBoundedPolicy(terms: {
|
|
2732
|
+
to: string;
|
|
2733
|
+
amountMicroUsdc: number;
|
|
2734
|
+
cluster: EscroOptions["cluster"] | undefined;
|
|
2735
|
+
maxDeadlineSeconds: number;
|
|
2736
|
+
escrowOnly?: boolean;
|
|
2737
|
+
now?: () => number;
|
|
2738
|
+
}): PayPolicy;
|
|
2739
|
+
|
|
2740
|
+
/** An http: or https: URL whose port (the scheme's default when the URL names none) `fetch` blocks. */
|
|
2741
|
+
declare function isBadPortUrl(url: URL): boolean;
|
|
2742
|
+
|
|
2743
|
+
/** The three x402 V2 HTTP header names. */
|
|
2744
|
+
declare const X402_HEADERS: {
|
|
2745
|
+
readonly paymentRequired: "PAYMENT-REQUIRED";
|
|
2746
|
+
readonly paymentSignature: "PAYMENT-SIGNATURE";
|
|
2747
|
+
readonly paymentResponse: "PAYMENT-RESPONSE";
|
|
2748
|
+
};
|
|
2749
|
+
/** A 402's `PAYMENT-REQUIRED` header value. */
|
|
2750
|
+
declare function encodePaymentRequired(value: PaymentRequired): string;
|
|
2751
|
+
/**
|
|
2752
|
+
* A `PAYMENT-REQUIRED` header's value, checked for version 2, `resource.url` and each entry's
|
|
2753
|
+
* `scheme` and `network`; throws {@link X402CodecError} otherwise.
|
|
2754
|
+
*/
|
|
2755
|
+
declare function decodePaymentRequired(header: string): PaymentRequired;
|
|
2756
|
+
/** A payment's `PAYMENT-SIGNATURE` header value. */
|
|
2757
|
+
declare function encodePaymentSignature(value: PaymentPayload): string;
|
|
2758
|
+
/**
|
|
2759
|
+
* A `PAYMENT-SIGNATURE` header's value, checked for version 2 and the `accepted` and `payload`
|
|
2760
|
+
* objects; throws {@link X402CodecError} otherwise.
|
|
2761
|
+
*/
|
|
2762
|
+
declare function decodePaymentSignature(header: string): PaymentPayload;
|
|
2763
|
+
/** A settlement's `PAYMENT-RESPONSE` header value. */
|
|
2764
|
+
declare function encodePaymentResponse(value: SettlementResponse): string;
|
|
2765
|
+
/**
|
|
2766
|
+
* A `PAYMENT-RESPONSE` header's value, checked for a boolean `success`; throws
|
|
2767
|
+
* {@link X402CodecError} otherwise.
|
|
2768
|
+
*/
|
|
2769
|
+
declare function decodePaymentResponse(header: string): SettlementResponse;
|
|
2770
|
+
|
|
2771
|
+
/** A `PAYMENT-REQUIRED`, `PAYMENT-SIGNATURE` or `PAYMENT-RESPONSE` header that is not the x402 V2 encoding. */
|
|
2772
|
+
declare class X402CodecError extends EscroError {
|
|
2773
|
+
constructor(message: string, options?: {
|
|
2774
|
+
cause?: unknown;
|
|
2775
|
+
});
|
|
2776
|
+
}
|
|
2777
|
+
/** No PlatformConfig account at the cluster's PlatformConfig PDA. */
|
|
2778
|
+
declare class PlatformConfigNotFoundError extends EscroError {
|
|
2779
|
+
constructor(address: string);
|
|
2780
|
+
}
|
|
2781
|
+
/** Why an `on-delivery` entry was not selected (docs/specs/scheme_on_delivery_svm.md, client checks). */
|
|
2782
|
+
type OnDeliveryAcceptRefusal = "no_entry" | "network" | "program" | "asset" | "fee_bps" | "settlement_mode" | "review_window" | "fee_payer" | "payment_flow" | "amount" | "over_limit" | "pay_to" | "spec_hash" | "spec_uri" | "deadline" | "max_timeout" | "extra_shape" | "extension_invalid" | "extension_terms" | "acceptance";
|
|
2783
|
+
/**
|
|
2784
|
+
* No acceptable `on-delivery` entry. `refusals` lists each candidate's first refusal; `index` is the
|
|
2785
|
+
* entry's index in `accepts`, or -1 where no entry is concerned (`no_entry`, an `escro` extension
|
|
2786
|
+
* parsed alone, an entry `buildEscrowAccept` refused to build).
|
|
2787
|
+
*/
|
|
2788
|
+
declare class OnDeliveryAcceptError extends EscroError {
|
|
2789
|
+
readonly refusals: readonly {
|
|
2790
|
+
index: number;
|
|
2791
|
+
reason: OnDeliveryAcceptRefusal;
|
|
2792
|
+
}[];
|
|
2793
|
+
constructor(refusals: readonly {
|
|
2794
|
+
index: number;
|
|
2795
|
+
reason: OnDeliveryAcceptRefusal;
|
|
2796
|
+
}[]);
|
|
2797
|
+
}
|
|
2798
|
+
type OnDeliveryFundRefusal = "selection_unknown" | "selection_spent" | "resource_url" | "resource_mismatch" | "spec_fetch" | "spec_host" | "spec_hash_mismatch" | "spec_refused" | "escrow_mismatch";
|
|
2799
|
+
/** `fundFromAccept` or `fetchTaskSpec` refused; `reason` names the check. */
|
|
2800
|
+
declare class OnDeliveryFundError extends EscroError {
|
|
2801
|
+
readonly reason: OnDeliveryFundRefusal;
|
|
2802
|
+
/** Set on `escrow_mismatch` only: the create landed; recover with `Escro.cancelEscrow(escrowPda)`. */
|
|
2803
|
+
readonly escrowId?: string;
|
|
2804
|
+
readonly escrowPda?: string;
|
|
2805
|
+
readonly signature?: string;
|
|
2806
|
+
constructor(reason: OnDeliveryFundRefusal, message: string, options?: {
|
|
2807
|
+
cause?: unknown;
|
|
2808
|
+
escrowId?: string;
|
|
2809
|
+
escrowPda?: string;
|
|
2810
|
+
signature?: string;
|
|
2811
|
+
});
|
|
2812
|
+
}
|
|
2813
|
+
/** The facilitator operation an {@link EscroFacilitatorError} failed in. */
|
|
2814
|
+
type FacilitatorOperation = "verify" | "settle" | "supported";
|
|
2815
|
+
/**
|
|
2816
|
+
* A facilitator call that failed with no answer: unreachable, timed out, an unrecognised error, or its client not
|
|
2817
|
+
* loadable. `indeterminate` is set on every `settle` failure: the facilitator may still have sent the transfer. The
|
|
2818
|
+
* message holds no part of the facilitator URL, and the error carries no `cause`.
|
|
2819
|
+
*/
|
|
2820
|
+
declare class EscroFacilitatorError extends EscroError {
|
|
2821
|
+
readonly operation: FacilitatorOperation;
|
|
2822
|
+
readonly indeterminate: boolean;
|
|
2823
|
+
constructor(operation: FacilitatorOperation, message: string);
|
|
2824
|
+
}
|
|
2825
|
+
/** Why {@link buildExactAccept} refused to build an `exact` entry. */
|
|
2826
|
+
type ExactAcceptRefusal = "pay_to" | "fee_payer" | "amount" | "max_timeout";
|
|
2827
|
+
/** The worker's `exact` entry would be one a buyer cannot pay or a facilitator cannot settle in time. */
|
|
2828
|
+
declare class ExactAcceptError extends EscroError {
|
|
2829
|
+
readonly reason: ExactAcceptRefusal;
|
|
2830
|
+
constructor(reason: ExactAcceptRefusal, message: string);
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
interface BuildBazaarDeclarationOptions {
|
|
2834
|
+
method: "GET" | "POST";
|
|
2835
|
+
/** The example request: the JSON body of a POST, the query parameters of a GET. */
|
|
2836
|
+
example: Record<string, unknown>;
|
|
2837
|
+
/** The example response. */
|
|
2838
|
+
output?: {
|
|
2839
|
+
type: string;
|
|
2840
|
+
example?: unknown;
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* The `bazaar` declaration of an HTTP route: a POST takes `example` as its JSON body, a GET as its query parameters;
|
|
2845
|
+
* the schema requires `input.type` "http" and a method of the route's family. Throws an Error naming `example` when it
|
|
2846
|
+
* is not a plain object that survives a JSON round trip, and naming `output.type` when that is empty. The declaration
|
|
2847
|
+
* is a copy: a later change to `example` or `output` does not reach it.
|
|
2848
|
+
*/
|
|
2849
|
+
declare function buildBazaarDeclaration(options: BuildBazaarDeclarationOptions): BazaarDeclaration;
|
|
2850
|
+
|
|
2851
|
+
interface BuildExactAcceptOptions {
|
|
2852
|
+
cluster: SolanaCluster;
|
|
2853
|
+
amountMicroUsdc: bigint;
|
|
2854
|
+
/** The worker's own wallet. */
|
|
2855
|
+
payTo: string;
|
|
2856
|
+
/** The facilitator's fee payer, from its `/supported` answer ({@link exactFeePayer}). */
|
|
2857
|
+
feePayer: string;
|
|
2858
|
+
maxTimeoutSeconds: number;
|
|
2859
|
+
}
|
|
2860
|
+
/**
|
|
2861
|
+
* The `exact` entry a worker offers beside its `on-delivery` entry. Throws {@link ExactAcceptError} for a `payTo` or
|
|
2862
|
+
* `feePayer` that is not a canonical key, a fee payer that is the worker itself, an amount outside 1..2^64-1, or a
|
|
2863
|
+
* `maxTimeoutSeconds` that is not a whole number from 10 to 3600.
|
|
2864
|
+
*/
|
|
2865
|
+
declare function buildExactAccept(options: BuildExactAcceptOptions): PaymentRequirements;
|
|
2866
|
+
/**
|
|
2867
|
+
* The `extra.feePayer` of the first x402 V2 `exact` kind on the cluster's network in a facilitator's `/supported`
|
|
2868
|
+
* answer; undefined when none names one. Its validity is {@link buildExactAccept}'s to check.
|
|
2869
|
+
*/
|
|
2870
|
+
declare function exactFeePayer(supported: SupportedResponse, cluster: SolanaCluster): string | undefined;
|
|
2871
|
+
|
|
2872
|
+
interface HttpFacilitatorOptions {
|
|
2873
|
+
/** `https:`, with no userinfo, query or fragment; a path is allowed. */
|
|
2874
|
+
url: string;
|
|
2875
|
+
/** Per request. Default 30 000. */
|
|
2876
|
+
timeoutMs?: number;
|
|
2877
|
+
}
|
|
2878
|
+
/**
|
|
2879
|
+
* A facilitator at `url`. Synchronous and offline: the client is loaded and built on the first call, once per
|
|
2880
|
+
* facilitator. Throws a TypeError, naming the rule and never the URL, for a URL that is not `https:` or carries a
|
|
2881
|
+
* username, password, query or fragment.
|
|
2882
|
+
*/
|
|
2883
|
+
declare function createHttpFacilitator(options: HttpFacilitatorOptions): Facilitator;
|
|
2884
|
+
|
|
2885
|
+
type PlatformConfigTerms = Pick<PlatformConfigAccount, "usdcMint" | "feeBps">;
|
|
2886
|
+
/**
|
|
2887
|
+
* The cluster's PlatformConfig, read at its PDA and decoded by the shared decoder. Throws
|
|
2888
|
+
* {@link PlatformConfigNotFoundError} when no account is there, and {@link ChainReadError}
|
|
2889
|
+
* `CHAIN_ACCOUNT_INVALID` (reason `version`) on a version this SDK does not read.
|
|
2890
|
+
*/
|
|
2891
|
+
declare function readPlatformConfig(rpc: Pick<Connection, "getAccountInfo">, cluster: SolanaCluster): Promise<PlatformConfigTerms & {
|
|
2892
|
+
treasury: string;
|
|
2893
|
+
}>;
|
|
2894
|
+
/**
|
|
2895
|
+
* The settlement modes this client funds. The version-1 account layout has no refund on silence
|
|
2896
|
+
* (the binding: `refund` is offered from a future account layout), so `release` only.
|
|
2897
|
+
*/
|
|
2898
|
+
declare const SUPPORTED_SETTLEMENT_MODES: readonly SettlementMode[];
|
|
2899
|
+
/** Whether the entry's `extra.settlementMode` is one of {@link SUPPORTED_SETTLEMENT_MODES}. */
|
|
2900
|
+
declare function settlementModeSupported(entry: {
|
|
2901
|
+
extra: {
|
|
2902
|
+
settlementMode: unknown;
|
|
2903
|
+
};
|
|
2904
|
+
}): boolean;
|
|
2905
|
+
interface ParseEscrowAcceptContext {
|
|
2906
|
+
cluster: SolanaCluster;
|
|
2907
|
+
/** From {@link readPlatformConfig}: the entry's mint and fee must equal these. */
|
|
2908
|
+
platformConfig: PlatformConfigTerms;
|
|
2909
|
+
/** The buyer's own bound on what it deposits: `amount` plus the fee at `platformConfig.feeBps`. */
|
|
2910
|
+
maxDepositMicroUsdc: bigint;
|
|
2911
|
+
/** When given, the only worker the buyer funds. */
|
|
2912
|
+
payTo?: string;
|
|
2913
|
+
/** Decides an `acceptance` predicate the 402 carries; absent, such an entry is refused. */
|
|
2914
|
+
admitAcceptance?: (acceptance: Acceptance) => boolean;
|
|
2915
|
+
/** Unix milliseconds. */
|
|
2916
|
+
now?: () => number;
|
|
2917
|
+
}
|
|
2918
|
+
interface EscrowAcceptSelection {
|
|
2919
|
+
readonly cluster: SolanaCluster;
|
|
2920
|
+
readonly resource: ResourceInfo;
|
|
2921
|
+
readonly entry: OnDeliveryAccept;
|
|
2922
|
+
readonly extension: EscroExtensionInfo | undefined;
|
|
2923
|
+
readonly extensions: Record<string, unknown> | undefined;
|
|
2924
|
+
}
|
|
2925
|
+
/**
|
|
2926
|
+
* The first `on-delivery` (or `job-escrow`) entry of the 402 that passes every client check of the
|
|
2927
|
+
* binding, against the cluster's pinned values, `ctx.platformConfig` and the buyer's own deposit
|
|
2928
|
+
* bound; entries of other schemes are ignored. The selection holds a deep-frozen copy of the 402's
|
|
2929
|
+
* resource, entry and extensions taken before the checks, and is the only input
|
|
2930
|
+
* {@link fundFromAccept} funds, once. Throws {@link OnDeliveryAcceptError} listing each candidate's
|
|
2931
|
+
* first refusal when none passes, and {@link EscroError} `VALIDATION_ERROR` when
|
|
2932
|
+
* `ctx.maxDepositMicroUsdc` is not a bigint or the 402 is not plain data.
|
|
2933
|
+
*/
|
|
2934
|
+
declare function parseEscrowAccept(required: PaymentRequired, ctx: ParseEscrowAcceptContext): EscrowAcceptSelection;
|
|
2935
|
+
interface BuildEscrowAcceptOptions {
|
|
2936
|
+
cluster: SolanaCluster;
|
|
2937
|
+
amountMicroUsdc: bigint;
|
|
2938
|
+
payTo: string;
|
|
2939
|
+
specHash: string;
|
|
2940
|
+
specUri: string;
|
|
2941
|
+
/** Unix seconds. */
|
|
2942
|
+
deadline: number;
|
|
2943
|
+
/** PlatformConfig's `fee_bps`, read by {@link readPlatformConfig}. */
|
|
2944
|
+
feeBps: number;
|
|
2945
|
+
maxTimeoutSeconds: number;
|
|
2946
|
+
/** Default `upfront`. */
|
|
2947
|
+
paymentFlow?: "upfront" | "escrow";
|
|
2948
|
+
}
|
|
2949
|
+
/**
|
|
2950
|
+
* The `on-delivery` entry a worker advertises: network, asset, program, review window, settlement
|
|
2951
|
+
* mode and fee payer from the cluster's pinned values, the fee from `options.feeBps`. Throws
|
|
2952
|
+
* {@link OnDeliveryAcceptError} for an entry the client side would refuse on its own terms (an
|
|
2953
|
+
* amount under the minimum escrow, a malformed key, hash, URI or bound).
|
|
2954
|
+
*/
|
|
2955
|
+
declare function buildEscrowAccept(options: BuildEscrowAcceptOptions): OnDeliveryAccept;
|
|
2956
|
+
|
|
2957
|
+
/**
|
|
2958
|
+
* The `escro` extension's `info`, validated by the rules this client holds (closed objects; `args`
|
|
2959
|
+
* free-form). Throws {@link OnDeliveryAcceptError} with reason `extension_invalid` otherwise.
|
|
2960
|
+
*/
|
|
2961
|
+
declare function parseEscroExtension(info: unknown): EscroExtensionInfo;
|
|
2962
|
+
|
|
2963
|
+
/** The buyer message's method place: a value no API route accepts. */
|
|
2964
|
+
declare const BUYER_MESSAGE_METHOD: "ON-DELIVERY";
|
|
2965
|
+
/**
|
|
2966
|
+
* `escro:<signedAt>:ON-DELIVERY:<resourceUrl>:<escrow>`: the API's request message shape with a
|
|
2967
|
+
* method no API route accepts and an absolute URL in the path place, so it never verifies as an API
|
|
2968
|
+
* request signature. Throws on a `resourceUrl` that is not an absolute http(s) URL, an `escrow` that
|
|
2969
|
+
* is not a canonical base58 key, or a `signedAt` that is not a non-negative safe integer.
|
|
2970
|
+
*/
|
|
2971
|
+
declare function buyerMessage(signedAt: number, resourceUrl: string, escrow: string): string;
|
|
2972
|
+
/**
|
|
2973
|
+
* The payload fields signed by `wallet` over the buyer message for `resourceUrl`, `signedAt` being
|
|
2974
|
+
* `now()`. A poll re-signs with the poll URL and a fresh `now()`.
|
|
2975
|
+
*/
|
|
2976
|
+
declare function signEscrowPayload(fields: Pick<OnDeliveryPayloadFields, "escrow" | "buyer" | "taskId" | "createSignature">, options: {
|
|
2977
|
+
wallet: Keypair;
|
|
2978
|
+
resourceUrl: string;
|
|
2979
|
+
now?: () => number;
|
|
2980
|
+
}): OnDeliveryPayloadFields;
|
|
2981
|
+
|
|
2982
|
+
/**
|
|
2983
|
+
* The job specification at an `https:` `specUri`, fetched with no SDK header (only `Accept`), no
|
|
2984
|
+
* redirect, a total deadline of `timeoutMs` (default 10 000) and at most 256 KiB of body. Throws
|
|
2985
|
+
* {@link OnDeliveryFundError} `spec_fetch` on any other URI, a network failure, a non-2xx status,
|
|
2986
|
+
* an oversized, non-UTF-8 or non-JSON body, or a document that is not a JSON object; a URI carrying a
|
|
2987
|
+
* username or password, or naming a port `fetch` blocks, is refused before any lookup or connection. With
|
|
2988
|
+
* `admitAddress`, the host is resolved once within the deadline, every answer is put to it, and the
|
|
2989
|
+
* request connects only to the answers it admitted (exactly `true`); a refused answer throws
|
|
2990
|
+
* `spec_host`, an unresolved host `spec_fetch`.
|
|
2991
|
+
*/
|
|
2992
|
+
declare function fetchTaskSpec(specUri: string, options?: {
|
|
2993
|
+
timeoutMs?: number;
|
|
2994
|
+
admitAddress?: (address: string) => boolean;
|
|
2995
|
+
}): Promise<Record<string, unknown>>;
|
|
2996
|
+
interface FundFromAcceptDeps {
|
|
2997
|
+
escro: Pick<Escro, "createEscrow">;
|
|
2998
|
+
wallet: Keypair;
|
|
2999
|
+
/** The absolute URL the paid request goes to: the 402's `resource.url`. */
|
|
3000
|
+
resourceUrl: string;
|
|
3001
|
+
/** Fetches `extra.specUri`; the only way to read an `ipfs:` URI. Default {@link fetchTaskSpec}. */
|
|
3002
|
+
fetchSpec?: (specUri: string) => Promise<unknown>;
|
|
3003
|
+
/**
|
|
3004
|
+
* Decides each address the default spec fetch may connect to (see {@link fetchTaskSpec}); a caller's
|
|
3005
|
+
* `fetchSpec` is its own transport and does not read it.
|
|
3006
|
+
*/
|
|
3007
|
+
admitAddress?: (address: string) => boolean;
|
|
3008
|
+
/** The buyer's veto over the hash-checked specification, before `createEscrow`; absent admits. */
|
|
3009
|
+
admitSpec?: (spec: TaskSpec) => boolean;
|
|
3010
|
+
/** Unix milliseconds. */
|
|
3011
|
+
now?: () => number;
|
|
3012
|
+
}
|
|
3013
|
+
interface FundFromAcceptResult {
|
|
3014
|
+
payment: OnDeliveryPaymentPayload;
|
|
3015
|
+
taskSpec: TaskSpec;
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* Funds a selection {@link parseEscrowAccept} returned, once: fetches the job specification, checks
|
|
3019
|
+
* its hash before it is used or sent, creates the escrow through `deps.escro.createEscrow` with
|
|
3020
|
+
* `payTo` as the assigned worker, and returns the `PAYMENT-SIGNATURE` payload signed by
|
|
3021
|
+
* `deps.wallet` over `deps.resourceUrl`, with the hash-checked specification.
|
|
3022
|
+
*
|
|
3023
|
+
* A selection is known only to the copy of the SDK that parsed it. An `escro` built with another
|
|
3024
|
+
* wallet, or for another cluster, is caught after the create lands, as `escrow_mismatch`; that
|
|
3025
|
+
* error carries `escrowId`, `escrowPda` and `signature`, and `cancelEscrow` is the recovery. An
|
|
3026
|
+
* error from `createEscrow` propagates unchanged.
|
|
3027
|
+
*/
|
|
3028
|
+
declare function fundFromAccept(selection: EscrowAcceptSelection, deps: FundFromAcceptDeps): Promise<FundFromAcceptResult>;
|
|
3029
|
+
|
|
3030
|
+
/**
|
|
3031
|
+
* The record of accepted presentations a server keeps; one per server, never module state.
|
|
3032
|
+
*/
|
|
3033
|
+
interface ReplayStore {
|
|
3034
|
+
/**
|
|
3035
|
+
* Records `key` until `expiresAtMs` (inclusive) and returns true; returns false when `key` is held and unexpired at
|
|
3036
|
+
* `nowMs`. Atomic per key (a shared store: Redis `SET NX PX`, Postgres `INSERT ... ON CONFLICT DO NOTHING`). A claim
|
|
3037
|
+
* is spent before the account read: a presentation that fails a later step is re-signed.
|
|
3038
|
+
*/
|
|
3039
|
+
claim(key: string, expiresAtMs: number, nowMs: number): boolean | Promise<boolean>;
|
|
3040
|
+
}
|
|
3041
|
+
/**
|
|
3042
|
+
* An in-memory {@link ReplayStore}: one map per call, held by this process only, so it suits a
|
|
3043
|
+
* single-process server; servers behind a load balancer share a store. Each claim drops the keys
|
|
3044
|
+
* expired at its `nowMs`. `size` is the number of keys held.
|
|
3045
|
+
*/
|
|
3046
|
+
declare function memoryReplayStore(): ReplayStore & {
|
|
3047
|
+
readonly size: number;
|
|
3048
|
+
};
|
|
3049
|
+
/** The binding's error-code table, in its order. */
|
|
3050
|
+
declare const ON_DELIVERY_SVM_INVALID_REASONS: readonly ["invalid_on_delivery_svm_payload", "invalid_on_delivery_svm_escrow_address_mismatch", "invalid_on_delivery_svm_buyer_signature", "invalid_on_delivery_svm_signature_expired", "invalid_on_delivery_svm_escrow_not_found", "invalid_on_delivery_svm_escrow_owner", "invalid_on_delivery_svm_escrow_version", "invalid_on_delivery_svm_wrong_state", "invalid_on_delivery_svm_buyer_mismatch", "invalid_on_delivery_svm_worker_mismatch", "invalid_on_delivery_svm_amount_mismatch", "invalid_on_delivery_svm_spec_hash_mismatch", "invalid_on_delivery_svm_deadline", "invalid_on_delivery_svm_claim_failed"];
|
|
3051
|
+
type OnDeliveryInvalidReason = (typeof ON_DELIVERY_SVM_INVALID_REASONS)[number] | "invalid_x402_version" | "invalid_scheme" | "invalid_network" | "invalid_payment_requirements";
|
|
3052
|
+
interface VerifyPresentationContext {
|
|
3053
|
+
/** The absolute URL this server is serving: the paid route, or the poll URL for a poll. */
|
|
3054
|
+
resourceUrl: string;
|
|
3055
|
+
replay: ReplayStore;
|
|
3056
|
+
/** Unix milliseconds. */
|
|
3057
|
+
now?: () => number;
|
|
3058
|
+
}
|
|
3059
|
+
interface VerifyEscrowContext extends VerifyPresentationContext {
|
|
3060
|
+
rpc: Pick<Connection, "getAccountInfo">;
|
|
3061
|
+
}
|
|
3062
|
+
type BuyerPresentationResult = {
|
|
3063
|
+
isValid: true;
|
|
3064
|
+
payer: string;
|
|
3065
|
+
} | {
|
|
3066
|
+
isValid: false;
|
|
3067
|
+
invalidReason: OnDeliveryInvalidReason;
|
|
3068
|
+
};
|
|
3069
|
+
/** `payer` is set on an invalid verdict exactly when the buyer's signature verified. */
|
|
3070
|
+
type OnDeliveryVerifyResult = {
|
|
3071
|
+
isValid: true;
|
|
3072
|
+
payer: string;
|
|
3073
|
+
job: "new" | "retry";
|
|
3074
|
+
escrow: DecodedEscrowAccount;
|
|
3075
|
+
} | {
|
|
3076
|
+
isValid: false;
|
|
3077
|
+
invalidReason: OnDeliveryInvalidReason;
|
|
3078
|
+
payer?: string;
|
|
3079
|
+
};
|
|
3080
|
+
/**
|
|
3081
|
+
* Binding server steps 1 to 3, with no RPC call: what a poll runs, `ctx.resourceUrl` being the poll
|
|
3082
|
+
* URL. Throws {@link EscroError} `VALIDATION_ERROR` before any work when `ctx.replay` is missing or
|
|
3083
|
+
* `ctx.resourceUrl` is not an absolute http: or https: URL.
|
|
3084
|
+
*/
|
|
3085
|
+
declare function verifyBuyerPresentation(payment: PaymentPayload, entry: OnDeliveryAccept, ctx: VerifyPresentationContext): Promise<BuyerPresentationResult>;
|
|
3086
|
+
/**
|
|
3087
|
+
* Binding server steps 1 to 6 against the server's own `entry`: the payload, the escrow PDA, the
|
|
3088
|
+
* buyer's signature within 30 s, claimed once in `ctx.replay`, then the escrow account read at
|
|
3089
|
+
* `confirmed`. A Funded escrow is a new job; InProgress or Submitted a retry. Throws
|
|
3090
|
+
* {@link ChainReadError} `CHAIN_RPC_FAILED` when the RPC fails, and {@link EscroError}
|
|
3091
|
+
* `VALIDATION_ERROR` before any work when `ctx.replay` is missing or `ctx.resourceUrl` is not an
|
|
3092
|
+
* absolute http: or https: URL.
|
|
3093
|
+
*/
|
|
3094
|
+
declare function verifyEscrowPayload(payment: PaymentPayload, entry: OnDeliveryAccept, ctx: VerifyEscrowContext): Promise<OnDeliveryVerifyResult>;
|
|
3095
|
+
|
|
3096
|
+
export { AKASH_ADAPTER_ID, AKASH_CAPABILITIES, AKASH_DEMO_ACCEPT_FLOOR, AKASH_DEMO_MARKER, ARCHIVAL_RPC_NOTE, AdapterContractError, ApiClient, BUYER_MESSAGE_METHOD, CHAIN_READ_MAX_SIGNATURE_PAGES, CHAIN_READ_MAX_TRANSACTIONS, ChainReadError, ENABLED_RAILS, ESCROW_ACCOUNT_DISCRIMINATOR, ESCROW_ACCOUNT_LAYOUT, ESCROW_ACCOUNT_SIZE, Escro, EscroConfirmError, EscroError, EscroFacilitatorError, EscroPayError, EscroRailNotEnabledError, EscrowNotFoundError, EscrowPaymentRouter, EscrowState, EscrowStateError, EscrowTimeoutError, ExactAcceptError, GEN404_ADAPTER_ID, GEN404_CAPABILITIES, GEN404_DEMO_EVAL_FLOOR, GEN404_DEMO_MARKER, GENSYN_ADAPTER_ID, GENSYN_CAPABILITIES, GENSYN_DEMO_MARKER, GENSYN_REE_SCHEME, GRADIENTS_ADAPTER_ID, GRADIENTS_CAPABILITIES, GRADIENTS_DEMO_EVAL_FLOOR, GRADIENTS_DEMO_MARKER, LIUM_ADAPTER_ID, LIUM_CAPABILITIES, LIUM_DEMO_ACCEPT_FLOOR, LIUM_DEMO_MARKER, MAX_PROOF_URI_BYTES, MEMO_PROGRAM_ID, MIN_ESCROW_AMOUNT, ONCHAIN_REFUND_GRACE_SECONDS, ON_DELIVERY_SVM_INVALID_REASONS, OnDeliveryAcceptError, OnDeliveryFundError, PAY_MAX_DEADLINE_SECONDS, PREDICATES, PlatformConfigNotFoundError, PredicateEvaluationError, PredicateParamsError, PredicateRecordError, RAILS, RAILS_DOCS_URL, REFERENCE_MICRO_USDC_PER_AKT, REFERENCE_MICRO_USDC_PER_RENDER, RENDER_ADAPTER_ID, RENDER_CAPABILITIES, RENDER_DEMO_ACCEPT_FLOOR, RENDER_DEMO_MARKER, RIDGES_ADAPTER_ID, RIDGES_CAPABILITIES, RIDGES_DEMO_COVERAGE_TARGET, RIDGES_DEMO_MARKER, ReputationUnavailableError, SPEND_CAP_ERROR_CODES, SUPPORTED_SETTLEMENT_MODES, UnauthorizedError, X402CodecError, X402_HEADERS, ZKML_ADAPTER_ID, ZKML_CAPABILITIES, ZKML_DEMO_MARKER, ZKML_DEMO_MODEL_COMMITMENT, ZKML_PROOF_SCHEME, ZKML_PROOF_URI_PREFIX, akashDemoJobSpec, akt, assertServiceAdapterContract, assertWithinSpendCap, attestationValid, buildBazaarDeclaration, buildEscrowAccept, buildExactAccept, buildReeProof, buildZkmlProof, buyerMessage, chainReadConnection, ciCheck, computeAkashDemoArtifact, computeLiumDemoArtifact, computeRenderDemoArtifact, computeTaskSpecHash, computeZkmlInputCommitment, create404genAdapter, createAkashAdapter, createGensynAdapter, createGradientsAdapter, createHttpFacilitator, createLiumAdapter, createRenderAdapter, createRidgesAdapter, createZkmlAdapter, deadlineBoundedPolicy, decisionRecordHash, decodeEscrowAccount, decodeGensynBundle, decodePaymentRequired, decodePaymentResponse, decodePaymentSignature, decodeZkmlProofUri, encodeGensynBundle, encodePaymentRequired, encodePaymentResponse, encodePaymentSignature, encodeZkmlProofUri, exactFeePayer, fetchTaskSpec, fileFormat, fundFromAccept, gen404DemoJobSpec, gensynAutoRelease, gensynDemoJobSpec, gensynProofAutoRelease, gradientsDemoJobSpec, hashMatches, isBadPortUrl, isPublicAddress, jcs, jsonSchema, liumDemoJobSpec, llmRubric, memoryReplayStore, paramsHash, parseEscroExtension, parseEscrowAccept, parseUsdc, payAddressRule, payUrlRefusal, periodSla, podReceipt, predicateJob, predicateMemo, proofUriError, readEscrowFromChain, readPlatformConfig, renderAmount, renderDemoJobSpec, reproduceGensynCompute, ridgesDemoJobSpec, runPredicate, score404genDemoDeliverable, scoreAkashDemoDeliverable, scoreGradientsDemoDeliverable, scoreLiumDemoDeliverable, scoreRenderDemoDeliverable, scoreRidgesDemoDeliverable, serviceResultToSubmitParams, settlementModeSupported, signEscrowPayload, solveAkashDemo, solveGen404Demo, solveGradientsDemo, solveLiumDemo, solveRenderDemo, solveRidgesDemo, solveZkmlDemo, tao, testsPass, verifyBuyerPresentation, verifyEscrowPayload, verifyReeProof, verifyZkmlProof, verifyZkmlProofUri, zkmlDemoJobSpec, zkmlProofAutoRelease };
|
|
3097
|
+
export type { Acceptance, AcceptanceCriterion, AdapterContractOptions, AkashAdapterConfig, Akt, AutoReleaseDecision, BazaarDeclaration, BazaarHttpInput, BotDescriptor, BotRole, BuildBazaarDeclarationOptions, BuildEscrowAcceptOptions, BuildExactAcceptOptions, BuyerPresentationResult, ChainAccountInvalidReason, ChainEscrowFigures, ChainEscrowReading, ChainReadErrorCode, ChainReadRpc, ChainReadTarget, ChainSettlement, CreateEscrowParams, CreateEscrowResult, DecisionJob, DecisionRecord, DecodedEscrowAccount, DeliverableFormat, DeliverableType, Delivery, EscroExtensionInfo, EscroNextAction, EscroOptions, EscroReceipt, EscroSettlementTerms, EscrowAcceptSelection, EscrowAccount, EscrowErrorCode, ExactAcceptRefusal, Facilitator, FacilitatorOperation, FundFromAcceptDeps, FundFromAcceptResult, Gen404AdapterConfig, GensynAdapterConfig, GensynDeliverableBundle, GensynProofAutoReleaseOptions, GradientsAdapterConfig, HostLookup, HttpFacilitatorOptions, ListBotsParams, ListOptions, LiumAdapterConfig, Network, OnDeliveryAccept, OnDeliveryAcceptRefusal, OnDeliveryExtra, OnDeliveryFundRefusal, OnDeliveryInvalidReason, OnDeliveryPayloadFields, OnDeliveryPaymentPayload, OnDeliveryScheme, OnDeliveryVerifyResult, PaginatedResult, ParseEscrowAcceptContext, PayOffer, PayParams, PayPolicy, PayRefusal, PayRequest, PayUrlRefusal, PaymentPayload, PaymentRequired, PaymentRequirements, PaymentResult, PaymentRouter, PinContent$3 as PinContent, PlatformConfigTerms, PollOptions, Predicate, PredicateCheck, PredicateContext, PredicateName, PredicateOutcome, PredicateResult, ProtocolStats, ProtocolStatsFigures, Rail, RaiseDisputeParams, ReadEscrowFromChainOptions, ReeExecution, ReeProof, ReeVerification, ReeVerifyContext, ReleasePaymentOutcome, ReleaseWithPredicateOutcome, Render, RenderAdapterConfig, ReplayStore, ReproduceCompute, ResolveProofUri, ResourceInfo, RidgesAdapterConfig, RunAkashDeployment, RunCodingAgent, RunGpuJob, RunRenderJob, SendOptions, ServedWalletReputation, ServiceAdapter, ServiceResult, SettlementMode, SettlementResponse, SpendCap, SubmitDeliverableParams, SubnetCall, SupportedKind, SupportedResponse, Tao, TaskSpec, TaskType, TxShape, UnsignedBotDescriptor, UsdcToAktSwap, UsdcToRenderSwap, UsdcToTaoSwap, VerifyEscrowContext, VerifyPresentationContext, VerifyResponse, WorkerCandidate, X402SpendCap, ZkmlAdapterConfig, ZkmlDeliverable, ZkmlExpectation, ZkmlInferenceOutput, ZkmlProof, ZkmlProofAutoReleaseOptions, ZkmlProofBundle, ZkmlReviewPolicy, ZkmlReviewResult, ZkmlVerification };
|