@escro/sdk 0.1.3 → 0.2.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/dist/index.d.cts CHANGED
@@ -1,9 +1,418 @@
1
- import { TaskSpec, EscrowState, EscrowAccount } from '@escro/shared';
2
- export { AcceptanceCriterion, DeliverableFormat, DeliverableType, EscrowAccount, EscrowErrorCode, EscrowState, Network, TaskSpec, TaskType } from '@escro/shared';
3
1
  import { Keypair } from '@solana/web3.js';
4
2
 
3
+ /**
4
+ * All possible lifecycle states of an AgentEscrow account on-chain.
5
+ *
6
+ * State transitions (happy path):
7
+ * CREATED → FUNDED → IN_PROGRESS → SUBMITTED → COMPLETED
8
+ *
9
+ * Exception paths:
10
+ * Any state (before COMPLETED) → DISPUTED (human arbitration)
11
+ * CREATED | FUNDED → CANCELLED (buyer cancels before agent accepts)
12
+ * SUBMITTED → COMPLETED (24h timeout auto-release to worker)
13
+ * IN_PROGRESS → REFUNDED (deadline expiry auto-refund to buyer)
14
+ */
15
+ declare enum EscrowState {
16
+ /** Escrow PDA created on-chain; awaiting token deposit from the maker. */
17
+ CREATED = "CREATED",
18
+ /** Maker deposited tokens into the vault; open for agent acceptance. */
19
+ FUNDED = "FUNDED",
20
+ /** An agent accepted the task; work is underway. */
21
+ IN_PROGRESS = "IN_PROGRESS",
22
+ /** Agent submitted a deliverable URI; awaiting buyer review or 24h auto-release. */
23
+ SUBMITTED = "SUBMITTED",
24
+ /** Funds released to the agent. Terminal state. */
25
+ COMPLETED = "COMPLETED",
26
+ /** Buyer cancelled before work started. Terminal state. */
27
+ CANCELLED = "CANCELLED",
28
+ /** Maker or agent raised a dispute; requires human arbitration. */
29
+ DISPUTED = "DISPUTED",
30
+ /** Funds returned to the maker (deadline expiry or dispute resolution). Terminal state. */
31
+ REFUNDED = "REFUNDED"
32
+ }
33
+ /** Solana cluster the escrow account lives on. */
34
+ type Network = "mainnet-beta" | "devnet" | "localnet";
35
+ /**
36
+ * Full on-chain representation of an AgentEscrow PDA, enriched with
37
+ * off-chain metadata resolved by the API server.
38
+ *
39
+ * `amount` and all `*At` timestamps use the on-chain units:
40
+ * - `amount` is in the SPL token's smallest denomination (e.g. μUSDC = 10⁻⁶ USDC).
41
+ * - timestamps are Unix seconds as stored in the Anchor account.
42
+ *
43
+ * When serialising over HTTP, `amount` is represented as a decimal `string`
44
+ * (see {@link GetEscrowResponse}) to avoid JSON `number` precision loss.
45
+ */
46
+ interface EscrowAccount {
47
+ /** Base-58 public key of the escrow PDA. */
48
+ address: string;
49
+ /** Base-58 public key of the task creator (the party paying for the work). */
50
+ maker: string;
51
+ /** Base-58 public key of the assigned agent, or `null` if no agent has accepted yet. */
52
+ taker: string | null;
53
+ /** Base-58 public key of the SPL token mint used for payment (e.g. USDC mint). */
54
+ mint: string;
55
+ /**
56
+ * Payment amount held in escrow, in the mint's smallest denomination.
57
+ * Stored as `bigint` to preserve full u64 precision from the on-chain account.
58
+ */
59
+ amount: bigint;
60
+ /** Current lifecycle state of the escrow. */
61
+ state: EscrowState;
62
+ /**
63
+ * SHA-256 hex digest of the canonical UTF-8 JSON serialisation of the {@link TaskSpec}.
64
+ * Stored on-chain; used by the oracle to verify it is evaluating the correct spec.
65
+ */
66
+ taskSpecHash: string;
67
+ /**
68
+ * Content-addressed URI (ipfs:// or ar://) where the full {@link TaskSpec} JSON is pinned.
69
+ * `null` until the maker uploads the spec via `POST /v1/task-specs`.
70
+ */
71
+ taskSpecUri: string | null;
72
+ /** Base-58 public key of the oracle authority permitted to sign timeout_release / refund_buyer. */
73
+ oracle: string;
74
+ /**
75
+ * Percentage of `amount` charged as a platform fee, in basis points.
76
+ * Deducted from the escrow vault on successful settlement.
77
+ * Valid range: 0–10 000 (0 %–100 %).
78
+ */
79
+ oracleFeeBps: number;
80
+ /** Unix timestamp (seconds) when the escrow PDA was initialised. */
81
+ createdAt: number;
82
+ /**
83
+ * Unix timestamp (seconds) at which the escrow deadline expires; mirrors the
84
+ * on-chain `deadline` field set at `create_escrow`. A Worker Bot reads this to
85
+ * decide whether it can finish a job before the deadline (never claim what it
86
+ * can't finish); after it passes, an unstarted escrow is refundable to the maker.
87
+ */
88
+ deadline: number;
89
+ /** Unix timestamp (seconds) of the most recent agent submission, or `null`. */
90
+ submittedAt: number | null;
91
+ /**
92
+ * SHA-256 hex digest of the worker's submitted deliverable, mirrored from the
93
+ * on-chain `deliverable_hash` written at `submit_deliverable`; `null` until the
94
+ * escrow reaches SUBMITTED. The on-chain value is authoritative: a Buyer Bot's
95
+ * review re-verifies a deliverable against a hash it independently expects and
96
+ * never treats this mirror as proof of integrity on its own.
97
+ */
98
+ deliverableHash: string | null;
99
+ /**
100
+ * URI of the submitted deliverable artifact (S3 presigned / IPFS / Arweave),
101
+ * mirrored from the off-chain `proof_uri` recorded at `submit_deliverable`;
102
+ * `null` until SUBMITTED. The Buyer Bot fetches the deliverable content here to
103
+ * review it.
104
+ */
105
+ proofUri: string | null;
106
+ /** PDA canonical bump seed, stored on-chain to validate future instructions. */
107
+ bump: number;
108
+ /** Solana cluster this account belongs to. */
109
+ network: Network;
110
+ }
111
+ /** Protocol-wide aggregate statistics — public, unauthenticated. */
112
+ interface ProtocolStats {
113
+ totalEscrows: number;
114
+ totalVolumeUsdc: string;
115
+ /**
116
+ * Settled USDC volume: the sum of `amount_usdc` (the job amount, which the
117
+ * worker keeps in full; the additive platform fee is protocol revenue, not
118
+ * settled work volume) over escrows in the COMPLETED terminal state. COMPLETED
119
+ * is reached only by the three worker-paying instructions (release_payment,
120
+ * timeout_release, arbitration_release); refunded and cancelled escrows never
121
+ * paid a worker and are excluded. This is the honest headline number: it counts
122
+ * settlement, not transaction volume.
123
+ */
124
+ settledVolumeUsdc: string;
125
+ byState: Record<EscrowState, number>;
126
+ activeEscrows: number;
127
+ }
128
+
129
+ /**
130
+ * Broad categories of agent work.
131
+ *
132
+ * Used for analytics and UI display. Use `"custom"` for task types not
133
+ * covered by the built-in categories.
134
+ */
135
+ type TaskType = "code_generation" | "code_review" | "data_analysis" | "content_writing" | "translation" | "summarization" | "question_answering" | "image_generation" | "audio_transcription" | "custom";
136
+ /** High-level container format for a deliverable artifact. */
137
+ type DeliverableType = "text" | "json" | "file" | "url" | "code";
138
+ /**
139
+ * Constraints on the shape, size, and encoding of the expected deliverable.
140
+ */
141
+ interface DeliverableFormat {
142
+ /** High-level container type. Determines which other fields are applicable. */
143
+ type: DeliverableType;
144
+ /**
145
+ * JSON Schema (draft-07) object the deliverable must validate against.
146
+ * Only applicable when `type === "json"`.
147
+ */
148
+ schema?: Record<string, unknown>;
149
+ /**
150
+ * Expected MIME type of the delivered file (e.g. `"application/pdf"`, `"image/png"`).
151
+ * Only applicable when `type === "file"`.
152
+ */
153
+ mimeType?: string;
154
+ /**
155
+ * Maximum permitted size of the deliverable content in bytes.
156
+ * Applies to `"file"`, `"text"`, `"code"`, and `"json"` types.
157
+ */
158
+ maxSizeBytes?: number;
159
+ /**
160
+ * Programming language identifier for code deliverables (e.g. `"typescript"`, `"python"`).
161
+ * Only applicable when `type === "code"`.
162
+ */
163
+ language?: string;
164
+ }
165
+ /**
166
+ * A single acceptance criterion that the deliverable must satisfy.
167
+ */
168
+ interface AcceptanceCriterion {
169
+ /**
170
+ * Unique identifier for this criterion within the task spec.
171
+ * Convention: short kebab-case string, e.g. `"ac-correctness"`, `"ac-format"`.
172
+ * Must be unique within a single {@link TaskSpec}.
173
+ */
174
+ id: string;
175
+ /**
176
+ * Human-readable description of what must be true for this criterion to pass.
177
+ */
178
+ description: string;
179
+ /**
180
+ * Relative importance of this criterion.
181
+ * Weights are normalised across all criteria, so only their ratios matter.
182
+ * Defaults to `1.0` when omitted.
183
+ */
184
+ weight?: number;
185
+ /**
186
+ * When `true`, this criterion is mandatory for acceptance.
187
+ * Defaults to `false`.
188
+ */
189
+ required?: boolean;
190
+ }
191
+ /**
192
+ * Canonical specification of the unit of work held in escrow.
193
+ *
194
+ * This object is:
195
+ * 1. Serialised to canonical UTF-8 JSON (sorted keys, no trailing whitespace).
196
+ * 2. Hashed with SHA-256 → stored on-chain as `EscrowAccount.taskSpecHash`.
197
+ * 3. Pinned to IPFS or Arweave → URI stored as `EscrowAccount.taskSpecUri`.
198
+ *
199
+ * Any mutation of the spec changes its hash, invalidating the on-chain record.
200
+ */
201
+ interface TaskSpec {
202
+ /**
203
+ * Semver string identifying the task spec schema version (e.g. `"1.0.0"`).
204
+ * Allows the oracle and API server to handle format evolution gracefully.
205
+ * Increment the minor version for backwards-compatible additions;
206
+ * the major version for breaking changes.
207
+ */
208
+ version: string;
209
+ /**
210
+ * Broad category of the task. See {@link TaskType} for supported values.
211
+ */
212
+ taskType: TaskType;
213
+ /**
214
+ * Complete description of the task, written for both the agent performing it
215
+ * and the oracle evaluating the result.
216
+ *
217
+ * Good descriptions:
218
+ * - State the goal, not just the method.
219
+ * - Include any non-obvious constraints (language, style, performance bounds).
220
+ * - Are precise enough that an LLM could verify correctness without ambiguity.
221
+ */
222
+ description: string;
223
+ /**
224
+ * Ordered list of acceptance criteria the deliverable must satisfy.
225
+ * Must contain at least one entry.
226
+ */
227
+ acceptanceCriteria: AcceptanceCriterion[];
228
+ /**
229
+ * Structural and size constraints the deliverable must conform to.
230
+ */
231
+ deliverableFormat: DeliverableFormat;
232
+ /**
233
+ * Arbitrary key-value extension map for protocol plugins, agent hints, or audit trails.
234
+ */
235
+ metadata: Record<string, unknown>;
236
+ }
237
+
238
+ /**
239
+ * Exhaustive set of machine-readable error codes returned by the escro.ai REST API
240
+ * in the `code` field of an {@link ApiError} response.
241
+ *
242
+ * Consumers should switch on this value to handle errors programmatically
243
+ * rather than parsing the human-readable `error` string.
244
+ */
245
+ type EscrowErrorCode =
246
+ /** The requested escrow PDA does not exist on the specified network. */
247
+ "ESCROW_NOT_FOUND"
248
+ /** The requested operation is not permitted in the escrow's current state. */
249
+ | "ESCROW_INVALID_STATE"
250
+ /** The referenced task spec hash has not been registered. */
251
+ | "TASK_SPEC_NOT_FOUND"
252
+ /** The submitted task spec failed schema validation. */
253
+ | "TASK_SPEC_INVALID"
254
+ /** The caller does not have permission to perform this action. */
255
+ | "UNAUTHORIZED"
256
+ /** The provided transaction signature is invalid or does not match the escrow. */
257
+ | "INVALID_SIGNATURE"
258
+ /** The requested token amount is zero, negative, or exceeds the u64 maximum. */
259
+ | "INVALID_AMOUNT"
260
+ /** The escrow's network does not match the caller's requested network. */
261
+ | "NETWORK_MISMATCH"
262
+ /** The caller has exceeded the rate limit; retry after the indicated backoff. */
263
+ | "RATE_LIMITED"
264
+ /** An unexpected server-side error occurred; report to escro.ai support. */
265
+ | "INTERNAL_ERROR"
266
+ /** Request body or query parameters failed schema validation. */
267
+ | "VALIDATION_ERROR";
268
+
269
+ /**
270
+ * EscroBots v0 - the permissionless capability directory (ARCHITECTURE §8).
271
+ *
272
+ * A bot advertises itself by publishing a wallet-signed capability descriptor.
273
+ * The descriptor is a *claim*, not a verified fact - on-chain history is the
274
+ * verification (surfaced in the Phase 7 v1 directory). The registry performs no
275
+ * approval, review, or ranking; fraud against the protocol is the only removal
276
+ * criterion. The descriptor document itself is independently verifiable: anyone
277
+ * holding it can check `signature` against `wallet` without trusting the API.
278
+ */
279
+ /**
280
+ * The advertisable roles. Single source for both the `BotRole` type and the API's
281
+ * zod enum (routes/bots.ts uses `z.enum(BOT_ROLES)`), so the accepted values and
282
+ * the type cannot drift: a role added here flows into validation automatically.
283
+ */
284
+ declare const BOT_ROLES: readonly ["worker", "buyer", "both"];
285
+ /** Whether the bot hires work, performs work, or both. */
286
+ type BotRole = (typeof BOT_ROLES)[number];
287
+ /**
288
+ * The descriptor fields the bot's wallet signs. Everything a registry consumer
289
+ * needs to find and reach the bot, minus the signature over these fields.
290
+ */
291
+ interface UnsignedBotDescriptor {
292
+ /** Base58 Solana pubkey - the advertising bot and the descriptor's signer. */
293
+ wallet: string;
294
+ /** What the bot does in the escrow relationship. */
295
+ role: BotRole;
296
+ /** Free-form capability tags, e.g. `["fine-tune", "eval"]`. Filterable. */
297
+ capabilities: string[];
298
+ /** The underlying service the bot wraps, e.g. `"bittensor:sn56"`. */
299
+ serviceRef: string;
300
+ /** Human-readable pricing guidance, e.g. `"~$5 per fine-tune job"`. */
301
+ pricingHint: string;
302
+ /** Optional http(s) endpoint a buyer can reach the bot at. */
303
+ endpoint?: string;
304
+ /** Unix milliseconds when the descriptor was signed. Monotonic per wallet. */
305
+ signedAt: number;
306
+ }
307
+ /**
308
+ * A signed capability descriptor as stored and served by the registry.
309
+ * `signature` is a base58 detached Ed25519 signature over the canonical form of
310
+ * the {@link UnsignedBotDescriptor} fields (see `canonicalBotDescriptorMessage`).
311
+ */
312
+ interface BotDescriptor extends UnsignedBotDescriptor {
313
+ /** Base58 detached Ed25519 signature over the canonical unsigned descriptor. */
314
+ signature: string;
315
+ }
316
+
317
+ type SolanaCluster = "devnet" | "mainnet";
318
+
319
+ /** Dispute tally with its outcome split (from the wallet's perspective). */
320
+ interface DisputeRecord {
321
+ /** Total disputes this wallet was party to (raised by either side). */
322
+ total: number;
323
+ /** Disputes resolved in this wallet's favour. */
324
+ won: number;
325
+ /** Disputes resolved against this wallet. */
326
+ lost: number;
327
+ }
328
+ /** Worker-side raw reputation components for a wallet. */
329
+ interface WorkerReputation {
330
+ /** Tasks this wallet claimed. */
331
+ tasksClaimed: number;
332
+ /**
333
+ * Completions credited to the Worker. Per the #23.1 ruling this is exactly the
334
+ * explicit-Buyer-release and timeout-release paths; an arbitration_release is a
335
+ * dispute WIN (see {@link disputes}), not a completion, though its funds still
336
+ * count in {@link volumeSettledUsdc}.
337
+ */
338
+ completions: number;
339
+ /** Completions via explicit Buyer release (stored distinctly — #23.1). */
340
+ completionsViaRelease: number;
341
+ /** Completions via timeout release (stored distinctly — #23.1). */
342
+ completionsViaTimeout: number;
343
+ /** Claimed-but-not-delivered escrows (deadline-expiry refund — #23.2). */
344
+ nonDeliveries: number;
345
+ /** completions / tasksClaimed; null when no task was claimed. */
346
+ completionRate: number | null;
347
+ /** Disputes as Worker: won = arbitration_release, lost = arbitration_refund. */
348
+ disputes: DisputeRecord;
349
+ /** disputes.total / tasksClaimed; null when no task was claimed. */
350
+ disputeRate: number | null;
351
+ /** Sum of worker_amount received in μUSDC. */
352
+ volumeSettledUsdc: bigint;
353
+ /** Avg seconds create->claim across this wallet's claimed escrows; null if none. */
354
+ avgCreateToClaimSeconds: number | null;
355
+ /** Avg seconds claim->submit across this wallet's submitted escrows; null if none. */
356
+ avgClaimToSubmitSeconds: number | null;
357
+ }
358
+ /** Buyer-side raw reputation components for a wallet. */
359
+ interface BuyerReputation {
360
+ /** Escrows this wallet created. */
361
+ escrowsCreated: number;
362
+ /** Escrows that settled via timeout release — buyer non-response signal (#23.1). */
363
+ timeoutReleases: number;
364
+ /** Disputes as Buyer: won = arbitration_refund, lost = arbitration_release. */
365
+ disputes: DisputeRecord;
366
+ /** disputes.total / escrowsCreated; null when no escrow was created. */
367
+ disputeRate: number | null;
368
+ /** Sum of worker_amount settled out of escrows this wallet funded, in μUSDC. */
369
+ volumeSettledUsdc: bigint;
370
+ }
371
+ /**
372
+ * The complete raw reputation for one wallet. No composite/overall score field
373
+ * exists by design (ARCHITECTURE §9).
374
+ */
375
+ interface WalletReputation {
376
+ /** Base-58 wallet address. */
377
+ wallet: string;
378
+ /** Worker-side components. */
379
+ asWorker: WorkerReputation;
380
+ /** Buyer-side components. */
381
+ asBuyer: BuyerReputation;
382
+ /** Unix seconds of first Escro activity (wallet-age basis); null if none. */
383
+ firstActivityAt: number | null;
384
+ /** Unix seconds of most recent Escro activity; null if none. */
385
+ lastActivityAt: number | null;
386
+ }
387
+ /** JSON-safe form of {@link WalletReputation} (bigint volumes as decimal strings). */
388
+ interface SerializedWalletReputation extends Omit<WalletReputation, "asWorker" | "asBuyer"> {
389
+ asWorker: Omit<WorkerReputation, "volumeSettledUsdc"> & {
390
+ volumeSettledUsdc: string;
391
+ };
392
+ asBuyer: Omit<BuyerReputation, "volumeSettledUsdc"> & {
393
+ volumeSettledUsdc: string;
394
+ };
395
+ }
396
+ /**
397
+ * The wire shape served by the internal reputation endpoint: the serialized
398
+ * aggregates plus wallet age derived at serve time. The indexer stores raw
399
+ * clock-free timestamps ({@link WalletReputation.firstActivityAt}); age (#23.5,
400
+ * "age since first Escro activity") is a function of the serving clock, so it is
401
+ * derived here rather than baked into the stored aggregates.
402
+ */
403
+ interface ServedWalletReputation extends SerializedWalletReputation {
404
+ /** now - firstActivityAt in seconds; null when the wallet has no activity. */
405
+ walletAgeSeconds: number | null;
406
+ }
407
+
5
408
  /** Constructor options for the {@link Escro} client. */
6
409
  interface EscroOptions {
410
+ /**
411
+ * Which Solana cluster this client talks to. Required so the program ID and
412
+ * USDC mint resolve correctly. Pass `"devnet"` for testing, `"mainnet"` for
413
+ * production. Breaking change in SDK 0.2.0 (previously implicit devnet).
414
+ */
415
+ cluster: SolanaCluster;
7
416
  /** Solana RPC endpoint URL. */
8
417
  rpcUrl: string;
9
418
  /** Escro REST API base URL (e.g. "https://api.escro.ai"). */
@@ -15,11 +424,19 @@ interface EscroOptions {
15
424
  interface CreateEscrowParams {
16
425
  /** Full task specification uploaded to IPFS. */
17
426
  taskSpec: TaskSpec;
18
- /** Payment amount in μUSDC (1 USDC = 1_000_000). Minimum: 5_000_000. */
427
+ /**
428
+ * Worker's net payment in μUSDC (1 USDC = 1_000_000). Minimum: 5_000_000.
429
+ * The buyer is charged `amountUsdc + fee` at creation; the worker receives
430
+ * the full `amountUsdc` on settlement.
431
+ */
19
432
  amountUsdc: number;
20
433
  /** Unix timestamp (seconds) at which the escrow deadline expires. */
21
- deadlineSeconds: number;
22
- /** Base-58 public key of the worker pre-assigned to this task. */
434
+ deadlineUnix: number;
435
+ /**
436
+ * Base-58 public key of the worker assigned to this task. Required —
437
+ * every escrow is created against a specific worker (open tasks are
438
+ * not supported).
439
+ */
23
440
  assignedWorker: string;
24
441
  }
25
442
  /** Return value from {@link Escro.createEscrow}. */
@@ -77,11 +494,100 @@ interface PaginatedResult<T> {
77
494
  /** The effective offset applied to this response. */
78
495
  offset: number;
79
496
  }
497
+ /** Filters for an EscroBots registry read (`GET /v1/bots`). */
498
+ interface ListBotsParams {
499
+ /** Free-form capability tag to filter by, e.g. `"fine-tune"`. */
500
+ capability?: string;
501
+ /** Role filter. `worker` includes `both` bots (a `both` bot is hireable as a worker). */
502
+ role?: BotDescriptor["role"];
503
+ /** Maximum number of descriptors to return. */
504
+ limit?: number;
505
+ /** Zero-based offset for pagination. */
506
+ offset?: number;
507
+ }
508
+ /**
509
+ * One candidate returned by {@link Escro.findWorkers}. The `descriptor` is a
510
+ * self-reported CLAIM (ARCHITECTURE §8); `signatureValid` attests only that the
511
+ * claim was genuinely signed by `descriptor.wallet` (authorship), NOT that its
512
+ * capabilities are true. On-chain history (EscroRep, Phase 7) is the verification
513
+ * of the claim, deliberately kept separate here, never merged into one flag.
514
+ */
515
+ interface WorkerCandidate {
516
+ /** The wallet-signed capability descriptor as served by the registry (a claim). */
517
+ descriptor: BotDescriptor;
518
+ /** True iff `descriptor.signature` verifies against `descriptor.wallet` (authorship only). */
519
+ signatureValid: boolean;
520
+ }
521
+
522
+ /**
523
+ * Reserved dual-path payment surface (ARCHITECTURE §7a, BOT_KIT_PRD §10).
524
+ *
525
+ * PLUMBING ONLY. The escrow rail is the sole implemented backend; the `x402`
526
+ * (synchronous) rail is reserved and lands in Phase 9 as an additive backend.
527
+ * Every name here is a FREEZE CONTRACT that Phase 9 (P9.T5) inherits "by name":
528
+ * enabling x402 must not be a breaking change for any kit-generated bot. The
529
+ * shapes below are pinned by a type-level test (src/__tests__/payments.test.ts);
530
+ * Phase 9 may add only OPTIONAL fields.
531
+ */
532
+ /** Single source for the rail identifiers. The {@link Rail} type is derived from
533
+ * this list (drift-safe, mirroring the BOT_ROLES pattern in @escro/shared). */
534
+ declare const RAILS: readonly ["escrow", "x402"];
535
+ /** The payment rails Escro can route across. Only `escrow` is implemented today;
536
+ * `x402` is RESERVED and not enabled until Phase 9. */
537
+ type Rail = (typeof RAILS)[number];
538
+ /** The rails enabled in this build. Frozen to escrow-only until Phase 9 enables
539
+ * x402. Typed `readonly Rail[]` (not the literal tuple) so runtime membership
540
+ * checks stay honest: `ENABLED_RAILS.includes(rail)` narrows nothing away. */
541
+ declare const ENABLED_RAILS: readonly Rail[];
542
+ /** Docs for the payment rails, linked from the reserved-rail error and the kit
543
+ * config's rejection message so both point to the same place. */
544
+ declare const RAILS_DOCS_URL = "https://docs.escro.ai/rails";
545
+ /** The minimal payment shape a {@link PaymentRouter} inspects to choose a rail.
546
+ * FROZEN; Phase 9 may add only optional fields. */
547
+ interface TxShape {
548
+ /** Recipient wallet address (base58). */
549
+ readonly to: string;
550
+ /** Amount to move, in USDC micro-units (integer, 6 decimals). */
551
+ readonly amountMicroUsdc: number;
552
+ /** `async` (verification-needed) work routes to escrow; `sync` work is x402's territory. */
553
+ readonly mode: "async" | "sync";
554
+ }
555
+ /** Chooses the rail for a payment. Defined now with a single backend; `x402` is
556
+ * returned only once that rail is enabled (Phase 9). FROZEN signature. */
557
+ interface PaymentRouter {
558
+ selectRail(tx: TxShape): Rail;
559
+ }
560
+ /** The one backend shipped today. Async work routes to escrow; sync work would
561
+ * prefer x402, but x402 is reserved and not enabled (ARCHITECTURE §7a), so the
562
+ * router falls back to escrow rather than ever returning a disabled rail. */
563
+ declare class EscrowPaymentRouter implements PaymentRouter {
564
+ selectRail(tx: TxShape): Rail;
565
+ }
566
+ /** Parameters for a synchronous payment via {@link Escro.pay}. FROZEN: both
567
+ * fields are required now so Phase 9 adds only optional fields; a required field
568
+ * added later would break every kit-generated bot. */
569
+ interface PayParams {
570
+ /** Recipient wallet address (base58). */
571
+ readonly to: string;
572
+ /** Amount to pay, in USDC micro-units (integer, 6 decimals). */
573
+ readonly amountMicroUsdc: number;
574
+ }
575
+ /** Result of a completed payment. FROZEN and rail-generic: `reference` is the
576
+ * rail-native settlement id (a Solana signature for escrow, an x402 receipt for
577
+ * x402), so the shape describes either rail without change. */
578
+ interface PaymentResult {
579
+ /** Which rail settled the payment. */
580
+ readonly rail: Rail;
581
+ /** Rail-native settlement reference. */
582
+ readonly reference: string;
583
+ }
80
584
 
81
585
  declare class Escro {
82
586
  private readonly connection;
83
587
  private readonly api;
84
588
  private readonly options;
589
+ private readonly cluster;
590
+ private readonly router;
85
591
  constructor(options: EscroOptions);
86
592
  /**
87
593
  * Create a new escrow: registers with the API, signs and submits the
@@ -92,7 +598,9 @@ declare class Escro {
92
598
  createEscrow(params: CreateEscrowParams): Promise<CreateEscrowResult>;
93
599
  /**
94
600
  * Release payment to the worker. Buyer must be the wallet in the constructor.
95
- * Updates API DB state, then builds and submits the `release_payment` on-chain tx.
601
+ * Builds and submits the `release_payment` on-chain tx FIRST (the chain is the
602
+ * source of truth), then confirms DB state. The DB confirmation is best-effort:
603
+ * the oracle sweep reconciles it if it fails.
96
604
  *
97
605
  * @returns Solana transaction signature.
98
606
  */
@@ -112,6 +620,18 @@ declare class Escro {
112
620
  * @returns Solana transaction signature.
113
621
  */
114
622
  cancelEscrow(address: string): Promise<string>;
623
+ /**
624
+ * Reserved synchronous-payment entrypoint (ARCHITECTURE §7a). `pay()` settles
625
+ * over the x402 rail, which is not implemented until Phase 9; today it rejects
626
+ * with {@link EscroRailNotEnabledError}. The signature is FROZEN so enabling
627
+ * x402 later is not a breaking change for kit-generated bots. For asynchronous,
628
+ * verification-needed work use {@link createEscrow}, the core product.
629
+ *
630
+ * Not `async`: it returns a rejected promise (never awaits) so callers can
631
+ * `await`/`.catch()` it uniformly, and it exercises the same {@link PaymentRouter}
632
+ * routing seam Phase 9 will implement.
633
+ */
634
+ pay(params: PayParams): Promise<PaymentResult>;
115
635
  /**
116
636
  * Claim an assigned task. Worker must be the wallet in the constructor.
117
637
  * Signs and submits the `claim_task` on-chain tx.
@@ -120,7 +640,7 @@ declare class Escro {
120
640
  */
121
641
  claimTask(address: string): Promise<string>;
122
642
  /**
123
- * Submit a deliverable for oracle evaluation. Worker must be the wallet.
643
+ * Submit a deliverable for the buyer to review. Worker must be the wallet.
124
644
  * Signs and submits the `submit_deliverable` on-chain tx.
125
645
  *
126
646
  * @returns Solana transaction signature.
@@ -137,6 +657,50 @@ declare class Escro {
137
657
  * @param options - Polling, pagination (limit/offset).
138
658
  */
139
659
  getMyTasks(state?: EscrowState[], options?: PollOptions & ListOptions): Promise<PaginatedResult<EscrowAccount>>;
660
+ /**
661
+ * List escrows CREATED by the wallet's public key (the maker / buyer), the
662
+ * mirror of {@link getMyTasks} for the buyer side. Optionally filter by state
663
+ * and paginate.
664
+ *
665
+ * A Buyer Bot uses this to sum its own outstanding (still-locked) escrows for
666
+ * the client-side spend cap: the program is the source of truth, so the total
667
+ * is read from chain state (via the API), never a local tally a crash could lose.
668
+ *
669
+ * @param state - Filter by one or more states (first state used as API filter).
670
+ * @param options - Polling, pagination (limit/offset).
671
+ */
672
+ getMyEscrows(state?: EscrowState[], options?: PollOptions & ListOptions): Promise<PaginatedResult<EscrowAccount>>;
673
+ /**
674
+ * Find worker bots in the EscroBots registry, optionally filtered by
675
+ * capability. Queries `GET /v1/bots?role=worker` (the API includes `both`
676
+ * bots) and returns candidates in REGISTRY ORDER: this method does no
677
+ * ranking, scoring, or reordering (ARCHITECTURE §8: no curation; §13: not a
678
+ * marketplace). Escro-shipped code never ranks; the caller's own bot decides.
679
+ *
680
+ * Each candidate keeps the CLAIM (`descriptor`) separate from the AUTHORSHIP
681
+ * check (`signatureValid`, verified locally so a third party need not trust the
682
+ * API). Capabilities remain unverified claims; on-chain history (EscroRep,
683
+ * Phase 7) is their verification, deliberately not merged in here.
684
+ */
685
+ findWorkers(params?: {
686
+ capability?: string;
687
+ } & ListOptions): Promise<WorkerCandidate[]>;
688
+ /**
689
+ * Fetch the EscroRep bulk export: every indexed wallet's RAW reputation
690
+ * components (ARCHITECTURE §9), each wallet exactly once, in one fetch. Returns
691
+ * the raw components verbatim - this method does NO ranking, scoring, or default
692
+ * weighting (Escro-shipped code never ranks; the caller's own bot weights and
693
+ * decides). Selection layers join these components to {@link findWorkers}
694
+ * candidates by wallet. Throws {@link ReputationUnavailableError} when the
695
+ * deployment mounts no reputation source (HTTP 404).
696
+ */
697
+ listReputations(): Promise<ServedWalletReputation[]>;
698
+ /**
699
+ * Fetch protocol-wide stats from the public `GET /v1/stats` endpoint.
700
+ *
701
+ * @returns protocol-wide {@link ProtocolStats}.
702
+ */
703
+ getStats(): Promise<ProtocolStats>;
140
704
  /**
141
705
  * Fetch an escrow by its PDA address.
142
706
  * If `options.poll` is true, polls with exponential backoff until the escrow
@@ -145,6 +709,130 @@ declare class Escro {
145
709
  getEscrow(address: string, options?: PollOptions): Promise<EscrowAccount>;
146
710
  }
147
711
 
712
+ declare class ApiClient {
713
+ private readonly baseUrl;
714
+ private readonly wallet;
715
+ constructor(baseUrl: string, wallet: Keypair);
716
+ private url;
717
+ /** GET /v1/escrows/:address */
718
+ getEscrow(address: string): Promise<EscrowAccount>;
719
+ /** GET /v1/escrows?assignedTo=...&maker=...&state=... */
720
+ listEscrows(params: {
721
+ assignedTo?: string;
722
+ maker?: string;
723
+ state?: EscrowState;
724
+ limit?: number;
725
+ offset?: number;
726
+ }): Promise<PaginatedResult<EscrowAccount>>;
727
+ /**
728
+ * GET /v1/bots?capability=...&role=...&limit=...&offset= : EscroBots registry
729
+ * read. Unauthenticated public read (no auth headers). Returns descriptors in
730
+ * registry order (newest first); descriptors are self-reported claims.
731
+ */
732
+ listBots(params: ListBotsParams): Promise<PaginatedResult<BotDescriptor>>;
733
+ /**
734
+ * GET /rep : EscroRep bulk export (ARCHITECTURE §9). Unauthenticated public
735
+ * read (no auth headers). Returns every indexed wallet's RAW components exactly
736
+ * once (no composite score). Ranking layers join against this ONE bulk fetch:
737
+ * the per-wallet endpoint shares a 10/min public-metrics budget, so a
738
+ * per-candidate fan-out would rate-limit itself. A 404 means the deployment
739
+ * mounted no reputation source (unknown wallets return zeroed rep, never 404),
740
+ * so it surfaces as {@link ReputationUnavailableError}, not EscrowNotFoundError.
741
+ */
742
+ listReputations(): Promise<ServedWalletReputation[]>;
743
+ /**
744
+ * POST /v1/escrows — create escrow, returns unsigned tx + ids.
745
+ * Requires auth.
746
+ */
747
+ createEscrow(params: CreateEscrowParams): Promise<{
748
+ escrowId: string;
749
+ escrowPda: string;
750
+ unsignedTx: string;
751
+ }>;
752
+ /**
753
+ * POST /v1/escrows/:address/claim — returns unsigned tx.
754
+ * Requires auth (worker).
755
+ */
756
+ claimTask(address: string): Promise<{
757
+ unsignedTx: string;
758
+ }>;
759
+ /**
760
+ * POST /v1/escrows/:address/submit — returns unsigned tx.
761
+ * Requires auth (worker).
762
+ */
763
+ submitDeliverable(address: string, params: SubmitDeliverableParams): Promise<{
764
+ unsignedTx: string;
765
+ }>;
766
+ /**
767
+ * POST /v1/escrows/:address/release — DB-only state update.
768
+ * Requires auth (buyer). No on-chain tx returned.
769
+ */
770
+ releasePaymentDb(address: string): Promise<void>;
771
+ /**
772
+ * POST /v1/escrows/:address/cancel — returns unsigned tx.
773
+ * Requires auth (buyer). Only valid when state is FUNDED.
774
+ */
775
+ cancelEscrow(address: string): Promise<{
776
+ unsignedTx: string;
777
+ }>;
778
+ /**
779
+ * POST /v1/escrows/:address/dispute — returns unsigned tx.
780
+ * Requires auth (buyer or worker).
781
+ */
782
+ raiseDispute(address: string, params: RaiseDisputeParams): Promise<{
783
+ unsignedTx: string;
784
+ }>;
785
+ /**
786
+ * GET /v1/stats — public protocol-wide stats.
787
+ * No auth required. Upstream typing in {@link Escro.getStats} narrows the
788
+ * return shape.
789
+ */
790
+ getStats(): Promise<unknown>;
791
+ }
792
+
793
+ /**
794
+ * The result a {@link ServiceAdapter} returns from `execute`. Escro is agnostic
795
+ * to what produced it: `content` is the deliverable itself, `contentHash` is the
796
+ * SHA-256 hex digest the Buyer verifies the deliverable against, and `proofUri`
797
+ * optionally points at where the content is pinned (IPFS/Arweave) or at a proof.
798
+ * No currency or token field appears here; token conversion is adapter-internal
799
+ * (ARCHITECTURE §3, §7).
800
+ */
801
+ interface ServiceResult {
802
+ /** The deliverable itself. */
803
+ content: string | Buffer;
804
+ /** SHA-256 hex digest of {@link ServiceResult.content}. */
805
+ contentHash: string;
806
+ /** Content-addressed URI (ipfs://, ar://) or proof URI for the deliverable. */
807
+ proofUri?: string;
808
+ /** Arbitrary adapter-specific metadata (model, timings, subnet ids, ...). */
809
+ metadata: Record<string, unknown>;
810
+ }
811
+ /**
812
+ * A Worker Bot implements ServiceAdapter to wrap any async service (a Bittensor
813
+ * subnet, an Akash deployment, a Render job, ...). Escro never sees what is
814
+ * underneath and never sees a non-USDC token: the adapter handles any token
815
+ * conversion internally (ARCHITECTURE §3, §7). Every pre-built adapter reuses
816
+ * this interface and is validated by `assertServiceAdapterContract`.
817
+ */
818
+ interface ServiceAdapter {
819
+ /** Stable identifier, e.g. "bittensor:sn56", "akash", "render". */
820
+ id: string;
821
+ /** Advertised capabilities, e.g. ["llm_inference", "image_gen"]. */
822
+ capabilities: string[];
823
+ /** Execute the task described by `spec` and return the deliverable. */
824
+ execute(spec: TaskSpec): Promise<ServiceResult>;
825
+ /** Report whether the underlying service is reachable and ready. */
826
+ healthCheck(): Promise<boolean>;
827
+ }
828
+ /**
829
+ * Map a {@link ServiceResult} onto {@link SubmitDeliverableParams}, surfacing the
830
+ * `contentHash` (and `proofUri`, when present) that `submit_deliverable` records.
831
+ * This is the single point where an adapter's output crosses into the escrow
832
+ * worker flow.
833
+ */
834
+ declare function serviceResultToSubmitParams(result: ServiceResult): SubmitDeliverableParams;
835
+
148
836
  /** Base class for all errors thrown by the @escro/sdk. */
149
837
  declare class EscroError extends Error {
150
838
  readonly code: string;
@@ -154,6 +842,16 @@ declare class EscroError extends Error {
154
842
  declare class EscrowNotFoundError extends EscroError {
155
843
  constructor(address: string);
156
844
  }
845
+ /**
846
+ * The reputation endpoint is not available on this deployment (HTTP 404). A 404
847
+ * from `GET /rep` means no `ReputationSource` is mounted (the surface is
848
+ * unmounted), NOT that a wallet is unknown - unknown wallets return zeroed raw
849
+ * components, never a 404. Kept distinct from {@link EscrowNotFoundError}, whose
850
+ * 404 is about a missing escrow.
851
+ */
852
+ declare class ReputationUnavailableError extends EscroError {
853
+ constructor();
854
+ }
157
855
  /** The operation is not valid for the escrow's current state (HTTP 409). */
158
856
  declare class EscrowStateError extends EscroError {
159
857
  constructor(message: string);
@@ -166,5 +864,837 @@ declare class EscrowTimeoutError extends EscroError {
166
864
  declare class UnauthorizedError extends EscroError {
167
865
  constructor(message?: string);
168
866
  }
867
+ /**
868
+ * A payment rail was requested that is not enabled in this build. The `x402`
869
+ * (synchronous) rail is reserved (ARCHITECTURE §7a) and lands in Phase 9;
870
+ * {@link Escro.pay} throws this until then. `rail` names the unavailable rail.
871
+ */
872
+ declare class EscroRailNotEnabledError extends EscroError {
873
+ readonly rail: string;
874
+ constructor(rail: string);
875
+ }
876
+
877
+ /** Options controlling {@link assertServiceAdapterContract}. */
878
+ interface AdapterContractOptions {
879
+ /**
880
+ * A representative TaskSpec the adapter can execute. The harness calls
881
+ * `execute(sampleSpec)` and validates the returned ServiceResult, so the spec
882
+ * should be one the adapter genuinely handles.
883
+ */
884
+ sampleSpec: TaskSpec;
885
+ }
886
+ /** Thrown by {@link assertServiceAdapterContract}, listing every contract violation. */
887
+ declare class AdapterContractError extends EscroError {
888
+ readonly violations: string[];
889
+ constructor(adapterId: string, violations: string[]);
890
+ }
891
+ /**
892
+ * Assert that `adapter` satisfies the ServiceAdapter contract. Resolves with the
893
+ * ServiceResult produced by `execute(sampleSpec)` when the adapter conforms;
894
+ * rejects with an {@link AdapterContractError} listing every violation otherwise.
895
+ *
896
+ * Reusable across adapters (this phase's Bittensor one, Phase 6's four, Phase 8's
897
+ * networks): a conforming adapter passes, a malformed one fails. The parameter is
898
+ * typed `ServiceAdapter`, but the harness validates at runtime: JS callers and
899
+ * `as`-cast objects reach this too, so every field is checked defensively.
900
+ */
901
+ declare function assertServiceAdapterContract(adapter: ServiceAdapter, options: AdapterContractOptions): Promise<ServiceResult>;
902
+
903
+ /**
904
+ * Amount denominated in TAO (Bittensor's token). Branded so it cannot be assigned to
905
+ * or from a plain `number` by accident and (the point of the brand) so it can never
906
+ * appear in a `ServiceResult` or the escrow submit path: those types have no field of
907
+ * this type. TAO exists ONLY inside the Bittensor adapter layer.
908
+ */
909
+ type Tao = number & {
910
+ readonly __brand: "TAO";
911
+ };
912
+ /** Construct a {@link Tao} amount from a plain number. Adapter-internal use only. */
913
+ declare function tao(amount: number): Tao;
914
+ /** Swap a microUSDC budget into TAO. Real workers route this through a DEX (e.g. Jupiter). */
915
+ type UsdcToTaoSwap = (microUsdc: number) => Promise<Tao>;
916
+ /**
917
+ * Pay subnet miners `budget` TAO to run `spec`; resolve with the raw deliverable. The
918
+ * single shared port shape across every Bittensor adapter (a GPU-rental call is a paid
919
+ * subnet call too; lium re-exports this as `RunGpuJob`).
920
+ */
921
+ type SubnetCall = (spec: TaskSpec, budget: Tao) => Promise<string | Buffer>;
922
+ /** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */
923
+ type PinContent$3 = (content: string | Buffer) => Promise<string>;
924
+
925
+ /**
926
+ * Gradients (Bittensor SN56) ServiceAdapter: the first SHIPPED, supported adapter
927
+ * (the reference pattern P6.T6b-d replicate). A Worker Bot wraps the Gradients
928
+ * fine-tuning subnet behind the `ServiceAdapter` interface: it swaps a per-task
929
+ * USDC budget into TAO internally, pays subnet miners in TAO to fine-tune, collects
930
+ * a checkpoint + eval deliverable, and returns a currency-free `ServiceResult`. The
931
+ * Buyer and the escrow contract only ever see USDC; no TAO-typed value crosses this
932
+ * boundary into SDK core (ARCHITECTURE §3, §7; see ../bittensor/bittensor.type-test.ts
933
+ * for the compile-time proof shared by the Bittensor trio).
934
+ *
935
+ * The swap, subnet call, and pinning are injectable ports so the reference runs (and
936
+ * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
937
+ * real implementations (Jupiter for the swap, the SN56 dendrite, Pinata/Arweave).
938
+ *
939
+ * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (checkpoint
940
+ * + eval JSON). Whether the eval clears the threshold is decided by the BUYER's
941
+ * review.ts, which independently recomputes the score (see `scoreGradientsDemoDeliverable`).
942
+ * The worker never scores-for-release and never releases (CLAUDE.md product framing).
943
+ *
944
+ * Relationship to `examples/worker-bot/bittensor-adapter.ts`: that example is
945
+ * pedagogy ("author your own adapter against the public interface", driven by e2e
946
+ * scenario 13 / the P5.T2b obligation); THIS module is the shipped, importable
947
+ * surface a generated bot uses. The USDC->TAO port skeleton and the execute shape are
948
+ * shared with the other Bittensor adapters via `../bittensor/index.js`; this module
949
+ * supplies only its subnet identity, capabilities, budget, and demo logic.
950
+ */
951
+
952
+ /** Configuration and injectable ports for {@link createGradientsAdapter}. */
953
+ interface GradientsAdapterConfig {
954
+ /** Subnet identifier. Defaults to "sn56" (Gradients); forms the adapter id `bittensor:<subnet>`. */
955
+ subnet?: string;
956
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["fine-tune"]`. */
957
+ capabilities?: string[];
958
+ /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */
959
+ taskBudgetMicroUsdc?: number;
960
+ /** Swap port. Default: a fixed-rate reference stub. */
961
+ swap?: UsdcToTaoSwap;
962
+ /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */
963
+ callSubnet?: SubnetCall;
964
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
965
+ pin?: PinContent$3;
966
+ /** Health-check port. Default: resolves `true`. */
967
+ checkHealth?: () => Promise<boolean>;
968
+ }
969
+ /** Stable id/capabilities, LOCKED against `ADAPTER_DESCRIPTORS.gradients` by a kit test (consult C2). */
970
+ declare const GRADIENTS_ADAPTER_ID = "bittensor:sn56";
971
+ declare const GRADIENTS_CAPABILITIES: readonly ["fine-tune"];
972
+ /** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */
973
+ declare const GRADIENTS_DEMO_MARKER = "gradients-sn56-demo-v1";
974
+ /** The demo eval floor: predictions must be at least this accurate to be accepted. */
975
+ declare const GRADIENTS_DEMO_EVAL_FLOOR = 0.8;
976
+ /**
977
+ * The canned Gradients demo job. Deterministic; its specHash is pinned by a test
978
+ * (consult C8) because the buyer journey depends on hash stability.
979
+ */
980
+ declare const gradientsDemoJobSpec: TaskSpec;
981
+ /**
982
+ * The reference solution to the demo job: the correct predictions plus a
983
+ * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.
984
+ * Exposed so the demo journey and tests share one source of the expected artifact.
985
+ */
986
+ declare function solveGradientsDemo(): string;
987
+ /**
988
+ * The BUYER's independent recompute of the demo eval score in [0, 1]. Reads the
989
+ * substantive output (the predictions) and compares it to the target map the buyer
990
+ * itself defines; it deliberately IGNORES any self-reported `eval.score` in the
991
+ * deliverable, so release can never be worker-controlled (consult C10). Malformed
992
+ * or unparseable content scores 0 and never throws.
993
+ */
994
+ declare function scoreGradientsDemoDeliverable(content: string | Buffer): number;
995
+ /**
996
+ * Build a Gradients (SN56) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`
997
+ * with the default ports; supply real ports for production use. The USDC->TAO swap,
998
+ * pinning, and execute skeleton come from the shared Bittensor core.
999
+ */
1000
+ declare function createGradientsAdapter(config?: GradientsAdapterConfig): ServiceAdapter;
1001
+
1002
+ /** Run the coding agent for `spec`; resolve with the raw deliverable (a test report). */
1003
+ type RunCodingAgent = (spec: TaskSpec) => Promise<string | Buffer>;
1004
+ /** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */
1005
+ type PinContent$2 = (content: string | Buffer) => Promise<string>;
1006
+ /** Configuration and injectable ports for {@link createRidgesAdapter}. */
1007
+ interface RidgesAdapterConfig {
1008
+ /** Service identifier. Defaults to "ridges"; forms the adapter id. */
1009
+ service?: string;
1010
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["code-generation"]`. */
1011
+ capabilities?: string[];
1012
+ /** Coding-agent port. Default: solves the canned demo kata; a placeholder otherwise. */
1013
+ runAgent?: RunCodingAgent;
1014
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1015
+ pin?: PinContent$2;
1016
+ /** Health-check port. Default: resolves `true`. */
1017
+ checkHealth?: () => Promise<boolean>;
1018
+ }
1019
+ /**
1020
+ * Stable id/capabilities. Locked against `ADAPTER_DESCRIPTORS.ridges` by a kit test
1021
+ * at merge (consult C2; the lock lives in create-escro-bot, which depends on this
1022
+ * package, and is landed with the barrel wiring — LANE-NOTES merge step 3).
1023
+ */
1024
+ declare const RIDGES_ADAPTER_ID = "ridges";
1025
+ declare const RIDGES_CAPABILITIES: readonly ["code-generation"];
1026
+ /** Stable marker on the demo spec's metadata so the default agent stub recognizes it. */
1027
+ declare const RIDGES_DEMO_MARKER = "ridges-demo-v1";
1028
+ /** The demo coverage target: the fraction of the test battery that must be covered. */
1029
+ declare const RIDGES_DEMO_COVERAGE_TARGET = 0.8;
1030
+ /**
1031
+ * The canned Ridges demo job. Deterministic; its specHash is pinned by a test
1032
+ * because the buyer journey depends on hash stability.
1033
+ */
1034
+ declare const ridgesDemoJobSpec: TaskSpec;
1035
+ /**
1036
+ * The reference solution to the demo kata: a passing test report over the full
1037
+ * battery, plus a (self-reported, buyer-ignored) pass/coverage block, as canonical
1038
+ * JSON. Deterministic. Exposed so the demo journey and tests share one source of the
1039
+ * expected artifact.
1040
+ */
1041
+ declare function solveRidgesDemo(): string;
1042
+ /**
1043
+ * The BUYER's independent recompute of the demo acceptance, as a score in [0, 1].
1044
+ * It reads the substantive output (the delivered test outputs) and recomputes the
1045
+ * expected FizzBuzz result for each; it deliberately IGNORES any self-reported
1046
+ * pass/coverage in the deliverable, so release can never be worker-controlled
1047
+ * (consult C10). Semantics:
1048
+ * - Any delivered test whose output is wrong = the suite did not pass (exit != 0):
1049
+ * score 0, no matter how much of the battery is covered.
1050
+ * - Otherwise the score is coverage = (distinct battery inputs delivered) / (battery
1051
+ * size); the buyer releases when it clears {@link RIDGES_DEMO_COVERAGE_TARGET}.
1052
+ * Malformed or unparseable content scores 0 and never throws.
1053
+ */
1054
+ declare function scoreRidgesDemoDeliverable(content: string | Buffer): number;
1055
+ /**
1056
+ * Build a Ridges {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with
1057
+ * the default ports; supply real ports for production use.
1058
+ */
1059
+ declare function createRidgesAdapter(config?: RidgesAdapterConfig): ServiceAdapter;
1060
+
1061
+ /**
1062
+ * 404gen (Bittensor SN17) ServiceAdapter: a batch 3D-generation reference adapter,
1063
+ * built to the pattern the shipped Gradients (SN56) adapter established (P6.T6a). A
1064
+ * Worker Bot wraps the 404gen text-to-3D subnet behind the `ServiceAdapter` interface:
1065
+ * it swaps a per-task USDC budget into TAO internally, pays subnet miners in TAO to
1066
+ * generate a batch of 3D assets, collects the batch deliverable, and returns a
1067
+ * currency-free `ServiceResult`. The Buyer and the escrow contract only ever see USDC;
1068
+ * no TAO-typed value crosses this boundary into SDK core (ARCHITECTURE §3, §7; see
1069
+ * ../bittensor/bittensor.type-test.ts for the compile-time proof shared by the Bittensor trio).
1070
+ *
1071
+ * The swap, subnet call, and pinning are injectable ports so the reference runs (and
1072
+ * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
1073
+ * real implementations (Jupiter for the swap, the SN17 dendrite, Pinata/Arweave).
1074
+ *
1075
+ * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (a batch of
1076
+ * 3D assets, each with a declared container format and polygon count). Whether the batch
1077
+ * is acceptable is decided by the BUYER's review.ts. For the canned demo the buyer knows
1078
+ * the exact expected artifact (the eval-threshold review re-verifies the fetched
1079
+ * deliverable hashes to the submitted contentHash) and additionally gates on the declared
1080
+ * per-asset descriptors via `score404genDemoDeliverable` (format, polygon range, batch
1081
+ * completeness). That recompute reads the DECLARED descriptors, not the asset bytes: a
1082
+ * production 404gen buyer generating novel assets must derive the container from the
1083
+ * fetched asset's magic bytes and the polygon count from its parsed geometry before
1084
+ * releasing. The worker never scores-for-release and never releases (CLAUDE.md framing).
1085
+ *
1086
+ * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor
1087
+ * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,
1088
+ * capabilities, budget, and demo logic.
1089
+ */
1090
+
1091
+ /** Configuration and injectable ports for {@link create404genAdapter}. */
1092
+ interface Gen404AdapterConfig {
1093
+ /** Subnet identifier. Defaults to "sn17" (404gen); forms the adapter id `bittensor:<subnet>`. */
1094
+ subnet?: string;
1095
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["3d-generation"]`. */
1096
+ capabilities?: string[];
1097
+ /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */
1098
+ taskBudgetMicroUsdc?: number;
1099
+ /** Swap port. Default: a fixed-rate reference stub. */
1100
+ swap?: UsdcToTaoSwap;
1101
+ /** Subnet-call port. Default: solves the canned demo job; a deterministic placeholder otherwise. */
1102
+ callSubnet?: SubnetCall;
1103
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1104
+ pin?: PinContent$3;
1105
+ /** Health-check port. Default: resolves `true`. */
1106
+ checkHealth?: () => Promise<boolean>;
1107
+ }
1108
+ /** Stable id/capabilities, to be locked against `ADAPTER_DESCRIPTORS["404gen"]` by a kit test at merge (consult C2). */
1109
+ declare const GEN404_ADAPTER_ID = "bittensor:sn17";
1110
+ declare const GEN404_CAPABILITIES: readonly ["3d-generation"];
1111
+ /** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */
1112
+ declare const GEN404_DEMO_MARKER = "404gen-sn17-demo-v1";
1113
+ /** The demo eval floor: the batch must be complete and every asset valid (score 1). */
1114
+ declare const GEN404_DEMO_EVAL_FLOOR = 1;
1115
+ /**
1116
+ * The canned 404gen demo job. Deterministic; its specHash is pinned by a test
1117
+ * (consult C8) because the buyer journey depends on hash stability.
1118
+ */
1119
+ declare const gen404DemoJobSpec: TaskSpec;
1120
+ /**
1121
+ * The reference solution to the demo job: a complete batch of valid assets plus a
1122
+ * (self-reported, buyer-ignored) eval block, as canonical JSON. Deterministic.
1123
+ * Exposed so the demo journey and tests share one source of the expected artifact.
1124
+ */
1125
+ declare function solveGen404Demo(): string;
1126
+ /**
1127
+ * The BUYER's recompute of the demo batch score in [0, 1] over the deliverable's
1128
+ * DECLARED per-asset descriptors. Every delivered asset must pass the format and
1129
+ * polygon-range checks (any single invalid asset scores 0, so a well-formed but junk
1130
+ * extra cannot slip through), and the batch must contain at least the requested count
1131
+ * (completeness); a short batch scores the filled fraction. Any self-reported `eval`
1132
+ * score in the deliverable is ignored. Malformed or unparseable content scores 0 and
1133
+ * never throws.
1134
+ *
1135
+ * NOTE: this gates the deliverable's declared `format`/`polygonCount` fields, not the
1136
+ * asset bytes. For the deterministic canned demo that is sufficient because the buyer
1137
+ * additionally knows the exact expected artifact (the eval-threshold review re-verifies
1138
+ * the fetched deliverable hashes to the submitted contentHash). A production 404gen
1139
+ * buyer generating NOVEL assets must derive the container from the fetched asset's magic
1140
+ * bytes and the polygon count from its parsed geometry before releasing (kit-docs debt).
1141
+ */
1142
+ declare function score404genDemoDeliverable(content: string | Buffer): number;
1143
+ /**
1144
+ * Build a 404gen (SN17) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`
1145
+ * with the default ports; supply real ports for production use. The USDC->TAO swap,
1146
+ * pinning, and execute skeleton come from the shared Bittensor core.
1147
+ */
1148
+ declare function create404genAdapter(config?: Gen404AdapterConfig): ServiceAdapter;
1149
+
1150
+ /**
1151
+ * Lium (Bittensor SN51) ServiceAdapter: a SHIPPED, supported adapter following the
1152
+ * P6.T6a Gradients pattern. A Worker Bot wraps the Lium GPU-compute subnet behind the
1153
+ * `ServiceAdapter` interface: it swaps a per-task USDC budget into TAO internally,
1154
+ * rents GPU compute from subnet miners in TAO to run the job, collects the output
1155
+ * artifact, and returns a currency-free `ServiceResult`. The Buyer and the escrow
1156
+ * contract only ever see USDC; no TAO-typed value crosses this boundary into SDK core
1157
+ * (ARCHITECTURE §3, §7; see ../bittensor/bittensor.type-test.ts for the compile-time
1158
+ * proof shared by the Bittensor trio).
1159
+ *
1160
+ * The swap, GPU-job call, and pinning are injectable ports so the reference runs (and
1161
+ * is tested) without a live DEX, subnet, or IPFS node. A production worker supplies
1162
+ * real implementations (Jupiter for the swap, the SN51 GPU-rental dendrite,
1163
+ * Pinata/Arweave for pinning).
1164
+ *
1165
+ * RELEASE JUDGMENT IS NOT HERE. This adapter only PRODUCES the deliverable (the job's
1166
+ * output artifact). Whether the job completed with a matching artifact is decided by
1167
+ * the BUYER's review.ts, which independently recomputes the scripted job's output and
1168
+ * compares hashes (see `scoreLiumDemoDeliverable`). The worker never scores-for-release
1169
+ * and never releases, and its self-reported `artifactHash` is never trusted
1170
+ * (CLAUDE.md product framing: the buyer is the judge).
1171
+ *
1172
+ * The USDC->TAO port skeleton and the execute shape are shared with the other Bittensor
1173
+ * adapters via `../bittensor/index.js`; this module supplies only its subnet identity,
1174
+ * capabilities, budget, and demo logic. A GPU-rental call is a paid subnet call, so its
1175
+ * port reuses the shared `SubnetCall` shape under the local `RunGpuJob` name.
1176
+ */
1177
+
1178
+ /** Rent GPU compute for `budget` TAO and run `spec`'s job; resolve with the raw output artifact. */
1179
+ type RunGpuJob = SubnetCall;
1180
+ /** Configuration and injectable ports for {@link createLiumAdapter}. */
1181
+ interface LiumAdapterConfig {
1182
+ /** Subnet identifier. Defaults to "sn51" (Lium GPU compute); forms the adapter id `bittensor:<subnet>`. */
1183
+ subnet?: string;
1184
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["gpu-compute"]`. */
1185
+ capabilities?: string[];
1186
+ /** μUSDC the worker allocates to a single task before converting to TAO (internal budgeting). */
1187
+ taskBudgetMicroUsdc?: number;
1188
+ /** Swap port. Default: a fixed-rate reference stub. */
1189
+ swap?: UsdcToTaoSwap;
1190
+ /** GPU-job port. Default: runs the canned demo job; a deterministic placeholder otherwise. */
1191
+ runJob?: RunGpuJob;
1192
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1193
+ pin?: PinContent$3;
1194
+ /** Health-check port. Default: resolves `true`. */
1195
+ checkHealth?: () => Promise<boolean>;
1196
+ }
1197
+ declare const LIUM_ADAPTER_ID = "bittensor:sn51";
1198
+ declare const LIUM_CAPABILITIES: readonly ["gpu-compute"];
1199
+ /** Stable marker on the demo spec's metadata so the default job stub recognizes it. */
1200
+ declare const LIUM_DEMO_MARKER = "lium-sn51-demo-v1";
1201
+ /** The demo accept floor: hash-match is exact, so the buyer requires a full match. */
1202
+ declare const LIUM_DEMO_ACCEPT_FLOOR = 1;
1203
+ /**
1204
+ * The scripted GPU job's deterministic output artifact: a hash chain over the fixed
1205
+ * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.
1206
+ */
1207
+ declare function computeLiumDemoArtifact(): string;
1208
+ /**
1209
+ * The canned Lium demo job. Deterministic; its specHash is pinned by a test (consult
1210
+ * C8) because the buyer journey depends on hash stability.
1211
+ */
1212
+ declare const liumDemoJobSpec: TaskSpec;
1213
+ /**
1214
+ * The reference solution to the demo job: the completed job report carrying the
1215
+ * correct output artifact plus a (self-reported, buyer-ignored) artifactHash, as
1216
+ * canonical JSON. Deterministic. Exposed so the demo journey and tests share one
1217
+ * source of the expected artifact.
1218
+ */
1219
+ declare function solveLiumDemo(): string;
1220
+ /**
1221
+ * The BUYER's independent recompute of the demo acceptance predicate, returning 1
1222
+ * when the deliverable satisfies all three criteria and 0 otherwise. It checks
1223
+ * completion (status), artifact presence, and hash match by RECOMPUTING the scripted
1224
+ * job's output and comparing the substantive artifact; it deliberately IGNORES any
1225
+ * self-reported `artifactHash`, so release can never be worker-controlled (consult
1226
+ * C10). Malformed or unparseable content scores 0 and never throws.
1227
+ */
1228
+ declare function scoreLiumDemoDeliverable(content: string | Buffer): number;
1229
+ /**
1230
+ * Build a Lium (SN51) {@link ServiceAdapter}. Passes `assertServiceAdapterContract`
1231
+ * with the default ports; supply real ports for production use. The USDC->TAO swap,
1232
+ * pinning, and execute skeleton come from the shared Bittensor core; the GPU-rental
1233
+ * port is wired in as the core's `callSubnet`.
1234
+ */
1235
+ declare function createLiumAdapter(config?: LiumAdapterConfig): ServiceAdapter;
1236
+
1237
+ /**
1238
+ * Amount denominated in AKT (Akash's token). Branded so it cannot be assigned to or from a
1239
+ * plain `number` by accident and (the point of the brand) so it can never appear in a
1240
+ * `ServiceResult` or the escrow submit path: those types have no field of this type. AKT
1241
+ * exists ONLY inside the Akash adapter layer.
1242
+ */
1243
+ type Akt = number & {
1244
+ readonly __brand: "AKT";
1245
+ };
1246
+ /** Construct an {@link Akt} amount from a plain number. Adapter-internal use only. */
1247
+ declare function akt(amount: number): Akt;
1248
+ /** Swap a microUSDC budget into AKT. Real workers route this through a DEX/CEX. */
1249
+ type UsdcToAktSwap = (microUsdc: number) => Promise<Akt>;
1250
+ /**
1251
+ * Provision an Akash deployment/lease funded with `budget` AKT to run `spec`; resolve with
1252
+ * the raw deliverable (the job's output artifact).
1253
+ */
1254
+ type RunAkashDeployment = (spec: TaskSpec, budget: Akt) => Promise<string | Buffer>;
1255
+ /** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */
1256
+ type PinContent$1 = (content: string | Buffer) => Promise<string>;
1257
+ /**
1258
+ * Stable id/capabilities. The adapter's own tests pin its runtime output to these
1259
+ * constants; the EscroBots registry descriptor for `akash` is registered separately in
1260
+ * P8.T6 (capability taxonomy extension).
1261
+ */
1262
+ declare const AKASH_ADAPTER_ID = "akash";
1263
+ declare const AKASH_CAPABILITIES: readonly ["cloud-compute"];
1264
+ declare const REFERENCE_MICRO_USDC_PER_AKT = 3000000;
1265
+ /** Configuration and injectable ports for {@link createAkashAdapter}. */
1266
+ interface AkashAdapterConfig {
1267
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["cloud-compute"]`. */
1268
+ capabilities?: string[];
1269
+ /** μUSDC the worker allocates to a single task before converting to AKT (internal budgeting). */
1270
+ taskBudgetMicroUsdc?: number;
1271
+ /** Swap port. Default: a fixed-rate reference stub. */
1272
+ swap?: UsdcToAktSwap;
1273
+ /** Deployment port. Default: runs the canned demo job; a deterministic placeholder otherwise. */
1274
+ runDeployment?: RunAkashDeployment;
1275
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1276
+ pin?: PinContent$1;
1277
+ /** Health-check port. Default: resolves `true`. */
1278
+ checkHealth?: () => Promise<boolean>;
1279
+ }
1280
+ /** Stable marker on the demo spec's metadata so the default deployment stub recognizes it. */
1281
+ declare const AKASH_DEMO_MARKER = "akash-demo-v1";
1282
+ /** The demo accept floor: hash-match is exact, so the buyer requires a full match. */
1283
+ declare const AKASH_DEMO_ACCEPT_FLOOR = 1;
1284
+ /**
1285
+ * The scripted batch job's deterministic output artifact: a hash chain over the fixed
1286
+ * seed. Deterministic and cheap to recompute, so the buyer can verify it independently.
1287
+ */
1288
+ declare function computeAkashDemoArtifact(): string;
1289
+ /**
1290
+ * The canned Akash demo job. Deterministic; its specHash is pinned by a test because the
1291
+ * buyer journey depends on hash stability.
1292
+ */
1293
+ declare const akashDemoJobSpec: TaskSpec;
1294
+ /**
1295
+ * The reference solution to the demo job: the completed job report carrying the correct
1296
+ * output artifact plus a (self-reported, buyer-ignored) artifactHash, as canonical JSON.
1297
+ * Deterministic. Exposed so the demo journey and tests share one source of the expected
1298
+ * artifact.
1299
+ */
1300
+ declare function solveAkashDemo(): string;
1301
+ /**
1302
+ * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when the
1303
+ * deliverable satisfies all three criteria and 0 otherwise. It checks completion (status),
1304
+ * artifact presence, and hash match by RECOMPUTING the scripted job's output and comparing
1305
+ * the substantive artifact; it deliberately IGNORES any self-reported `artifactHash`, so
1306
+ * release can never be worker-controlled. Malformed or unparseable content scores 0 and
1307
+ * never throws.
1308
+ */
1309
+ declare function scoreAkashDemoDeliverable(content: string | Buffer): number;
1310
+ /**
1311
+ * Build an Akash {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the
1312
+ * default ports; supply real ports for production use. The execute skeleton: swap the USDC
1313
+ * budget into AKT (internal, never surfaced), provision the deployment and collect the
1314
+ * output, then hash and pin. The recorded `ServiceResult` is currency-free (no AKT field).
1315
+ */
1316
+ declare function createAkashAdapter(config?: AkashAdapterConfig): ServiceAdapter;
1317
+
1318
+ /**
1319
+ * Amount denominated in RENDER (Render Network's Solana SPL token). Branded so it cannot
1320
+ * be assigned to or from a plain `number` by accident and (the point of the brand) so it
1321
+ * can never appear in a `ServiceResult` or the escrow submit path: those types have no
1322
+ * field of this type. RENDER exists ONLY inside this adapter module.
1323
+ */
1324
+ type Render = number & {
1325
+ readonly __brand: "RENDER";
1326
+ };
1327
+ /** Construct a {@link Render} amount from a plain number. Adapter-internal use only. */
1328
+ declare function renderAmount(amount: number): Render;
1329
+ /** Swap a microUSDC budget into RENDER. Real workers route this through a Solana DEX (e.g. Jupiter). */
1330
+ type UsdcToRenderSwap = (microUsdc: number) => Promise<Render>;
1331
+ /** Submit `spec`'s render job funded with `budget` RENDER; resolve with the raw rendered artifact. */
1332
+ type RunRenderJob = (spec: TaskSpec, budget: Render) => Promise<string | Buffer>;
1333
+ /** Pin `content` and resolve with a content-addressed proof URI (ipfs://, ar://). */
1334
+ type PinContent = (content: string | Buffer) => Promise<string>;
1335
+ /** Configuration and injectable ports for {@link createRenderAdapter}. */
1336
+ interface RenderAdapterConfig {
1337
+ /** Service identifier. Defaults to "render"; forms the adapter id. */
1338
+ service?: string;
1339
+ /** Advertised capabilities for EscroBots discovery. Defaults to {@link RENDER_CAPABILITIES}. */
1340
+ capabilities?: string[];
1341
+ /** microUSDC the worker allocates to a single task before converting to RENDER (internal budgeting). */
1342
+ taskBudgetMicroUsdc?: number;
1343
+ /** Swap port. Default: a fixed-rate reference stub (no live price feed). */
1344
+ swap?: UsdcToRenderSwap;
1345
+ /** Render-job port. Default: renders the canned demo scene; a deterministic placeholder otherwise. */
1346
+ runJob?: RunRenderJob;
1347
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1348
+ pin?: PinContent;
1349
+ /** Health-check port. Default: resolves `true`. */
1350
+ checkHealth?: () => Promise<boolean>;
1351
+ }
1352
+ declare const RENDER_ADAPTER_ID = "render";
1353
+ declare const RENDER_CAPABILITIES: readonly ["3d-rendering", "video-rendering", "gpu-inference"];
1354
+ declare const REFERENCE_MICRO_USDC_PER_RENDER = 2000000;
1355
+ /** Stable marker on the demo spec's metadata so the default job stub recognizes it. */
1356
+ declare const RENDER_DEMO_MARKER = "render-demo-v1";
1357
+ /** The demo accept floor: frame-match is exact, so the buyer requires a full match. */
1358
+ declare const RENDER_DEMO_ACCEPT_FLOOR = 1;
1359
+ /**
1360
+ * Render the fixed demo scene into a grayscale raster and return its hex encoding.
1361
+ * Deterministic and cheap to recompute, so the buyer verifies the frame independently.
1362
+ */
1363
+ declare function computeRenderDemoArtifact(): string;
1364
+ /**
1365
+ * The canned Render demo job. Deterministic; its specHash is pinned by a test because
1366
+ * the buyer journey depends on hash stability.
1367
+ */
1368
+ declare const renderDemoJobSpec: TaskSpec;
1369
+ /**
1370
+ * The reference solution to the demo job: the completed job report carrying the correct
1371
+ * rendered frame plus a (self-reported, buyer-ignored) frameHash, as canonical JSON.
1372
+ * Deterministic. Exposed so the demo journey and tests share one source of the expected
1373
+ * artifact.
1374
+ */
1375
+ declare function solveRenderDemo(): string;
1376
+ /**
1377
+ * The BUYER's independent recompute of the demo acceptance predicate, returning 1 when
1378
+ * the deliverable satisfies all three criteria and 0 otherwise. It checks completion
1379
+ * (status), frame presence, and a frame match by RE-RENDERING the scripted scene and
1380
+ * comparing the substantive frame; it deliberately IGNORES any self-reported
1381
+ * `frameHash`, so release can never be worker-controlled (consult C10). Malformed or
1382
+ * unparseable content scores 0 and never throws.
1383
+ */
1384
+ declare function scoreRenderDemoDeliverable(content: string | Buffer): number;
1385
+ /**
1386
+ * Build a Render {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the
1387
+ * default ports; supply real ports for production use. The execute skeleton: swap the
1388
+ * USDC budget into RENDER (internal, same-chain, never surfaced), pay the render job in
1389
+ * RENDER and collect the frame, then hash and pin. The recorded `ServiceResult` is
1390
+ * currency-free (no RENDER field).
1391
+ */
1392
+ declare function createRenderAdapter(config?: RenderAdapterConfig): ServiceAdapter;
1393
+
1394
+ /** Stable adapter identity + EscroBots capability (locked by gensyn.test.ts). */
1395
+ declare const GENSYN_ADAPTER_ID = "gensyn";
1396
+ declare const GENSYN_CAPABILITIES: readonly ["verifiable-compute"];
1397
+ /** REE proof scheme tag. A verifier accepts only proofs carrying this exact scheme. */
1398
+ declare const GENSYN_REE_SCHEME = "gensyn-ree-v1";
1399
+ /** Marker on the demo spec's metadata so the default reproducible compute recognizes it. */
1400
+ declare const GENSYN_DEMO_MARKER = "gensyn-ree-demo-v1";
1401
+ /** The result of one reproducible execution: its transcript and final output. */
1402
+ interface ReeExecution {
1403
+ /** Seed the walk started from. */
1404
+ seed: number;
1405
+ /** Number of steps walked. */
1406
+ steps: number;
1407
+ /** Ordered per-step states (the execution transcript). */
1408
+ states: number[];
1409
+ /** Final state (the deliverable's numeric result). */
1410
+ result: number;
1411
+ }
1412
+ /** Run the reproducible compute for `spec`, deriving the transcript and result. */
1413
+ type ReproduceCompute = (spec: TaskSpec) => ReeExecution;
1414
+ /**
1415
+ * The reference reproducible execution. Deterministic from `spec` (its seed/steps
1416
+ * come from `spec.metadata`, defaulting to the demo parameters), so both worker and
1417
+ * buyer derive the same transcript.
1418
+ */
1419
+ declare const reproduceGensynCompute: ReproduceCompute;
1420
+ /**
1421
+ * A Gensyn REE proof. Every field is a commitment the buyer re-derives:
1422
+ * `commitment` binds the whole tuple, `outputHash` binds the delivered content,
1423
+ * `specHash` binds the task asked, `transcriptHash` binds the reproducible run.
1424
+ */
1425
+ interface ReeProof {
1426
+ scheme: typeof GENSYN_REE_SCHEME;
1427
+ /** SHA-256 hex of the canonical task spec. */
1428
+ specHash: string;
1429
+ /** SHA-256 hex of the delivered content. */
1430
+ outputHash: string;
1431
+ /** Number of reproducible execution steps (positive integer). */
1432
+ steps: number;
1433
+ /** SHA-256 hex of the canonical execution transcript. */
1434
+ transcriptHash: string;
1435
+ /** SHA-256 hex binding scheme, specHash, outputHash, steps, and transcriptHash. */
1436
+ commitment: string;
1437
+ }
1438
+ /**
1439
+ * Build the REE proof a worker attaches to its deliverable. Not a trust anchor on
1440
+ * its own: `verifyReeProof` re-derives every field, so a proof only accepts when it
1441
+ * genuinely binds the content, spec, and a reproducible transcript.
1442
+ */
1443
+ declare function buildReeProof(spec: TaskSpec, exec: ReeExecution, content: string | Buffer): ReeProof;
1444
+ /** The verifier's verdict: a proof is either valid, or invalid/malformed with a reason. */
1445
+ interface ReeVerification {
1446
+ valid: boolean;
1447
+ /** Prefixed `malformed` (shape/structure) or `invalid` (a binding failed), or a pass note. */
1448
+ reason: string;
1449
+ }
1450
+ /** Inputs the buyer verifies a proof against: the task asked and the content received. */
1451
+ interface ReeVerifyContext {
1452
+ /** The task spec the buyer commissioned. */
1453
+ spec: TaskSpec;
1454
+ /** The deliverable content the buyer received (fetched from proofUri in production). */
1455
+ content: string | Buffer;
1456
+ /** The reproducible compute; defaults to the reference {@link reproduceGensynCompute}. */
1457
+ reproduce?: ReproduceCompute;
1458
+ }
1459
+ /**
1460
+ * The BUYER's verification of an REE proof (untrusted input from the worker). Returns
1461
+ * `valid: true` only when the proof is well-formed AND every binding holds: the
1462
+ * commitment is self-consistent, the committed output hash equals the delivered
1463
+ * content, the spec hash equals the commissioned task, and the transcript hash
1464
+ * matches the buyer's own reproduction of the execution. Never throws.
1465
+ */
1466
+ declare function verifyReeProof(proof: unknown, ctx: ReeVerifyContext): ReeVerification;
1467
+ /** What the buyer assembles to decide acceptance: the received content and the worker's proof. */
1468
+ interface GensynDeliverableBundle {
1469
+ /** The deliverable content the buyer received. */
1470
+ content: string | Buffer;
1471
+ /** The REE proof the worker attached (untrusted; verified before any release). */
1472
+ proof: unknown;
1473
+ }
1474
+ /** A buyer auto-release decision. `release: true` means "call release_payment()". */
1475
+ interface AutoReleaseDecision {
1476
+ release: boolean;
1477
+ reason: string;
1478
+ }
1479
+ /**
1480
+ * The buyer bot's auto-release decision for a Gensyn deliverable. Releases ONLY when
1481
+ * the REE proof verifies against the delivered content and the commissioned spec;
1482
+ * an invalid or malformed proof never releases. This is the whole T4 acceptance
1483
+ * mechanism, and it lives entirely at the buyer layer.
1484
+ */
1485
+ declare function gensynAutoRelease(bundle: GensynDeliverableBundle, ctx: {
1486
+ spec: TaskSpec;
1487
+ reproduce?: ReproduceCompute;
1488
+ }): AutoReleaseDecision;
1489
+ /** Configuration and injectable ports for {@link createGensynAdapter}. */
1490
+ interface GensynAdapterConfig {
1491
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["verifiable-compute"]`. */
1492
+ capabilities?: string[];
1493
+ /** The reproducible compute the worker runs. Default: the reference LCG walk. */
1494
+ runCompute?: ReproduceCompute;
1495
+ /** Pinning port. Default: a deterministic `ipfs://` placeholder URI. */
1496
+ pin?: (content: string | Buffer) => Promise<string>;
1497
+ /** Health-check port. Default: resolves `true`. */
1498
+ checkHealth?: () => Promise<boolean>;
1499
+ }
1500
+ /** The canned demo job the buyer template's journey hires a Gensyn worker for. */
1501
+ declare const gensynDemoJobSpec: TaskSpec;
1502
+ /**
1503
+ * Build a Gensyn {@link ServiceAdapter}. `execute` runs the reproducible compute,
1504
+ * serializes the deliverable, and attaches an REE proof (in `metadata.reeProof`) the
1505
+ * buyer verifies with {@link verifyReeProof} / {@link gensynAutoRelease}. Passes
1506
+ * `assertServiceAdapterContract` with the default ports; supply real ports (a real
1507
+ * Gensyn job runner, a real pinner) for production.
1508
+ */
1509
+ declare function createGensynAdapter(config?: GensynAdapterConfig): ServiceAdapter;
1510
+
1511
+ /** Stable id/capabilities; locked against the EscroBots registry descriptor by a kit test at merge (consult C2). */
1512
+ declare const ZKML_ADAPTER_ID = "zkml";
1513
+ declare const ZKML_CAPABILITIES: readonly ["zk-verified-inference"];
1514
+ /** Marker on the demo spec's metadata so the default inference port recognizes it. */
1515
+ declare const ZKML_DEMO_MARKER = "zkml-demo-v1";
1516
+ /** The reference proving scheme this verifier understands. Unknown schemes are malformed to it. */
1517
+ declare const ZKML_PROOF_SCHEME = "escro-zkml-ref-v1";
1518
+ /** Prefix marking an inline (self-contained) zkml proof URI: `zkml-proof:<base64url(json)>`. */
1519
+ declare const ZKML_PROOF_URI_PREFIX = "zkml-proof:";
1520
+ /**
1521
+ * A ZKML proof: its public inputs plus a `verificationTag` binding them. In the
1522
+ * reference scheme the tag is recomputable (see {@link computeZkmlVerificationTag});
1523
+ * in a production scheme it is a SNARK/STARK checked against a verifying key over the
1524
+ * same public inputs.
1525
+ */
1526
+ interface ZkmlProof {
1527
+ /** Proving scheme identifier; the verifier only understands {@link ZKML_PROOF_SCHEME}. */
1528
+ scheme: string;
1529
+ /** Commitment to the model that produced the output (e.g. a weights hash). */
1530
+ modelCommitment: string;
1531
+ /** Commitment to the input the model was run on. */
1532
+ inputCommitment: string;
1533
+ /** SHA-256 hex of the delivered output; binds the proof to a specific deliverable. */
1534
+ outputHash: string;
1535
+ /** Binding tag over the public inputs (reference: recomputable; production: a SNARK). */
1536
+ verificationTag: string;
1537
+ }
1538
+ /** Build a well-formed reference proof binding the given public inputs. */
1539
+ declare function buildZkmlProof(args: {
1540
+ scheme?: string;
1541
+ modelCommitment: string;
1542
+ inputCommitment: string;
1543
+ outputHash: string;
1544
+ }): ZkmlProof;
1545
+ /** Encode a proof as a self-contained inline proof URI. */
1546
+ declare function encodeZkmlProofUri(proof: ZkmlProof): string;
1547
+ /**
1548
+ * Decode an inline zkml proof URI back to a {@link ZkmlProof}. Returns null for any
1549
+ * URI that is not an inline zkml proof or does not decode to the proof shape (a
1550
+ * pinned `ipfs://`/`ar://` proof is fetched by the caller, then passed to
1551
+ * {@link verifyZkmlProof} directly).
1552
+ */
1553
+ declare function decodeZkmlProofUri(uri: string): ZkmlProof | null;
1554
+ /**
1555
+ * The outcome of verifying a proof. `malformed` = the verifier cannot understand the
1556
+ * proof (missing/wrong-typed fields, unsupported scheme, undecodable URI); `invalid`
1557
+ * = a well-formed proof that fails verification (tag does not recompute, or attests a
1558
+ * different output/model than expected).
1559
+ */
1560
+ type ZkmlVerification = {
1561
+ valid: true;
1562
+ } | {
1563
+ valid: false;
1564
+ category: "invalid" | "malformed";
1565
+ reason: string;
1566
+ };
1567
+ /** What the Buyer expects the proof to attest to. */
1568
+ interface ZkmlExpectation {
1569
+ /** The submitted deliverable's contentHash; the proof's outputHash must equal it. */
1570
+ contentHash: string;
1571
+ /** When set, the proof's modelCommitment must equal it (pin to a specific model). */
1572
+ modelCommitment?: string;
1573
+ }
1574
+ /**
1575
+ * Verify a decoded proof against the Buyer's expectation. NOTE: this is the REFERENCE
1576
+ * verifier and is NOT cryptographically sound -- the tag is a keyless hash, so a `valid`
1577
+ * result means only that the proof is internally consistent and bound to
1578
+ * `expected.contentHash`, not that a trustworthy party produced it. Pass a real verifier
1579
+ * to {@link zkmlProofAutoRelease} for production. `malformed` = an unusable proof;
1580
+ * `invalid` = a usable proof that fails the checks.
1581
+ */
1582
+ declare function verifyZkmlProof(proof: unknown, expected: ZkmlExpectation): ZkmlVerification;
1583
+ /** Decode an inline proof URI (or reject a missing/foreign one) and verify it. */
1584
+ declare function verifyZkmlProofUri(uri: string | null | undefined, expected: ZkmlExpectation): ZkmlVerification;
1585
+ /** The submitted deliverable as the Buyer's review reads it off the escrow read model. */
1586
+ interface ZkmlDeliverable {
1587
+ /**
1588
+ * SHA-256 hex the WORKER submitted on-chain (mirrored to the read model). It is the
1589
+ * worker's CLAIM about the artifact; {@link zkmlProofAutoRelease} re-hashes the real
1590
+ * artifact (via its `fetchContent` port) and never trusts this value on its own.
1591
+ */
1592
+ contentHash: string;
1593
+ /** URI where the ZK proof is (inline `zkml-proof:` or a pinned `ipfs://`), or null. */
1594
+ proofUri: string | null;
1595
+ }
1596
+ /** A release decision: release, and if not, whether to contest via dispute. */
1597
+ interface ZkmlReviewResult {
1598
+ accept: boolean;
1599
+ dispute: boolean;
1600
+ reason: string;
1601
+ }
1602
+ /**
1603
+ * A named release policy the Buyer's review wires in. Field-for-field this mirrors the
1604
+ * buyer template's `ReviewPolicy`
1605
+ * (packages/create-escro-bot/templates/buyer/src/review.ts). The SDK cannot import the
1606
+ * scaffolding templates, and promoting the shared review shapes into `@escro/shared` is
1607
+ * a cross-package change owned by `main`, not this lane -- tracked as a merge-time
1608
+ * follow-up (LANE-NOTES).
1609
+ */
1610
+ interface ZkmlReviewPolicy {
1611
+ name: string;
1612
+ evaluate(deliverable: ZkmlDeliverable): Promise<ZkmlReviewResult>;
1613
+ }
1614
+ /** Options for {@link zkmlProofAutoRelease}. */
1615
+ interface ZkmlProofAutoReleaseOptions {
1616
+ /**
1617
+ * Fetch the ACTUAL delivered artifact so the predicate can re-hash it. Integrity comes
1618
+ * from the buyer recomputing `sha256(artifact)` and requiring it equals the worker-
1619
+ * submitted `contentHash` -- never from trusting the submitted hash (mirror of the
1620
+ * buyer template's `evalThresholdReview`). Required: without the artifact the predicate
1621
+ * would be trusting a worker-chosen number.
1622
+ */
1623
+ fetchContent: (deliverable: ZkmlDeliverable) => Promise<string | Buffer> | string | Buffer;
1624
+ /** When set, the proof's modelCommitment must equal it (pin to a specific model). */
1625
+ modelCommitment?: string;
1626
+ /**
1627
+ * The proof verifier. DEFAULT is {@link verifyZkmlProof}, the reference verifier, which
1628
+ * is NOT cryptographically sound. A production buyer MUST pass a real SNARK/STARK
1629
+ * verifier here; the default is for demos only.
1630
+ */
1631
+ verify?: (proof: ZkmlProof, expected: ZkmlExpectation) => ZkmlVerification;
1632
+ /**
1633
+ * Resolve a non-inline (pinned) proof URI to a proof. Default: only inline
1634
+ * `zkml-proof:` URIs are understood; a pinned `ipfs://` proof needs this port.
1635
+ */
1636
+ fetchProof?: (uri: string) => Promise<ZkmlProof | null> | ZkmlProof | null;
1637
+ }
1638
+ /**
1639
+ * Buyer-layer auto-release predicate for zk-verified jobs. RELEASE only when BOTH hold:
1640
+ * (1) the delivered artifact re-hashes to the worker-submitted `contentHash` (fetched via
1641
+ * `fetchContent`, never trusted), and (2) the attached proof verifies against that buyer-
1642
+ * recomputed hash (and the pinned model, when given). Otherwise DISPUTE. Disputing rather
1643
+ * than holding is deliberate -- a held SUBMITTED escrow is auto-released to the worker by
1644
+ * the 24h protocol timeout, so a buyer who required a proof contests a missing/invalid one
1645
+ * instead of letting it time out to release. This is the Buyer's judgment, not the
1646
+ * protocol's. Soundness of step (2) lives in the `verify` option; the default reference
1647
+ * verifier is a demo and proves nothing on its own. A port that throws (e.g.
1648
+ * `fetchContent` failing to retrieve the artifact) PROPAGATES: a transient infra failure
1649
+ * is not a verdict, so the caller retries it -- it is never silently converted into a
1650
+ * dispute.
1651
+ */
1652
+ declare function zkmlProofAutoRelease(opts: ZkmlProofAutoReleaseOptions): ZkmlReviewPolicy;
1653
+ /** What an inference run yields: the output plus the commitments the proof binds. */
1654
+ interface ZkmlInferenceOutput {
1655
+ /** The deliverable content. */
1656
+ content: string;
1657
+ /** Commitment to the model that produced `content`. */
1658
+ modelCommitment: string;
1659
+ /** Commitment to the input the model was run on. */
1660
+ inputCommitment: string;
1661
+ }
1662
+ /** Configuration and injectable ports for {@link createZkmlAdapter}. */
1663
+ interface ZkmlAdapterConfig {
1664
+ /** Adapter id. Defaults to `"zkml"`. */
1665
+ id?: string;
1666
+ /** Advertised capabilities for EscroBots discovery. Defaults to `["zk-verified-inference"]`. */
1667
+ capabilities?: string[];
1668
+ /** Inference port. Default: solves the canned demo job; a deterministic placeholder otherwise. */
1669
+ runInference?: (spec: TaskSpec) => Promise<ZkmlInferenceOutput> | ZkmlInferenceOutput;
1670
+ /** Proving port. Default: builds a reference proof binding the output to its commitments. */
1671
+ prove?: (args: {
1672
+ spec: TaskSpec;
1673
+ output: ZkmlInferenceOutput;
1674
+ outputHash: string;
1675
+ }) => Promise<ZkmlProof> | ZkmlProof;
1676
+ /** Pinning port. Default: a self-contained inline proof URI. A production worker pins the proof. */
1677
+ pin?: (proof: ZkmlProof) => Promise<string> | string;
1678
+ /** Health-check port. Default: resolves `true`. */
1679
+ checkHealth?: () => Promise<boolean>;
1680
+ }
1681
+ /**
1682
+ * The canned zk-verified-inference demo job (BOT_KIT_PRD §6 / §13): a deterministic
1683
+ * classification the buyer template's zero-config journey hires this bot for.
1684
+ * Acceptance is machine-checkable by the buyer via {@link zkmlProofAutoRelease}.
1685
+ */
1686
+ declare const zkmlDemoJobSpec: TaskSpec;
1687
+ /**
1688
+ * The reference solution to the demo job: the classifier's output as canonical JSON.
1689
+ * Deterministic. Exposed so the demo journey and tests share one source of truth.
1690
+ */
1691
+ declare function solveZkmlDemo(): string;
1692
+ /**
1693
+ * Build a ZKML {@link ServiceAdapter}. Passes `assertServiceAdapterContract` with the
1694
+ * default ports and, out of the box, produces a demo deliverable whose proof verifies
1695
+ * under {@link zkmlProofAutoRelease}. Supply real ports (a genuine inference call, a
1696
+ * real prover, a pin to IPFS/Arweave) for production use.
1697
+ */
1698
+ declare function createZkmlAdapter(config?: ZkmlAdapterConfig): ServiceAdapter;
169
1699
 
170
- export { type CreateEscrowParams, type CreateEscrowResult, Escro, EscroError, type EscroOptions, EscrowNotFoundError, EscrowStateError, EscrowTimeoutError, type ListOptions, type PaginatedResult, type PollOptions, type RaiseDisputeParams, type SubmitDeliverableParams, UnauthorizedError };
1700
+ export { AKASH_ADAPTER_ID, AKASH_CAPABILITIES, AKASH_DEMO_ACCEPT_FLOOR, AKASH_DEMO_MARKER, type AcceptanceCriterion, AdapterContractError, type AdapterContractOptions, type AkashAdapterConfig, type Akt, ApiClient, type AutoReleaseDecision, type BotDescriptor, type BotRole, type CreateEscrowParams, type CreateEscrowResult, type DeliverableFormat, type DeliverableType, ENABLED_RAILS, Escro, EscroError, type EscroOptions, EscroRailNotEnabledError, type EscrowAccount, type EscrowErrorCode, EscrowNotFoundError, EscrowPaymentRouter, EscrowState, EscrowStateError, EscrowTimeoutError, 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, type Gen404AdapterConfig, type GensynAdapterConfig, type GensynDeliverableBundle, type GradientsAdapterConfig, LIUM_ADAPTER_ID, LIUM_CAPABILITIES, LIUM_DEMO_ACCEPT_FLOOR, LIUM_DEMO_MARKER, type ListBotsParams, type ListOptions, type LiumAdapterConfig, type Network, type PaginatedResult, type PayParams, type PaymentResult, type PaymentRouter, type PinContent$3 as PinContent, type PollOptions, type ProtocolStats, 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, type Rail, type RaiseDisputeParams, type ReeExecution, type ReeProof, type ReeVerification, type ReeVerifyContext, type Render, type RenderAdapterConfig, type ReproduceCompute, ReputationUnavailableError, type RidgesAdapterConfig, type RunAkashDeployment, type RunCodingAgent, type RunGpuJob, type RunRenderJob, type ServedWalletReputation, type ServiceAdapter, type ServiceResult, type SubmitDeliverableParams, type SubnetCall, type Tao, type TaskSpec, type TaskType, type TxShape, UnauthorizedError, type UnsignedBotDescriptor, type UsdcToAktSwap, type UsdcToRenderSwap, type UsdcToTaoSwap, type WorkerCandidate, ZKML_ADAPTER_ID, ZKML_CAPABILITIES, ZKML_DEMO_MARKER, ZKML_PROOF_SCHEME, ZKML_PROOF_URI_PREFIX, type ZkmlAdapterConfig, type ZkmlDeliverable, type ZkmlExpectation, type ZkmlInferenceOutput, type ZkmlProof, type ZkmlProofAutoReleaseOptions, type ZkmlReviewPolicy, type ZkmlReviewResult, type ZkmlVerification, akashDemoJobSpec, akt, assertServiceAdapterContract, buildReeProof, buildZkmlProof, computeAkashDemoArtifact, computeLiumDemoArtifact, computeRenderDemoArtifact, create404genAdapter, createAkashAdapter, createGensynAdapter, createGradientsAdapter, createLiumAdapter, createRenderAdapter, createRidgesAdapter, createZkmlAdapter, decodeZkmlProofUri, encodeZkmlProofUri, gen404DemoJobSpec, gensynAutoRelease, gensynDemoJobSpec, gradientsDemoJobSpec, liumDemoJobSpec, renderAmount, renderDemoJobSpec, reproduceGensynCompute, ridgesDemoJobSpec, score404genDemoDeliverable, scoreAkashDemoDeliverable, scoreGradientsDemoDeliverable, scoreLiumDemoDeliverable, scoreRenderDemoDeliverable, scoreRidgesDemoDeliverable, serviceResultToSubmitParams, solveAkashDemo, solveGen404Demo, solveGradientsDemo, solveLiumDemo, solveRenderDemo, solveRidgesDemo, solveZkmlDemo, tao, verifyReeProof, verifyZkmlProof, verifyZkmlProofUri, zkmlDemoJobSpec, zkmlProofAutoRelease };