@blindmarket/sdk 0.1.6 → 0.1.8

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.
Files changed (156) hide show
  1. package/README.md +242 -29
  2. package/dist/chain/BlindEscrowClient.d.ts +2 -0
  3. package/dist/chain/BlindEscrowClient.js +19 -7
  4. package/dist/chain/BlindReputationClient.d.ts +3 -0
  5. package/dist/chain/BlindReputationClient.js +3 -1
  6. package/dist/chain/ChainClient.d.ts +6 -3
  7. package/dist/chain/ChainClient.js +6 -1
  8. package/dist/chain/IBlindMarketChain.d.ts +74 -0
  9. package/dist/chain/IBlindMarketChain.js +1 -0
  10. package/dist/chain/TaskRegistryClient.d.ts +2 -1
  11. package/dist/chain/TaskRegistryClient.js +15 -7
  12. package/dist/chain/createChainAdapter.d.ts +25 -0
  13. package/dist/chain/createChainAdapter.js +24 -0
  14. package/dist/chain/domain-types.d.ts +77 -0
  15. package/dist/chain/domain-types.js +1 -0
  16. package/dist/chain/evm/EVMChainAdapter.d.ts +56 -0
  17. package/dist/chain/evm/EVMChainAdapter.js +161 -0
  18. package/dist/chain/evm/index.d.ts +1 -0
  19. package/dist/chain/evm/index.js +1 -0
  20. package/dist/chain/index.d.ts +4 -0
  21. package/dist/chain/index.js +5 -0
  22. package/dist/crypto/constants.js +1 -1
  23. package/dist/errors/{BlindBountyError.d.ts → BlindMarketError.d.ts} +1 -1
  24. package/dist/errors/{BlindBountyError.js → BlindMarketError.js} +1 -1
  25. package/dist/errors/index.d.ts +1 -1
  26. package/dist/errors/index.js +1 -1
  27. package/dist/errors/subclasses.d.ts +9 -9
  28. package/dist/errors/subclasses.js +9 -9
  29. package/dist/executor/WorkerRuntime.d.ts +113 -0
  30. package/dist/executor/WorkerRuntime.js +248 -0
  31. package/dist/executor/index.d.ts +1 -0
  32. package/dist/executor/index.js +1 -0
  33. package/dist/index.d.ts +292 -22
  34. package/dist/index.js +413 -23
  35. package/dist/keystore/InMemoryKeyStore.js +2 -2
  36. package/dist/network/presets.d.ts +33 -5
  37. package/dist/network/presets.js +35 -8
  38. package/dist/network/resolve.d.ts +12 -3
  39. package/dist/network/resolve.js +15 -7
  40. package/dist/network/types.d.ts +3 -16
  41. package/dist/signer/EthersSigner.js +1 -1
  42. package/dist/storage/index.d.ts +0 -1
  43. package/dist/storage/index.js +1 -1
  44. package/dist/tools/adapters.d.ts +99 -0
  45. package/dist/tools/adapters.js +129 -0
  46. package/dist/tools/helpers.d.ts +9 -0
  47. package/dist/tools/helpers.js +169 -0
  48. package/dist/tools/index.d.ts +36 -0
  49. package/dist/tools/index.js +32 -0
  50. package/dist/tools/types.d.ts +44 -0
  51. package/dist/tools/types.js +1 -0
  52. package/dist/types.d.ts +202 -1
  53. package/dist/types.js +24 -1
  54. package/package.json +13 -2
  55. package/src/chain/BlindEscrowClient.ts +20 -6
  56. package/src/chain/BlindReputationClient.ts +6 -1
  57. package/src/chain/ChainClient.ts +9 -3
  58. package/src/chain/IBlindMarketChain.ts +109 -0
  59. package/src/chain/TaskRegistryClient.ts +17 -8
  60. package/src/chain/createChainAdapter.ts +40 -0
  61. package/src/chain/domain-types.ts +92 -0
  62. package/src/chain/evm/EVMChainAdapter.ts +212 -0
  63. package/src/chain/evm/index.ts +1 -0
  64. package/src/chain/index.ts +6 -0
  65. package/src/executor/WorkerRuntime.ts +338 -0
  66. package/src/executor/index.ts +8 -0
  67. package/src/index.ts +546 -36
  68. package/src/network/presets.ts +47 -8
  69. package/src/network/resolve.ts +20 -8
  70. package/src/network/types.ts +18 -16
  71. package/src/signer/index.ts +1 -1
  72. package/src/storage/index.ts +1 -1
  73. package/src/tools/adapters.ts +177 -0
  74. package/src/tools/helpers.ts +199 -0
  75. package/src/tools/index.ts +59 -0
  76. package/src/tools/types.ts +47 -0
  77. package/src/types.ts +222 -1
  78. package/tsconfig.json +2 -1
  79. package/dist/BlindEscrowClient-CyPuKMge.d.cts +0 -54
  80. package/dist/BlindEscrowClient-R7iGpE-n.d.ts +0 -54
  81. package/dist/KeyStore-Be_SSpCt.d.cts +0 -21
  82. package/dist/KeyStore-k1JgYPJY.d.ts +0 -21
  83. package/dist/Signer-BnqH_qew.d.cts +0 -38
  84. package/dist/Signer-LColE0Uo.d.ts +0 -38
  85. package/dist/Storage-4QOrh7rm.d.ts +0 -17
  86. package/dist/Storage-Cf4IJRMk.d.cts +0 -17
  87. package/dist/TaskRegistryClient-Ch6lYqM_.d.ts +0 -24
  88. package/dist/TaskRegistryClient-CrQjddDc.d.cts +0 -24
  89. package/dist/aes-J-7HrHze.d.cts +0 -17
  90. package/dist/aes-J-7HrHze.d.ts +0 -17
  91. package/dist/agent/index.cjs +0 -425
  92. package/dist/agent/index.cjs.map +0 -1
  93. package/dist/agent/index.d.cts +0 -63
  94. package/dist/agent/index.js.map +0 -1
  95. package/dist/api/index.cjs +0 -4
  96. package/dist/api/index.cjs.map +0 -1
  97. package/dist/api/index.d.cts +0 -2
  98. package/dist/api/index.js.map +0 -1
  99. package/dist/chain/index.cjs +0 -2484
  100. package/dist/chain/index.cjs.map +0 -1
  101. package/dist/chain/index.d.cts +0 -2305
  102. package/dist/chain/index.js.map +0 -1
  103. package/dist/compute/index.cjs +0 -4
  104. package/dist/compute/index.cjs.map +0 -1
  105. package/dist/compute/index.d.cts +0 -2
  106. package/dist/compute/index.js.map +0 -1
  107. package/dist/crypto/index.cjs +0 -424
  108. package/dist/crypto/index.cjs.map +0 -1
  109. package/dist/crypto/index.d.cts +0 -74
  110. package/dist/crypto/index.js.map +0 -1
  111. package/dist/errors/index.cjs +0 -136
  112. package/dist/errors/index.cjs.map +0 -1
  113. package/dist/errors/index.d.cts +0 -60
  114. package/dist/errors/index.js.map +0 -1
  115. package/dist/events/index.cjs +0 -41
  116. package/dist/events/index.cjs.map +0 -1
  117. package/dist/events/index.d.cts +0 -61
  118. package/dist/events/index.js.map +0 -1
  119. package/dist/index.cjs +0 -4
  120. package/dist/index.cjs.map +0 -1
  121. package/dist/index.d.cts +0 -2
  122. package/dist/index.js.map +0 -1
  123. package/dist/keystore/index.cjs +0 -335
  124. package/dist/keystore/index.cjs.map +0 -1
  125. package/dist/keystore/index.d.cts +0 -23
  126. package/dist/keystore/index.js.map +0 -1
  127. package/dist/network/index.cjs +0 -74
  128. package/dist/network/index.cjs.map +0 -1
  129. package/dist/network/index.d.cts +0 -36
  130. package/dist/network/index.js.map +0 -1
  131. package/dist/signer/index.cjs +0 -121
  132. package/dist/signer/index.cjs.map +0 -1
  133. package/dist/signer/index.d.cts +0 -40
  134. package/dist/signer/index.js.map +0 -1
  135. package/dist/storage/ZgStorage.d.ts +0 -24
  136. package/dist/storage/ZgStorage.js +0 -102
  137. package/dist/storage/index.cjs +0 -221
  138. package/dist/storage/index.cjs.map +0 -1
  139. package/dist/storage/index.d.cts +0 -44
  140. package/dist/storage/index.js.map +0 -1
  141. package/dist/testing/index.cjs +0 -4
  142. package/dist/testing/index.cjs.map +0 -1
  143. package/dist/testing/index.d.cts +0 -2
  144. package/dist/testing/index.js.map +0 -1
  145. package/dist/types-BOG5Ub1z.d.cts +0 -31
  146. package/dist/types-BOG5Ub1z.d.ts +0 -31
  147. package/dist/types-V7_ZmUb-.d.cts +0 -19
  148. package/dist/types-hAsITUQ7.d.ts +0 -19
  149. package/dist/verifier/index.cjs +0 -4
  150. package/dist/verifier/index.cjs.map +0 -1
  151. package/dist/verifier/index.d.cts +0 -2
  152. package/dist/verifier/index.js.map +0 -1
  153. package/dist/worker/index.cjs +0 -382
  154. package/dist/worker/index.cjs.map +0 -1
  155. package/dist/worker/index.d.cts +0 -58
  156. package/dist/worker/index.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,4 +1,36 @@
1
1
  import { ethers } from 'ethers';
2
+ // ── Helpers ─────────────────────────────────────────────────────────────────
3
+ class ApiError extends Error {
4
+ status;
5
+ body;
6
+ constructor(status, message, body) {
7
+ super(message);
8
+ this.status = status;
9
+ this.body = body;
10
+ this.name = 'ApiError';
11
+ }
12
+ }
13
+ // ── Main client ─────────────────────────────────────────────────────────────
14
+ /**
15
+ * BlindMarket REST API client.
16
+ *
17
+ * Two usage modes:
18
+ * 1. **High-level (this class)** — talks to the BlindMarket backend over REST.
19
+ * Covers the full task lifecycle, agent management, A2A, and marketplace.
20
+ * 2. **Low-level primitives** — `Agent`, `Worker`, `PrivateKeySigner`, etc.
21
+ * for on-chain + crypto operations when you need direct chain access.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const bb = new BlindMarket({ apiKey: process.env.BLINDMARKET_API_KEY! });
26
+ *
27
+ * // Deploy an agent
28
+ * const agent = await bb.deployAgent({ name: 'my-agent', ... });
29
+ *
30
+ * // Watch for status changes
31
+ * const unsub = bb.watchTask(42, (state) => console.log(state.status));
32
+ * ```
33
+ */
2
34
  export class BlindMarket {
3
35
  apiBase;
4
36
  apiKey;
@@ -6,25 +38,107 @@ export class BlindMarket {
6
38
  this.apiBase = config.apiBase ?? 'https://api.blindmarket.xyz';
7
39
  this.apiKey = config.apiKey;
8
40
  }
41
+ // ── Tools ─────────────────────────────────────────────────────────────────
42
+ /**
43
+ * Tool definitions for AI agent frameworks. Access framework-specific formats
44
+ * via property — no need to remember adapter function names.
45
+ *
46
+ * IMPORTANT: due to ESM circular-dependency constraints this is a standalone
47
+ * function rather than an instance getter. You pass `bb` once and reach the
48
+ * format you need.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * import { BlindMarket, tools } from '@blindmarket/sdk';
53
+ * const bb = new BlindMarket({ apiKey });
54
+ *
55
+ * // OpenAI (default — also works with Vercel AI SDK)
56
+ * openai.chat.completions.create({ model: 'gpt-4', tools: tools(bb).definitions });
57
+ *
58
+ * // LangChain
59
+ * createReactAgent({ llm, tools: tools(bb).langchain });
60
+ *
61
+ * // Claude
62
+ * anthropic.messages.create({ model, tools: tools(bb).claude });
63
+ *
64
+ * // Vercel
65
+ * generateText({ model, tools: tools(bb).vercel });
66
+ * ```
67
+ */
9
68
  async req(method, path, body) {
10
69
  const res = await fetch(`${this.apiBase}${path}`, {
11
70
  method,
12
- headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.apiKey}` },
71
+ headers: {
72
+ 'Content-Type': 'application/json',
73
+ Authorization: `Bearer ${this.apiKey}`,
74
+ },
13
75
  body: body ? JSON.stringify(body) : undefined,
14
76
  });
15
77
  const json = await res.json();
16
- if (!json.success)
17
- throw new Error(json.error?.message ?? `HTTP ${res.status}`);
78
+ if (!json.success) {
79
+ throw new ApiError(res.status, json.error?.message ?? `HTTP ${res.status}`, json);
80
+ }
18
81
  return json.data;
19
82
  }
20
- // ── Agent deployment ──────────────────────────────────────────────────────
83
+ // ── Health & Stats ──────────────────────────────────────────────────────
84
+ /** Backend liveness check. */
85
+ async health() {
86
+ return this.req('GET', '/health');
87
+ }
88
+ /** Live platform counts. */
89
+ async stats() {
90
+ return this.req('GET', '/api/v1/stats');
91
+ }
92
+ // ── Task lifecycle ──────────────────────────────────────────────────────
93
+ /** List open tasks (human-readable). */
94
+ async listTasks(limit = 20) {
95
+ const { tasks } = await this.req('GET', `/api/v1/tasks?limit=${limit}`);
96
+ return tasks;
97
+ }
98
+ /** Get full task details (on-chain + A2A state). */
99
+ async getTask(id) {
100
+ return this.req('GET', `/api/v1/tasks/${id}`);
101
+ }
102
+ /**
103
+ * Build an unsigned `createTask` transaction.
104
+ * You must sign and broadcast it with your wallet.
105
+ */
106
+ async createTask(params) {
107
+ return this.req('POST', '/api/v1/tasks', params);
108
+ }
109
+ /**
110
+ * Build an unsigned `assignWorker` transaction.
111
+ */
112
+ async assignWorker(taskId, worker) {
113
+ return this.req('POST', `/api/v1/tasks/${taskId}/assign`, { worker });
114
+ }
115
+ /**
116
+ * Build an unsigned `cancelTask` transaction.
117
+ */
118
+ async cancelTask(taskId) {
119
+ return this.req('POST', `/api/v1/tasks/${taskId}/cancel`);
120
+ }
121
+ /**
122
+ * Build an unsigned `claimTimeout` transaction.
123
+ */
124
+ async claimTimeout(taskId) {
125
+ return this.req('POST', `/api/v1/tasks/${taskId}/timeout`);
126
+ }
21
127
  /**
22
- * Deploy a new agent. Generates a wallet, mints an INFT, returns the agent.
128
+ * Build an unsigned `submitEvidence` transaction.
129
+ */
130
+ async submitEvidence(params) {
131
+ return this.req('POST', '/api/v1/submissions/submit', params);
132
+ }
133
+ // ── Agent deployment & management ─────────────────────────────────────────
134
+ /**
135
+ * Deploy a new agent. The backend generates a wallet, mints an INFT,
136
+ * and returns the agent descriptor.
23
137
  *
24
138
  * @example
25
139
  * const agent = await bb.deployAgent({
26
140
  * name: 'research-agent',
27
- * instructions: 'You research topics and post tasks for humans to verify.',
141
+ * instructions: 'You research topics and post tasks.',
28
142
  * provider: 'anthropic',
29
143
  * model: 'claude-sonnet-4-5',
30
144
  * apiKey: process.env.ANTHROPIC_API_KEY!,
@@ -36,41 +150,317 @@ export class BlindMarket {
36
150
  return this.req('POST', '/api/v1/agents/deploy', params);
37
151
  }
38
152
  /**
39
- * List all agents owned by an address.
153
+ * One-shot agent creation: generates a secp256k1 wallet, then registers the
154
+ * agent as an executor in the A2A marketplace with the generated wallet
155
+ * address and public key. Replaces the manual two-step flow of generating a
156
+ * wallet, then calling registerExecutor().
157
+ *
158
+ * The private key is returned **once** in the response — store it securely.
159
+ *
160
+ * @example
161
+ * const { executor, wallet } = await bb.createAgent({
162
+ * displayName: 'DataBot',
163
+ * capabilities: [AgentCap.DATA_PROCESSING, AgentCap.WEB_RESEARCH],
164
+ * minReward: '1000000000000000000', // 1 0G in wei
165
+ * });
166
+ * console.log(`Agent ${wallet.address} registered as ${executor.address}`);
40
167
  */
168
+ async createAgent(params) {
169
+ const wallet = ethers.Wallet.createRandom();
170
+ const executor = {
171
+ address: wallet.address,
172
+ displayName: params.displayName,
173
+ capabilities: params.capabilities,
174
+ publicKey: wallet.publicKey.slice(2), // strip 0x prefix — backend expects raw hex
175
+ agentCardUrl: params.agentCardUrl,
176
+ mcpEndpointUrl: params.mcpEndpointUrl,
177
+ minReward: params.minReward,
178
+ preferredCapabilities: params.preferredCapabilities,
179
+ };
180
+ const result = await this.registerExecutor(executor);
181
+ return {
182
+ executor: result.agent,
183
+ wallet: {
184
+ address: wallet.address,
185
+ publicKey: wallet.publicKey,
186
+ privateKey: wallet.privateKey,
187
+ },
188
+ };
189
+ }
190
+ /** List deployed agents, optionally filtered by owner address. */
41
191
  async listAgents(ownerAddress) {
42
- return this.req('GET', `/api/v1/agents?owner=${ownerAddress}`);
192
+ const qs = ownerAddress ? `?owner=${ownerAddress}` : '';
193
+ return this.req('GET', `/api/v1/agents${qs}`);
194
+ }
195
+ /** Get a single deployed agent by ID. */
196
+ async getAgent(id) {
197
+ return this.req('GET', `/api/v1/agents/${id}`);
198
+ }
199
+ /** Get an agent's on-chain wallet address. */
200
+ async getAgentWallet(id) {
201
+ return this.req('GET', `/api/v1/agents/${id}/wallet`);
202
+ }
203
+ /** Start a deployed agent. Requires owner auth. */
204
+ async startAgent(id) {
205
+ return this.req('POST', `/api/v1/agents/${id}/start`);
206
+ }
207
+ /** Stop a deployed agent. Requires owner auth. */
208
+ async stopAgent(id) {
209
+ return this.req('POST', `/api/v1/agents/${id}/stop`);
210
+ }
211
+ /** Pause a deployed agent. Requires owner auth. */
212
+ async pauseAgent(id) {
213
+ return this.req('POST', `/api/v1/agents/${id}/pause`);
214
+ }
215
+ /** Restart a deployed agent. Requires owner auth. */
216
+ async restartAgent(id) {
217
+ return this.req('POST', `/api/v1/agents/${id}/restart`);
43
218
  }
44
- // ── Task lifecycle ────────────────────────────────────────────────────────
45
219
  /**
46
- * Assign a worker to a task. Returns an unsigned tx.
220
+ * Update a deployed agent's config (instructions, model, tools, etc.).
221
+ * Requires owner auth.
47
222
  */
48
- async assignWorker(taskId, worker) {
49
- return this.req('POST', `/api/v1/tasks/${taskId}/assign`, { worker });
223
+ async updateAgent(id, patch) {
224
+ return this.req('PATCH', `/api/v1/agents/${id}`, patch);
225
+ }
226
+ // ── A2A executor registration ───────────────────────────────────────────
227
+ /** Register as an A2A agent executor (worker-side). */
228
+ async registerExecutor(params) {
229
+ return this.req('POST', '/api/v1/a2a/register', params);
230
+ }
231
+ /** List registered A2A executors, optionally filtered by capability. */
232
+ async listExecutors(capabilities) {
233
+ const qs = capabilities?.length ? `?capabilities=${capabilities.join(',')}` : '';
234
+ return this.req('GET', `/api/v1/a2a/executors${qs}`);
235
+ }
236
+ /** Get own executor profile with on-chain + decayed reputation. */
237
+ async getExecutorProfile() {
238
+ return this.req('GET', '/api/v1/a2a/profile');
239
+ }
240
+ // ── A2A task lifecycle ───────────────────────────────────────────────────
241
+ /** Browse A2A tasks available for execution. */
242
+ async browseA2ATasks(params) {
243
+ const qs = new URLSearchParams();
244
+ if (params?.capabilities)
245
+ qs.set('capabilities', params.capabilities.join(','));
246
+ if (params?.minReputation != null)
247
+ qs.set('minReputation', String(params.minReputation));
248
+ const suffix = qs.toString() ? `?${qs.toString()}` : '';
249
+ return this.req('GET', `/api/v1/a2a/tasks${suffix}`);
250
+ }
251
+ /** Register intent to accept a task (bid). */
252
+ async bidOnTask(taskId) {
253
+ return this.req('POST', `/api/v1/a2a/tasks/${taskId}/bid`);
254
+ }
255
+ /** Accept a task and get wrapped AES key. Requires executor auth. */
256
+ async acceptTask(taskId) {
257
+ return this.req('POST', `/api/v1/a2a/tasks/${taskId}/accept`);
258
+ }
259
+ /** Submit result for an accepted task. */
260
+ async submitResult(taskId, resultData) {
261
+ return this.req('POST', `/api/v1/a2a/tasks/${taskId}/submit`, { resultData });
262
+ }
263
+ /** Get tasks posted by the authenticated user. */
264
+ async getPostedTasks() {
265
+ return this.req('GET', '/api/v1/a2a/tasks/posted');
266
+ }
267
+ /** Get tasks executed by the authenticated user. */
268
+ async getExecutions(address) {
269
+ const qs = address ? `?address=${address}` : '';
270
+ return this.req('GET', `/api/v1/a2a/executions${qs}`);
50
271
  }
272
+ // ── Verification ─────────────────────────────────────────────────────────
51
273
  /**
52
- * Trigger TEE verification for a task.
274
+ * Trigger TEE / AI verification for a task.
53
275
  */
54
276
  async verify(params) {
55
- return this.req('POST', '/api/v1/verification/trigger', {
277
+ return this.req('POST', '/api/v1/verification/verify', {
56
278
  taskId: params.taskId,
57
- taskCategory: params.category ?? 'general',
58
- taskRequirements: params.requirements,
279
+ taskCategory: params.taskCategory,
280
+ taskRequirements: params.taskRequirements,
59
281
  evidenceSummary: params.evidenceSummary,
60
282
  });
61
283
  }
284
+ /** List available 0G Compute inference providers. */
285
+ async getVerificationProviders() {
286
+ return this.req('GET', '/api/v1/verification/providers');
287
+ }
288
+ /** Check if 0G Compute is configured. */
289
+ async getVerificationStatus() {
290
+ return this.req('GET', '/api/v1/verification/status');
291
+ }
292
+ // ── Reputation ──────────────────────────────────────────────────────────
293
+ /** Get merged reputation (on-chain + off-chain) for an address. */
294
+ async getReputation(address) {
295
+ return this.req('GET', `/api/v1/reputation/${address}`);
296
+ }
297
+ /** Get top workers by decayed score. */
298
+ async getLeaderboard(limit = 50) {
299
+ return this.req('GET', `/api/v1/reputation/leaderboard?limit=${limit}`);
300
+ }
301
+ // ── Storage ─────────────────────────────────────────────────────────────
302
+ /** Upload an encrypted blob to 0G Storage. */
303
+ async uploadBlob(data) {
304
+ return this.req('POST', '/api/v1/storage/upload', { data });
305
+ }
306
+ /** Download a blob by root hash. */
307
+ async downloadBlob(rootHash) {
308
+ return this.req('GET', `/api/v1/storage/${rootHash}`);
309
+ }
310
+ // ── Messages ─────────────────────────────────────────────────────────────
311
+ /** Send a message to another user or agent. */
312
+ async sendMessage(params) {
313
+ return this.req('POST', '/api/v1/messages/send', params);
314
+ }
315
+ /** Get inbox messages. */
316
+ async getInbox() {
317
+ return this.req('GET', '/api/v1/messages/inbox');
318
+ }
319
+ /** Get unread message count. */
320
+ async getUnreadCount() {
321
+ return this.req('GET', '/api/v1/messages/unread-count');
322
+ }
323
+ // ── Marketplace ─────────────────────────────────────────────────────────
324
+ /** Search agents by capability and/or minimum rating. */
325
+ async searchAgents(params) {
326
+ const qs = new URLSearchParams();
327
+ if (params?.capability)
328
+ qs.set('capability', params.capability);
329
+ if (params?.minRating != null)
330
+ qs.set('minRating', String(params.minRating));
331
+ const suffix = qs.toString() ? `?${qs.toString()}` : '';
332
+ return this.req('GET', `/api/v1/marketplace/agents/search${suffix}`);
333
+ }
334
+ /** List public task templates. */
335
+ async listTemplates() {
336
+ return this.req('GET', '/api/v1/marketplace/templates');
337
+ }
338
+ /** List own templates. */
339
+ async listMyTemplates() {
340
+ return this.req('GET', '/api/v1/marketplace/templates/mine');
341
+ }
342
+ /** Create a task template. */
343
+ async createTemplate(params) {
344
+ return this.req('POST', '/api/v1/marketplace/templates', params);
345
+ }
346
+ // ── Event watching ──────────────────────────────────────────────────────
62
347
  /**
63
- * Get task status.
348
+ * Poll a task's status at a fixed interval. Calls `callback` on every change.
349
+ * Returns an unsubscribe function.
350
+ *
351
+ * @example
352
+ * const stop = bb.watchTask('42', (task) => {
353
+ * console.log('Status:', task.status);
354
+ * if (task.status === 'verified') stop();
355
+ * });
64
356
  */
65
- async getTask(taskId) {
66
- return this.req('GET', `/api/v1/tasks/${taskId}`);
357
+ watchTask(taskId, callback, intervalMs = 5_000) {
358
+ let prev = '';
359
+ const id = setInterval(async () => {
360
+ try {
361
+ const task = await this.getTask(taskId);
362
+ const cur = task.a2aState?.status ?? String(task.status);
363
+ if (cur !== prev) {
364
+ prev = cur;
365
+ callback(task);
366
+ }
367
+ }
368
+ catch {
369
+ // Silently retry on next tick
370
+ }
371
+ }, intervalMs);
372
+ return () => clearInterval(id);
67
373
  }
68
374
  /**
69
- * List open tasks.
375
+ * Poll an agent's status at a fixed interval. Returns an unsubscribe function.
70
376
  */
71
- async listTasks(limit = 20) {
72
- const { tasks } = await this.req('GET', `/api/v1/tasks?limit=${limit}`);
73
- return tasks;
377
+ watchAgent(agentId, callback, intervalMs = 5_000) {
378
+ let prev = '';
379
+ const id = setInterval(async () => {
380
+ try {
381
+ const agent = await this.getAgent(agentId);
382
+ if (agent.status !== prev) {
383
+ prev = agent.status;
384
+ callback(agent);
385
+ }
386
+ }
387
+ catch {
388
+ // Silently retry on next tick
389
+ }
390
+ }, intervalMs);
391
+ return () => clearInterval(id);
392
+ }
393
+ // ── Device-flow registration (static) ─────────────────────────────────────
394
+ /**
395
+ * Start a device-flow registration session. Generates a magic-link URL
396
+ * that the user opens in a browser to sign with their wallet.
397
+ *
398
+ * After registering, call `BlindMarket.pollSession(token)` to wait for
399
+ * the user to confirm and receive the API key.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * const wallet = ethers.Wallet.createRandom();
404
+ * const { url, token } = await BlindMarket.register({
405
+ * agentName: 'my-agent',
406
+ * agentWallet: wallet.address,
407
+ * agentPublicKey: wallet.publicKey,
408
+ * });
409
+ * console.log('Open', url, 'to confirm');
410
+ * const apiKey = await BlindMarket.pollSession(token);
411
+ * const bb = new BlindMarket({ apiKey });
412
+ * ```
413
+ */
414
+ static async register(params) {
415
+ const base = params.apiBase ?? 'https://api.blindmarket.xyz';
416
+ const res = await fetch(`${base}/api/v1/registration/session`, {
417
+ method: 'POST',
418
+ headers: { 'Content-Type': 'application/json' },
419
+ body: JSON.stringify({
420
+ agentName: params.agentName,
421
+ agentWallet: params.agentWallet,
422
+ agentPublicKey: params.agentPublicKey,
423
+ }),
424
+ });
425
+ const json = await res.json();
426
+ if (!json.success)
427
+ throw new ApiError(res.status, json.error?.message ?? 'Registration failed', json);
428
+ return json.data;
429
+ }
430
+ /**
431
+ * Poll a device-flow registration session until the user confirms or
432
+ * the session expires. Returns the API key to use with `new BlindMarket({ apiKey })`.
433
+ *
434
+ * @param token - The session token from `BlindMarket.register()`.
435
+ * @param apiBase - Optional custom API base URL.
436
+ * @param intervalMs - Poll interval (default 2s).
437
+ * @param timeoutMs - Max wait time (default 5min).
438
+ */
439
+ static async pollSession(token, apiBase, intervalMs = 2_000, timeoutMs = 300_000) {
440
+ const base = apiBase ?? 'https://api.blindmarket.xyz';
441
+ const deadline = Date.now() + timeoutMs;
442
+ while (Date.now() < deadline) {
443
+ const res = await fetch(`${base}/api/v1/registration/session/${token}`);
444
+ const json = await res.json();
445
+ if (!json.success)
446
+ throw new ApiError(res.status, json.error?.message ?? 'Session lookup failed', json);
447
+ if (json.data?.status === 'confirmed' && json.data?.apiKey)
448
+ return json.data.apiKey;
449
+ if (json.data?.status === 'pending') {
450
+ await new Promise(r => setTimeout(r, intervalMs));
451
+ continue;
452
+ }
453
+ throw new Error(`Unexpected session status: ${json.data?.status}`);
454
+ }
455
+ throw new Error('Registration session timed out');
74
456
  }
75
457
  }
76
458
  export { ethers };
459
+ export { ApiError };
460
+ export { tools, createBlindMarketTools, createTaskTools, createAgentManagementTools, createA2ATools, toLangChainTools, toVercelTools, toOpenAITools, toClaudeTools, } from './tools/index.js';
461
+ export * from './executor/index.js';
462
+ export * from './types.js';
463
+ // Chain abstraction layer
464
+ export { EVMChainAdapter } from './chain/evm/index.js';
465
+ export { createChainAdapter } from './chain/createChainAdapter.js';
466
+ export { isEVMNetwork } from './network/resolve.js';
@@ -1,7 +1,7 @@
1
1
  import { aesDecrypt, aesEncrypt, generateAesKey, hkdfSha256 } from '../crypto/index.js';
2
2
  import { CryptoError } from '../errors/index.js';
3
- const EXPORT_FORMAT = 'blindbounty.keystore.v1';
4
- const EXPORT_INFO = new TextEncoder().encode('BlindBounty-Keystore-Export-v1');
3
+ const EXPORT_FORMAT = 'blindmarket.keystore.v1';
4
+ const EXPORT_INFO = new TextEncoder().encode('BlindMarket-Keystore-Export-v1');
5
5
  /**
6
6
  * Default KeyStore. Non-persistent — keys live only for the process lifetime.
7
7
  * Export/import is encrypted with a passphrase via HKDF-derived AES-256-GCM,
@@ -1,14 +1,43 @@
1
1
  /**
2
2
  * Known-good network presets. Addresses pinned per SDK version so upgrading
3
3
  * the SDK cannot silently move contracts under a consumer.
4
- *
5
- * testnet = 0G Galileo (chainId 16602) — addresses from
6
- * contracts/deployments/0g-testnet.json (deployed 2026-04-15).
7
4
  */
5
+ export type NetworkName = 'testnet' | 'og-testnet' | 'og-mainnet';
8
6
  export declare const networks: {
7
+ readonly 'og-testnet': {
8
+ readonly name: "0g-galileo-testnet";
9
+ readonly chainType: "evm";
10
+ readonly chainId: 16602;
11
+ readonly rpc: ["https://evmrpc-testnet.0g.ai"];
12
+ readonly contracts: {
13
+ readonly escrow: "0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681";
14
+ readonly registry: "0xeE52d780A47F77E8a4a1cEb236e3C65A48FbD828";
15
+ readonly reputation: "0x4A6374Fae37E19E69ba43E7cf6994AC15F63256e";
16
+ readonly usdc: "0x317227efcA18D004E12CA8046AEf7E1597458F25";
17
+ };
18
+ readonly indexer: "https://indexer-storage-testnet-turbo.0g.ai";
19
+ readonly broker: "https://broker.testnet.0g.ai";
20
+ readonly explorer: "https://chainscan-galileo.0g.ai";
21
+ };
22
+ readonly 'og-mainnet': {
23
+ readonly name: "0g-mainnet";
24
+ readonly chainType: "evm";
25
+ readonly chainId: 16661;
26
+ readonly rpc: ["https://evmrpc.0g.ai"];
27
+ readonly contracts: {
28
+ readonly escrow: "0x3d0374963DaaD43e31d42373eb11156A8e8ce2Ff";
29
+ readonly registry: "0x9CCF9c196006B573FaA9C9c9CebDd1296dbd5cE0";
30
+ readonly reputation: "0x3af9232009C5da30AdA366B6E09849A040162A1a";
31
+ readonly usdc: "0x0000000000000000000000000000000000000000";
32
+ };
33
+ readonly indexer: "https://indexer-storage-turbo.0g.ai";
34
+ readonly broker: "https://broker.0g.ai";
35
+ readonly explorer: "https://chainscan.0g.ai";
36
+ };
9
37
  readonly testnet: {
10
38
  readonly name: "0g-galileo-testnet";
11
- readonly chainId: 16602n;
39
+ readonly chainType: "evm";
40
+ readonly chainId: 16602;
12
41
  readonly rpc: ["https://evmrpc-testnet.0g.ai"];
13
42
  readonly contracts: {
14
43
  readonly escrow: "0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681";
@@ -21,4 +50,3 @@ export declare const networks: {
21
50
  readonly explorer: "https://chainscan-galileo.0g.ai";
22
51
  };
23
52
  };
24
- export type NetworkName = keyof typeof networks;
@@ -1,14 +1,41 @@
1
- /**
2
- * Known-good network presets. Addresses pinned per SDK version so upgrading
3
- * the SDK cannot silently move contracts under a consumer.
4
- *
5
- * testnet = 0G Galileo (chainId 16602) — addresses from
6
- * contracts/deployments/0g-testnet.json (deployed 2026-04-15).
7
- */
8
1
  export const networks = {
2
+ // ── 0G EVM chains ─────────────────────────────────────────────────────
3
+ 'og-testnet': {
4
+ name: '0g-galileo-testnet',
5
+ chainType: 'evm',
6
+ chainId: 16602,
7
+ rpc: ['https://evmrpc-testnet.0g.ai'],
8
+ contracts: {
9
+ escrow: '0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681',
10
+ registry: '0xeE52d780A47F77E8a4a1cEb236e3C65A48FbD828',
11
+ reputation: '0x4A6374Fae37E19E69ba43E7cf6994AC15F63256e',
12
+ usdc: '0x317227efcA18D004E12CA8046AEf7E1597458F25',
13
+ },
14
+ indexer: 'https://indexer-storage-testnet-turbo.0g.ai',
15
+ broker: 'https://broker.testnet.0g.ai',
16
+ explorer: 'https://chainscan-galileo.0g.ai',
17
+ },
18
+ 'og-mainnet': {
19
+ name: '0g-mainnet',
20
+ chainType: 'evm',
21
+ chainId: 16661,
22
+ rpc: ['https://evmrpc.0g.ai'],
23
+ contracts: {
24
+ escrow: '0x3d0374963DaaD43e31d42373eb11156A8e8ce2Ff',
25
+ registry: '0x9CCF9c196006B573FaA9C9c9CebDd1296dbd5cE0',
26
+ reputation: '0x3af9232009C5da30AdA366B6E09849A040162A1a',
27
+ usdc: '0x0000000000000000000000000000000000000000',
28
+ },
29
+ indexer: 'https://indexer-storage-turbo.0g.ai',
30
+ broker: 'https://broker.0g.ai',
31
+ explorer: 'https://chainscan.0g.ai',
32
+ },
33
+ // ── Backward-compat alias ──────────────────────────────────────────────
34
+ // Kept so existing code referencing 'testnet' doesn't break.
9
35
  testnet: {
10
36
  name: '0g-galileo-testnet',
11
- chainId: 16602n,
37
+ chainType: 'evm',
38
+ chainId: 16602,
12
39
  rpc: ['https://evmrpc-testnet.0g.ai'],
13
40
  contracts: {
14
41
  escrow: '0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681',
@@ -1,7 +1,16 @@
1
1
  import { type NetworkName } from './presets.js';
2
- import type { Network } from './types.js';
2
+ import type { Network } from '../chain/domain-types.js';
3
3
  /**
4
- * Resolve a preset name or a literal Network object into the canonical
5
- * Network used throughout the SDK. Throws ConfigError for unknown names.
4
+ * Resolve a network preset name or a Network object to a canonical Network.
5
+ *
6
+ * When given a string, looks up the preset. When given a Network object,
7
+ * returns it as-is (pass-through for callers that already have a resolved
8
+ * network config).
6
9
  */
7
10
  export declare function resolveNetwork(arg: NetworkName | Network): Network;
11
+ /**
12
+ * Type guard: check if a Network is an EVM network.
13
+ */
14
+ export declare function isEVMNetwork(network: Network): network is Network & {
15
+ chainType: 'evm';
16
+ };
@@ -1,17 +1,25 @@
1
1
  import { ConfigError } from '../errors/index.js';
2
2
  import { networks } from './presets.js';
3
3
  /**
4
- * Resolve a preset name or a literal Network object into the canonical
5
- * Network used throughout the SDK. Throws ConfigError for unknown names.
4
+ * Resolve a network preset name or a Network object to a canonical Network.
5
+ *
6
+ * When given a string, looks up the preset. When given a Network object,
7
+ * returns it as-is (pass-through for callers that already have a resolved
8
+ * network config).
6
9
  */
7
10
  export function resolveNetwork(arg) {
8
11
  if (typeof arg === 'string') {
9
- const preset = networks[arg];
10
- if (!preset) {
11
- const known = Object.keys(networks).join(', ');
12
- throw new ConfigError('CONFIG/INVALID_NETWORK', `unknown network '${arg}' (known: ${known})`);
12
+ const net = networks[arg];
13
+ if (!net) {
14
+ throw new ConfigError('CONFIG/INVALID_NETWORK', `Unknown network: "${arg}". Known presets: ${Object.keys(networks).join(', ')}`);
13
15
  }
14
- return preset;
16
+ return net;
15
17
  }
16
18
  return arg;
17
19
  }
20
+ /**
21
+ * Type guard: check if a Network is an EVM network.
22
+ */
23
+ export function isEVMNetwork(network) {
24
+ return network.chainType === 'evm';
25
+ }