@blindmarket/sdk 0.8.0 → 0.9.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.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { ApiError } from './apiError.js';
3
+ import { type SettlementPin } from './settlementPins.js';
3
4
  import type { Address, Hex, RootHash, HealthStatus, PlatformStats, OpenTask, TaskDetail, CreateTaskTx, ExecutorProfile, RegisterExecutorInput, DeployedAgentInfo, AgentWalletInfo, ReputationInfo, LeaderboardEntry, StorageUploadResult, Message, AgentSearchResult, TaskTemplate, VerifyTaskInput, A2ATaskEntry, AgentCapability, CreateAgentParams, CreateAgentResult, CreateTaskRequest } from './types.js';
4
5
  export interface BlindMarketConfig {
5
6
  /** Backend API base URL (default: https://api.blindmarket.xyz) */
@@ -13,6 +14,14 @@ export interface BlindMarketConfig {
13
14
  * never take a key as an argument. Stays in-process; never sent to the backend.
14
15
  */
15
16
  executor?: DeliverSigner;
17
+ /**
18
+ * Escrows postTask() and postTasks() may fund besides the known
19
+ * deployments (SETTLEMENT_PINS: Arc mainnet and Arc Testnet), for a custom
20
+ * or local deployment. Each names its chain id, escrow and settlement
21
+ * token; the backend's /health/settlement must name exactly one of them, or
22
+ * nothing is approved or funded (ESCROW_NOT_PINNED).
23
+ */
24
+ trustedEscrows?: SettlementPin[];
16
25
  }
17
26
  export interface DeployAgentParams {
18
27
  name: string;
@@ -141,6 +150,12 @@ export interface PostTaskParams {
141
150
  targetExecutor?: Address;
142
151
  /** Default 'global'. */
143
152
  locationZone?: string;
153
+ /**
154
+ * A public one-liner shown on the task board, at most 500 characters. A
155
+ * private task's brief is sealed, so this is what the board says it is
156
+ * about: keep secrets out of it.
157
+ */
158
+ routingSummary?: string;
144
159
  }
145
160
  export interface PostTaskOptions {
146
161
  /**
@@ -162,6 +177,8 @@ export interface PostTaskOptions {
162
177
  */
163
178
  onFunded?: (funding: {
164
179
  txHash: string;
180
+ nonce: number;
181
+ raw?: string;
165
182
  taskHash: string;
166
183
  indexParams: IndexTaskParams;
167
184
  }) => void | Promise<void>;
@@ -200,6 +217,168 @@ export interface IndexTaskParams {
200
217
  verifierAddress?: Address;
201
218
  requiredCapabilities?: AgentCapability[];
202
219
  targetExecutor?: Address;
220
+ routingSummary?: string;
221
+ }
222
+ export interface PostTasksOptions {
223
+ /** As postTask(): signs on the posting chain instead of the configured executor, and must be the API key's own wallet. */
224
+ signer?: ethers.Signer;
225
+ /**
226
+ * The most postTasks() will lock in escrow across every row, in the
227
+ * token's smallest unit. Refused with AMOUNT_ABOVE_MAX before anything is sent.
228
+ */
229
+ maxTotalRaw?: bigint | string;
230
+ /**
231
+ * Tasks per transaction on an escrow that has createTasks (SettlementChainInfo.batchCreate).
232
+ * Default 20, at most the chain's maxBatch and 50. On an escrow without
233
+ * it every task is its own transaction and this is ignored.
234
+ */
235
+ chunkSize?: number;
236
+ /** Called as each row settles: posted, unlisted, failed or skipped. A throwing callback does not stop the run. */
237
+ onProgress?: (progress: {
238
+ done: number;
239
+ total: number;
240
+ result: PostTasksRowResult;
241
+ }) => void | Promise<void>;
242
+ /**
243
+ * Called the moment a funding transaction is broadcast, once for every row
244
+ * it funds. Persist `indexParams`: if this process dies before the row is
245
+ * listed, indexTask(indexParams) lists it without funding it again, or
246
+ * indexTasks() for rows whose `batch` is true, which share one transaction
247
+ * (the single index route refuses a receipt that funded several tasks).
248
+ */
249
+ onFunded?: (funding: {
250
+ index: number;
251
+ txHash: string;
252
+ nonce: number;
253
+ raw?: string;
254
+ taskHash: string;
255
+ batch: boolean;
256
+ indexParams: IndexTaskParams;
257
+ }) => void | Promise<void>;
258
+ /** How long to wait for each transaction to confirm. Default 180000 ms. */
259
+ confirmTimeoutMs?: number;
260
+ /**
261
+ * Stops the run before the next row, or the next transaction of rows; a
262
+ * transaction already sent is always seen through to its listing. Rows not
263
+ * started come back 'skipped'.
264
+ */
265
+ signal?: AbortSignal;
266
+ /**
267
+ * Backoff for a rate limit (429), a 5xx or a network error on a read, an
268
+ * upload, a build or a listing: `attempts` tries in all (default 5), the
269
+ * wait doubling from `baseDelayMs` (default 2000). A funding transaction is
270
+ * never sent twice.
271
+ */
272
+ retry?: {
273
+ attempts?: number;
274
+ baseDelayMs?: number;
275
+ };
276
+ }
277
+ /** A row that cannot be posted as it is, from postTasks()' checks before anything is sent (ApiError INVALID_ROWS, `body.errors`). */
278
+ export interface PostTasksRowError {
279
+ /** The row's position in the array passed to postTasks(). */
280
+ index: number;
281
+ code: string;
282
+ message: string;
283
+ }
284
+ /** What happened to one row of postTasks(), by its position in the input. */
285
+ export type PostTasksRowResult =
286
+ /** Funded and listed. */
287
+ {
288
+ index: number;
289
+ status: 'posted';
290
+ task: PostedTask;
291
+ }
292
+ /**
293
+ * Funded (or sent and maybe funded, with code UNCONFIRMED) but not listed.
294
+ * Do not post it again: list it with indexTask(indexParams), or with
295
+ * indexTasks() when `batch` is true, or cancel it for a refund.
296
+ */
297
+ | {
298
+ index: number;
299
+ status: 'unlisted';
300
+ taskHash: string;
301
+ txHash: string;
302
+ batch: boolean;
303
+ indexParams: IndexTaskParams;
304
+ aesKey?: string;
305
+ error: {
306
+ code?: string;
307
+ message: string;
308
+ };
309
+ }
310
+ /** Nothing was funded for this row. */
311
+ | {
312
+ index: number;
313
+ status: 'failed';
314
+ error: {
315
+ code?: string;
316
+ message: string;
317
+ };
318
+ }
319
+ /** Not started: the run was aborted, or stopped at an earlier row. */
320
+ | {
321
+ index: number;
322
+ status: 'skipped';
323
+ reason: string;
324
+ };
325
+ export interface PostTasksResult {
326
+ chain: string;
327
+ chainId: number;
328
+ /** 'batch': createTasks, several tasks per transaction. 'single': one createTask per task. */
329
+ mode: 'batch' | 'single';
330
+ /** One per input row, in input order. */
331
+ results: PostTasksRowResult[];
332
+ posted: number;
333
+ unlisted: number;
334
+ failed: number;
335
+ skipped: number;
336
+ /**
337
+ * Why the run stopped before the last row, when it did: an on-chain or
338
+ * listing failure (so no further escrow is funded behind it), a backend
339
+ * that built the wrong transaction, one that stayed unreachable, or the abort signal.
340
+ */
341
+ stopped?: {
342
+ index: number;
343
+ code?: string;
344
+ message: string;
345
+ };
346
+ }
347
+ /** POST /api/v1/tasks/batch: several posts built into one createTasks transaction. */
348
+ export interface CreateTasksRequest {
349
+ token: Address;
350
+ tasks: Array<Omit<CreateTaskRequest, 'token'>>;
351
+ }
352
+ export interface CreateTasksTx {
353
+ unsignedTx: {
354
+ to: Address;
355
+ data: Hex;
356
+ value?: string;
357
+ from?: Address;
358
+ };
359
+ chain?: string;
360
+ chainId?: number;
361
+ /** The task hashes the transaction escrows, in order. */
362
+ taskHashes?: string[];
363
+ }
364
+ /** POST /api/v1/a2a/tasks/index-batch: list the tasks one transaction funded. */
365
+ export interface IndexTasksParams {
366
+ txHash: string;
367
+ isUserOp?: boolean;
368
+ tasks: Array<Omit<IndexTaskParams, 'txHash'>>;
369
+ }
370
+ export interface IndexTasksResult {
371
+ results: Array<{
372
+ taskHash: string;
373
+ onChainTaskId?: string;
374
+ indexed: true;
375
+ } | {
376
+ taskHash: string;
377
+ error: {
378
+ code?: string;
379
+ message: string;
380
+ };
381
+ }>;
203
382
  }
204
383
  /** A refund the client signed and sent: cancelAndRefund() or reclaimAfterTimeout(). */
205
384
  export interface RefundResult {
@@ -239,6 +418,15 @@ export interface SettlementChainInfo {
239
418
  relayChain?: string | null;
240
419
  gasSymbol?: string;
241
420
  postable?: boolean;
421
+ /**
422
+ * Whether this chain's escrow has createTasks (several tasks in one
423
+ * transaction), and how many one call takes. Absent from older backends,
424
+ * which is the same as unsupported.
425
+ */
426
+ batchCreate?: {
427
+ supported: boolean;
428
+ maxBatch: number;
429
+ };
242
430
  }
243
431
  /** Per-chain RPC URLs for signing `submitEvidence` — a task is escrowed on exactly one chain. */
244
432
  export interface DeliverSigner {
@@ -271,6 +459,7 @@ export declare class BlindMarket {
271
459
  private apiBase;
272
460
  private apiKey;
273
461
  private executor?;
462
+ private trustedEscrows;
274
463
  constructor(config: BlindMarketConfig);
275
464
  /** True when an executor signer was configured (see BlindMarketConfig.executor). */
276
465
  get canSign(): boolean;
@@ -300,6 +489,12 @@ export declare class BlindMarket {
300
489
  * generateText({ model, tools: tools(bb).vercel });
301
490
  * ```
302
491
  */
492
+ /**
493
+ * `timeoutMs` gives up on a request that has not answered (ApiError
494
+ * TIMEOUT). `strictBody` turns a reply that is not JSON (a gateway's error
495
+ * page, such as Cloudflare's 524) into an ApiError carrying its HTTP status,
496
+ * instead of the parser's SyntaxError.
497
+ */
303
498
  private req;
304
499
  /** Backend liveness check. */
305
500
  health(): Promise<HealthStatus>;
@@ -396,6 +591,109 @@ export declare class BlindMarket {
396
591
  * );
397
592
  */
398
593
  postTask(params: PostTaskParams, opts?: PostTaskOptions): Promise<PostedTask>;
594
+ /**
595
+ * Post many tasks, from the API key's own wallet: postTask() for a list, in
596
+ * as few transactions as the posting chain's escrow allows.
597
+ *
598
+ * Every row is checked and its brief sealed before anything is uploaded or
599
+ * sent: a row the escrow or the backend would refuse throws 400
600
+ * INVALID_ROWS listing every such row (`err.body.errors`), with nothing
601
+ * sent. The wallet must hold the total, and the escrow is approved for it
602
+ * once, just before the first funding transaction.
603
+ *
604
+ * On an escrow with createTasks (SettlementChainInfo.batchCreate) up to
605
+ * `chunkSize` rows share one transaction and one listing call; otherwise
606
+ * each row is its own createTask, as postTask() sends it. The same checks
607
+ * guard every transaction: the backend's build must be exactly these tasks,
608
+ * for this escrow and chain, before a key signs it.
609
+ *
610
+ * A row the backend refuses before funding fails alone and the run goes on.
611
+ * A funding transaction that reverts or cannot be confirmed, a listing that
612
+ * fails, or a backend that builds the wrong transaction or stays
613
+ * unreachable stops the run there (`result.stopped`), so no further escrow
614
+ * is funded behind a problem. Nothing is ever funded twice: a funded row
615
+ * that is not listed comes back 'unlisted' with its `indexParams`.
616
+ *
617
+ * @example
618
+ * const res = await bb.postTasks(rows, {
619
+ * onFunded: ({ taskHash, indexParams }) => save(taskHash, indexParams),
620
+ * onProgress: ({ done, total }) => console.log(`${done}/${total}`),
621
+ * });
622
+ */
623
+ postTasks(rows: PostTaskParams[], opts?: PostTasksOptions): Promise<PostTasksResult>;
624
+ /**
625
+ * Build and list several posts at once (POST /api/v1/tasks/batch): one
626
+ * unsigned createTasks transaction for the posting chain's escrow. Only an
627
+ * escrow with createTasks builds it (409 BATCH_UNSUPPORTED otherwise);
628
+ * postTasks() calls it, and checks the transaction before signing.
629
+ */
630
+ createTasks(params: CreateTasksRequest): Promise<CreateTasksTx>;
631
+ /**
632
+ * List every task one funding transaction created
633
+ * (POST /api/v1/a2a/tasks/index-batch). It works for a transaction that
634
+ * funded one task too. Each task comes back listed, or with its own error;
635
+ * a task the receipt does not hold is NOT_IN_RECEIPT. postTasks() calls it;
636
+ * call it yourself to finish rows it returned 'unlisted' with `batch` true.
637
+ */
638
+ indexTasks(params: IndexTasksParams): Promise<IndexTasksResult>;
639
+ /**
640
+ * Upload several blobs to 0G Storage in one call
641
+ * (POST /api/v1/storage/upload-batch). Each is base64, as uploadBlob()
642
+ * takes it; the results come back in the same order. All or nothing.
643
+ */
644
+ uploadBlobs(data: string[]): Promise<Array<{
645
+ rootHash: string;
646
+ txHash?: string;
647
+ }>>;
648
+ /** The posting chain, its escrow and token, and a signer checked to be the API key's own wallet on that chain. */
649
+ private postingContext;
650
+ /** Throws 402 INSUFFICIENT_BALANCE, with nothing sent, when the wallet holds less than `amount` of an ERC-20 settlement token. */
651
+ private assertCovers;
652
+ /** The executors on the posting chain a private brief can be wrapped to. */
653
+ private postingExecutors;
654
+ /**
655
+ * The backend's createTask, checked to be exactly this post before a key
656
+ * signs it: the chain and escrow checked above, the task hash, the token,
657
+ * the amount, the zone and the duration (a verifier commits through
658
+ * createTaskWithVerifier). Only its to and data are signed; the value is
659
+ * the amount computed here.
660
+ */
661
+ private checkedCreateCall;
662
+ /** The backend's createTasks, checked to be exactly these posts, in this order, for this token, escrow and chain. */
663
+ private checkedCreateTasksCall;
664
+ private postedTask;
665
+ /**
666
+ * The escrow's ERC-20 allowance for every row still to fund, approved once,
667
+ * right before the first funding transaction (after that transaction's
668
+ * build has been checked, as postTask() approves).
669
+ */
670
+ private approveRemaining;
671
+ /** Every row a transaction funds, told its hash (again with a replacement's hash if the wallet re-priced it). */
672
+ private notifyFunded;
673
+ /** One row as its own createTask, the way postTask() posts it. */
674
+ private postRow;
675
+ /** Several rows in one createTasks transaction, listed with one call. */
676
+ private postChunk;
677
+ /**
678
+ * Store briefs (base64) and return their root hashes, in order. Batched
679
+ * (upload-batch), they go UPLOAD_GROUP to a request, one request after the
680
+ * other; a group that fails transiently (isTransientUpload) is sent again
681
+ * one brief per request, each with the backoff, and a brief already stored
682
+ * comes back at once. Unbatched, each brief is one /storage/upload request
683
+ * with the backoff. A refusal (a 400) or an answer that does not add up
684
+ * fails at once.
685
+ */
686
+ private uploadBriefs;
687
+ /** One /storage/upload-batch request, checked to answer one root hash per brief. */
688
+ private uploadBatchRequest;
689
+ /** One /storage/upload request, as postTask() stores a brief. */
690
+ private uploadOneRequest;
691
+ /**
692
+ * `fn`, asked again after a rate limit, a 5xx or a network error (and, for
693
+ * a listing, while the backend's RPC has not seen the receipt), or after
694
+ * what `retryable` says is worth another try.
695
+ */
696
+ private retrying;
399
697
  /**
400
698
  * List a funded task on the market (`POST /api/v1/a2a/tasks/index`), from
401
699
  * its funding transaction. Safe to call again for the same task: the
@@ -867,6 +1165,8 @@ export declare class BlindMarket {
867
1165
  }
868
1166
  export { ethers };
869
1167
  export { ApiError };
1168
+ export { SETTLEMENT_PINS, isPinnedSettlement } from './settlementPins.js';
1169
+ export type { SettlementPin } from './settlementPins.js';
870
1170
  export { tools, createBlindMarketTools, createTaskTools, createAgentManagementTools, createA2ATools, toLangChainTools, toVercelTools, toOpenAITools, toClaudeTools, } from './tools/index.js';
871
1171
  export type { Tool, ToolKit, ToolDefinition } from './tools/types.js';
872
1172
  export type { BlindMarketTools } from './tools/index.js';