@blindmarket/sdk 0.1.7 → 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.
- package/dist/chain/BlindEscrowClient.d.ts +2 -0
- package/dist/chain/BlindEscrowClient.js +14 -6
- package/dist/chain/BlindReputationClient.d.ts +3 -0
- package/dist/chain/BlindReputationClient.js +3 -1
- package/dist/chain/ChainClient.d.ts +5 -2
- package/dist/chain/ChainClient.js +5 -0
- package/dist/chain/IBlindMarketChain.d.ts +74 -0
- package/dist/chain/IBlindMarketChain.js +1 -0
- package/dist/chain/TaskRegistryClient.d.ts +2 -1
- package/dist/chain/TaskRegistryClient.js +15 -7
- package/dist/chain/createChainAdapter.d.ts +25 -0
- package/dist/chain/createChainAdapter.js +24 -0
- package/dist/chain/domain-types.d.ts +77 -0
- package/dist/chain/domain-types.js +1 -0
- package/dist/chain/evm/EVMChainAdapter.d.ts +56 -0
- package/dist/chain/evm/EVMChainAdapter.js +161 -0
- package/dist/chain/evm/index.d.ts +1 -0
- package/dist/chain/evm/index.js +1 -0
- package/dist/chain/index.d.ts +4 -0
- package/dist/chain/index.js +5 -0
- package/dist/executor/WorkerRuntime.d.ts +113 -0
- package/dist/executor/WorkerRuntime.js +248 -0
- package/dist/executor/index.d.ts +1 -0
- package/dist/executor/index.js +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -3
- package/dist/network/presets.d.ts +33 -5
- package/dist/network/presets.js +35 -8
- package/dist/network/resolve.d.ts +12 -3
- package/dist/network/resolve.js +15 -7
- package/dist/network/types.d.ts +3 -16
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/chain/BlindEscrowClient.ts +15 -6
- package/src/chain/BlindReputationClient.ts +6 -1
- package/src/chain/ChainClient.ts +9 -3
- package/src/chain/IBlindMarketChain.ts +109 -0
- package/src/chain/TaskRegistryClient.ts +17 -8
- package/src/chain/createChainAdapter.ts +40 -0
- package/src/chain/domain-types.ts +92 -0
- package/src/chain/evm/EVMChainAdapter.ts +212 -0
- package/src/chain/evm/index.ts +1 -0
- package/src/chain/index.ts +6 -0
- package/src/executor/WorkerRuntime.ts +338 -0
- package/src/executor/index.ts +8 -0
- package/src/index.ts +23 -4
- package/src/network/presets.ts +47 -8
- package/src/network/resolve.ts +20 -8
- package/src/network/types.ts +18 -16
- package/src/signer/index.ts +1 -1
- package/src/types.ts +2 -1
- package/dist/BlindEscrowClient-CyPuKMge.d.cts +0 -54
- package/dist/BlindEscrowClient-R7iGpE-n.d.ts +0 -54
- package/dist/KeyStore-Be_SSpCt.d.cts +0 -21
- package/dist/KeyStore-k1JgYPJY.d.ts +0 -21
- package/dist/Signer-BnqH_qew.d.cts +0 -38
- package/dist/Signer-LColE0Uo.d.ts +0 -38
- package/dist/Storage-4QOrh7rm.d.ts +0 -17
- package/dist/Storage-Cf4IJRMk.d.cts +0 -17
- package/dist/TaskRegistryClient-Ch6lYqM_.d.ts +0 -24
- package/dist/TaskRegistryClient-CrQjddDc.d.cts +0 -24
- package/dist/aes-J-7HrHze.d.cts +0 -17
- package/dist/aes-J-7HrHze.d.ts +0 -17
- package/dist/agent/index.cjs +0 -425
- package/dist/agent/index.cjs.map +0 -1
- package/dist/agent/index.d.cts +0 -63
- package/dist/agent/index.js.map +0 -1
- package/dist/api/index.cjs +0 -4
- package/dist/api/index.cjs.map +0 -1
- package/dist/api/index.d.cts +0 -2
- package/dist/api/index.js.map +0 -1
- package/dist/chain/index.cjs +0 -2484
- package/dist/chain/index.cjs.map +0 -1
- package/dist/chain/index.d.cts +0 -2305
- package/dist/chain/index.js.map +0 -1
- package/dist/compute/index.cjs +0 -4
- package/dist/compute/index.cjs.map +0 -1
- package/dist/compute/index.d.cts +0 -2
- package/dist/compute/index.js.map +0 -1
- package/dist/crypto/index.cjs +0 -424
- package/dist/crypto/index.cjs.map +0 -1
- package/dist/crypto/index.d.cts +0 -74
- package/dist/crypto/index.js.map +0 -1
- package/dist/errors/BlindBountyError.d.ts +0 -14
- package/dist/errors/BlindBountyError.js +0 -30
- package/dist/errors/index.cjs +0 -136
- package/dist/errors/index.cjs.map +0 -1
- package/dist/errors/index.d.cts +0 -60
- package/dist/errors/index.js.map +0 -1
- package/dist/events/index.cjs +0 -41
- package/dist/events/index.cjs.map +0 -1
- package/dist/events/index.d.cts +0 -61
- package/dist/events/index.js.map +0 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/keystore/index.cjs +0 -335
- package/dist/keystore/index.cjs.map +0 -1
- package/dist/keystore/index.d.cts +0 -23
- package/dist/keystore/index.js.map +0 -1
- package/dist/mcp.d.ts +0 -23
- package/dist/mcp.js +0 -101
- package/dist/network/index.cjs +0 -74
- package/dist/network/index.cjs.map +0 -1
- package/dist/network/index.d.cts +0 -36
- package/dist/network/index.js.map +0 -1
- package/dist/signer/index.cjs +0 -121
- package/dist/signer/index.cjs.map +0 -1
- package/dist/signer/index.d.cts +0 -40
- package/dist/signer/index.js.map +0 -1
- package/dist/storage/ZgStorage.d.ts +0 -24
- package/dist/storage/ZgStorage.js +0 -102
- package/dist/storage/index.cjs +0 -221
- package/dist/storage/index.cjs.map +0 -1
- package/dist/storage/index.d.cts +0 -44
- package/dist/storage/index.js.map +0 -1
- package/dist/testing/index.cjs +0 -4
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -2
- package/dist/testing/index.js.map +0 -1
- package/dist/types-BOG5Ub1z.d.cts +0 -31
- package/dist/types-BOG5Ub1z.d.ts +0 -31
- package/dist/types-V7_ZmUb-.d.cts +0 -19
- package/dist/types-hAsITUQ7.d.ts +0 -19
- package/dist/verifier/index.cjs +0 -4
- package/dist/verifier/index.cjs.map +0 -1
- package/dist/verifier/index.d.cts +0 -2
- package/dist/verifier/index.js.map +0 -1
- package/dist/worker/index.cjs +0 -382
- package/dist/worker/index.cjs.map +0 -1
- package/dist/worker/index.d.cts +0 -58
- package/dist/worker/index.js.map +0 -1
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { BlindMarket } from '../index.js';
|
|
2
|
+
import { eciesDecrypt, aesDecrypt } from '../crypto/index.js';
|
|
3
|
+
import type {
|
|
4
|
+
A2ATaskState, AgentCapability, ExecutorProfile, Message,
|
|
5
|
+
} from '../types.js';
|
|
6
|
+
|
|
7
|
+
// ── Config ──────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
export interface WorkerRuntimeConfig {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
apiBase?: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
capabilities: AgentCapability[];
|
|
14
|
+
executeTask: ExecuteTaskHandler;
|
|
15
|
+
existingPrivateKey?: string;
|
|
16
|
+
existingAddress?: string;
|
|
17
|
+
existingPublicKey?: string;
|
|
18
|
+
minReward?: string;
|
|
19
|
+
preferredCapabilities?: AgentCapability[];
|
|
20
|
+
browseIntervalMs?: number;
|
|
21
|
+
watchIntervalMs?: number;
|
|
22
|
+
maxConcurrentTasks?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ── Types ───────────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
export type ExecuteTaskHandler = (ctx: TaskContext) => Promise<Record<string, unknown>>;
|
|
28
|
+
|
|
29
|
+
export interface TaskContext {
|
|
30
|
+
taskId: string;
|
|
31
|
+
task: A2ATaskState;
|
|
32
|
+
instructions: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TaskExecutionInfo {
|
|
36
|
+
taskId: string;
|
|
37
|
+
status: 'bidding' | 'assigned' | 'working' | 'submitted' | 'completed' | 'failed';
|
|
38
|
+
task?: A2ATaskState;
|
|
39
|
+
error?: string;
|
|
40
|
+
startedAt: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type WorkerRuntimeEvent =
|
|
44
|
+
| { type: 'started' }
|
|
45
|
+
| { type: 'stopped' }
|
|
46
|
+
| { type: 'paused' }
|
|
47
|
+
| { type: 'resumed' }
|
|
48
|
+
| { type: 'registered'; profile: ExecutorProfile }
|
|
49
|
+
| { type: 'task_found'; taskId: string; task: A2ATaskState }
|
|
50
|
+
| { type: 'task_bidded'; taskId: string }
|
|
51
|
+
| { type: 'task_assigned'; taskId: string }
|
|
52
|
+
| { type: 'task_accepted'; taskId: string }
|
|
53
|
+
| { type: 'task_working'; taskId: string }
|
|
54
|
+
| { type: 'task_executed'; taskId: string }
|
|
55
|
+
| { type: 'task_submitted'; taskId: string; result: Record<string, unknown> }
|
|
56
|
+
| { type: 'task_failed'; taskId: string; error: string }
|
|
57
|
+
| { type: 'message_received'; message: Message; count: number }
|
|
58
|
+
| { type: 'browse_done'; found: number }
|
|
59
|
+
| { type: 'error'; error: string };
|
|
60
|
+
|
|
61
|
+
// ── Defaults ────────────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
const DEFAULTS = {
|
|
64
|
+
browseIntervalMs: 15_000,
|
|
65
|
+
watchIntervalMs: 5_000,
|
|
66
|
+
maxConcurrentTasks: 3,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// ── WorkerRuntime ───────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
export class WorkerRuntime {
|
|
72
|
+
private bb: BlindMarket;
|
|
73
|
+
private config: WorkerRuntimeConfig & typeof DEFAULTS;
|
|
74
|
+
private wallet?: { address: string; privateKey: string; publicKey: string };
|
|
75
|
+
private profile?: ExecutorProfile;
|
|
76
|
+
private running = false;
|
|
77
|
+
private paused = false;
|
|
78
|
+
private browseTimer?: ReturnType<typeof setInterval>;
|
|
79
|
+
private watchTimers = new Map<string, ReturnType<typeof setInterval>>();
|
|
80
|
+
private executions = new Map<string, TaskExecutionInfo>();
|
|
81
|
+
private listeners = new Set<(event: WorkerRuntimeEvent) => void>();
|
|
82
|
+
|
|
83
|
+
constructor(config: WorkerRuntimeConfig) {
|
|
84
|
+
this.config = { ...DEFAULTS, ...config };
|
|
85
|
+
this.bb = new BlindMarket({ apiKey: config.apiKey, apiBase: config.apiBase });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── Status ──────────────────────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
get isRunning(): boolean {
|
|
91
|
+
return this.running;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get isPaused(): boolean {
|
|
95
|
+
return this.paused;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get activeExecutions(): TaskExecutionInfo[] {
|
|
99
|
+
return [...this.executions.values()];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Get own executor profile (available after start). */
|
|
103
|
+
get executorProfile(): ExecutorProfile | undefined {
|
|
104
|
+
return this.profile;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Get own wallet info (available after start). */
|
|
108
|
+
get executorWallet(): { address: string; publicKey: string } | undefined {
|
|
109
|
+
return this.wallet;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ── Events ──────────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
on(listener: (event: WorkerRuntimeEvent) => void): () => void {
|
|
115
|
+
this.listeners.add(listener);
|
|
116
|
+
return () => this.listeners.delete(listener);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private emit(event: WorkerRuntimeEvent): void {
|
|
120
|
+
for (const l of this.listeners) l(event);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── Lifecycle ───────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
async start(): Promise<ExecutorProfile> {
|
|
126
|
+
if (this.running) return this.profile!;
|
|
127
|
+
|
|
128
|
+
// 1. Register or restore executor
|
|
129
|
+
if (this.config.existingPrivateKey && this.config.existingAddress && this.config.existingPublicKey) {
|
|
130
|
+
this.wallet = {
|
|
131
|
+
address: this.config.existingAddress,
|
|
132
|
+
privateKey: this.config.existingPrivateKey,
|
|
133
|
+
publicKey: this.config.existingPublicKey,
|
|
134
|
+
};
|
|
135
|
+
// Fetch existing profile — backend identifies by API key
|
|
136
|
+
const result = await this.bb.getExecutorProfile();
|
|
137
|
+
this.profile = result.agent;
|
|
138
|
+
} else {
|
|
139
|
+
const result = await this.bb.createAgent({
|
|
140
|
+
displayName: this.config.displayName,
|
|
141
|
+
capabilities: this.config.capabilities,
|
|
142
|
+
minReward: this.config.minReward,
|
|
143
|
+
preferredCapabilities: this.config.preferredCapabilities,
|
|
144
|
+
});
|
|
145
|
+
this.wallet = {
|
|
146
|
+
address: result.wallet.address,
|
|
147
|
+
privateKey: result.wallet.privateKey,
|
|
148
|
+
publicKey: result.wallet.publicKey,
|
|
149
|
+
};
|
|
150
|
+
this.profile = result.executor;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.emit({ type: 'registered', profile: this.profile });
|
|
154
|
+
|
|
155
|
+
// 2. Start the browse loop
|
|
156
|
+
this.running = true;
|
|
157
|
+
this.startBrowseLoop();
|
|
158
|
+
this.emit({ type: 'started' });
|
|
159
|
+
|
|
160
|
+
return this.profile;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
stop(): void {
|
|
164
|
+
this.running = false;
|
|
165
|
+
if (this.browseTimer) {
|
|
166
|
+
clearInterval(this.browseTimer);
|
|
167
|
+
this.browseTimer = undefined;
|
|
168
|
+
}
|
|
169
|
+
for (const t of this.watchTimers.values()) clearInterval(t);
|
|
170
|
+
this.watchTimers.clear();
|
|
171
|
+
this.emit({ type: 'stopped' });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
pause(): void {
|
|
175
|
+
if (!this.running || this.paused) return;
|
|
176
|
+
this.paused = true;
|
|
177
|
+
this.emit({ type: 'paused' });
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
resume(): void {
|
|
181
|
+
if (!this.running || !this.paused) return;
|
|
182
|
+
this.paused = false;
|
|
183
|
+
this.emit({ type: 'resumed' });
|
|
184
|
+
// Immediately browse instead of waiting for next interval
|
|
185
|
+
this.browse();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ── Browse loop ─────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
private startBrowseLoop(): void {
|
|
191
|
+
const ms = this.config.browseIntervalMs;
|
|
192
|
+
this.browseTimer = setInterval(() => this.browse(), ms);
|
|
193
|
+
this.browse();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private async browse(): Promise<void> {
|
|
197
|
+
if (this.paused) return;
|
|
198
|
+
try {
|
|
199
|
+
const active = this.activeExecutions;
|
|
200
|
+
const inFlight = active.filter(e => e.status === 'bidding' || e.status === 'working').length;
|
|
201
|
+
if (inFlight >= this.config.maxConcurrentTasks) return;
|
|
202
|
+
|
|
203
|
+
const result = await this.bb.browseA2ATasks({
|
|
204
|
+
capabilities: this.config.capabilities,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
this.emit({ type: 'browse_done', found: result.tasks.length });
|
|
208
|
+
|
|
209
|
+
for (const task of result.tasks) {
|
|
210
|
+
if (this.executions.has(task.taskId)) continue;
|
|
211
|
+
if (task.status !== 'open' && task.status !== 'bidding') continue;
|
|
212
|
+
if (task.executorAddress && task.executorAddress !== this.wallet?.address) continue;
|
|
213
|
+
|
|
214
|
+
this.executions.set(task.taskId, {
|
|
215
|
+
taskId: task.taskId,
|
|
216
|
+
status: 'bidding',
|
|
217
|
+
task,
|
|
218
|
+
startedAt: Date.now(),
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
this.emit({ type: 'task_found', taskId: task.taskId, task });
|
|
222
|
+
|
|
223
|
+
await this.bb.bidOnTask(task.taskId);
|
|
224
|
+
this.emit({ type: 'task_bidded', taskId: task.taskId });
|
|
225
|
+
|
|
226
|
+
this.watchForAssignment(task.taskId);
|
|
227
|
+
}
|
|
228
|
+
} catch (err) {
|
|
229
|
+
this.emit({ type: 'error', error: `Browse failed: ${err}` });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ── Assignment watching ─────────────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
private watchForAssignment(taskId: string): void {
|
|
236
|
+
if (!this.running) return;
|
|
237
|
+
const ms = this.config.watchIntervalMs;
|
|
238
|
+
const timer = setInterval(async () => {
|
|
239
|
+
if (!this.running || this.paused) return;
|
|
240
|
+
try {
|
|
241
|
+
const detail = await this.bb.getTask(taskId);
|
|
242
|
+
const a2a = detail.a2aState;
|
|
243
|
+
if (!a2a) return;
|
|
244
|
+
|
|
245
|
+
if (a2a.status === 'assigned') {
|
|
246
|
+
clearInterval(timer);
|
|
247
|
+
this.watchTimers.delete(taskId);
|
|
248
|
+
this.emit({ type: 'task_assigned', taskId });
|
|
249
|
+
await this.executeTask(taskId, a2a);
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
// Retry next tick
|
|
253
|
+
}
|
|
254
|
+
}, ms);
|
|
255
|
+
this.watchTimers.set(taskId, timer);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ── Task execution ──────────────────────────────────────────────────────
|
|
259
|
+
|
|
260
|
+
private async executeTask(taskId: string, a2a: A2ATaskState): Promise<void> {
|
|
261
|
+
const exec = this.executions.get(taskId);
|
|
262
|
+
if (!exec) return;
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
exec.status = 'assigned';
|
|
266
|
+
|
|
267
|
+
// Accept task — get the ECIES-wrapped AES key
|
|
268
|
+
const acceptResult = await this.bb.acceptTask(taskId);
|
|
269
|
+
exec.task = acceptResult.task;
|
|
270
|
+
this.emit({ type: 'task_accepted', taskId });
|
|
271
|
+
|
|
272
|
+
// Get full task detail for the storage root hash
|
|
273
|
+
const detail = await this.bb.getTask(taskId);
|
|
274
|
+
const taskHash = detail.taskHash;
|
|
275
|
+
|
|
276
|
+
// Decrypt the wrapped key with the worker's private key
|
|
277
|
+
let instructions = '';
|
|
278
|
+
if (acceptResult.wrappedKey && taskHash) {
|
|
279
|
+
const wrappedBytes = this.decodeWrappedKey(acceptResult.wrappedKey);
|
|
280
|
+
const aesKey = await eciesDecrypt(wrappedBytes, this.wallet!.privateKey);
|
|
281
|
+
|
|
282
|
+
// Download ciphertext from storage via REST API
|
|
283
|
+
const storageResult = await this.bb.downloadBlob(taskHash);
|
|
284
|
+
const ciphertext = this.hexToBytes(storageResult.data);
|
|
285
|
+
|
|
286
|
+
// AES decrypt to get plaintext instructions
|
|
287
|
+
const plaintext = await aesDecrypt(ciphertext, aesKey);
|
|
288
|
+
instructions = new TextDecoder().decode(plaintext);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
exec.status = 'working';
|
|
292
|
+
this.emit({ type: 'task_working', taskId });
|
|
293
|
+
|
|
294
|
+
// Call the user-provided execution handler with decrypted instructions
|
|
295
|
+
const result = await this.config.executeTask({
|
|
296
|
+
taskId,
|
|
297
|
+
task: acceptResult.task,
|
|
298
|
+
instructions,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
exec.status = 'submitted';
|
|
302
|
+
this.emit({ type: 'task_executed', taskId });
|
|
303
|
+
|
|
304
|
+
// Submit result
|
|
305
|
+
const submitResult = await this.bb.submitResult(taskId, result);
|
|
306
|
+
|
|
307
|
+
exec.status = 'completed';
|
|
308
|
+
this.emit({ type: 'task_submitted', taskId, result: submitResult });
|
|
309
|
+
} catch (err) {
|
|
310
|
+
exec.status = 'failed';
|
|
311
|
+
exec.error = String(err);
|
|
312
|
+
this.emit({ type: 'task_failed', taskId, error: String(err) });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
private decodeWrappedKey(wrappedKey: Record<string, string>): Uint8Array {
|
|
319
|
+
// Backend returns wrapped key as hex or base64 in a record
|
|
320
|
+
const hex = Object.values(wrappedKey)[0];
|
|
321
|
+
if (!hex) throw new Error('Empty wrapped key');
|
|
322
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
323
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
324
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
325
|
+
bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
326
|
+
}
|
|
327
|
+
return bytes;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private hexToBytes(hex: string): Uint8Array {
|
|
331
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
332
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
333
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
334
|
+
bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
335
|
+
}
|
|
336
|
+
return bytes;
|
|
337
|
+
}
|
|
338
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -200,7 +200,7 @@ export class BlindMarket {
|
|
|
200
200
|
return this.req('POST', '/api/v1/submissions/submit', params);
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
// ── Agent deployment & management
|
|
203
|
+
// ── Agent deployment & management ─────────────────────────────────────────
|
|
204
204
|
|
|
205
205
|
/**
|
|
206
206
|
* Deploy a new agent. The backend generates a wallet, mints an INFT,
|
|
@@ -382,7 +382,7 @@ export class BlindMarket {
|
|
|
382
382
|
reasoning: string;
|
|
383
383
|
teeVerified?: boolean;
|
|
384
384
|
}> {
|
|
385
|
-
return this.req('POST', '/api/v1/verification/
|
|
385
|
+
return this.req('POST', '/api/v1/verification/verify', {
|
|
386
386
|
taskId: params.taskId,
|
|
387
387
|
taskCategory: params.taskCategory,
|
|
388
388
|
taskRequirements: params.taskRequirements,
|
|
@@ -424,7 +424,7 @@ export class BlindMarket {
|
|
|
424
424
|
return this.req<{ data: Hex }>('GET', `/api/v1/storage/${rootHash}`);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
// ── Messages
|
|
427
|
+
// ── Messages ─────────────────────────────────────────────────────────────
|
|
428
428
|
|
|
429
429
|
/** Send a message to another user or agent. */
|
|
430
430
|
async sendMessage(params: {
|
|
@@ -614,4 +614,23 @@ export {
|
|
|
614
614
|
} from './tools/index.js';
|
|
615
615
|
export type { Tool, ToolKit, ToolDefinition } from './tools/types.js';
|
|
616
616
|
export type { BlindMarketTools } from './tools/index.js';
|
|
617
|
-
export * from './
|
|
617
|
+
export * from './executor/index.js';
|
|
618
|
+
export * from './types.js';
|
|
619
|
+
|
|
620
|
+
// Chain abstraction layer
|
|
621
|
+
export { EVMChainAdapter } from './chain/evm/index.js';
|
|
622
|
+
export { createChainAdapter } from './chain/createChainAdapter.js';
|
|
623
|
+
export type { CreateChainAdapterOptions } from './chain/createChainAdapter.js';
|
|
624
|
+
export type { IBlindMarketChain } from './chain/IBlindMarketChain.js';
|
|
625
|
+
export type {
|
|
626
|
+
Network,
|
|
627
|
+
EVMNetwork,
|
|
628
|
+
BlockchainType,
|
|
629
|
+
CreateTaskParams,
|
|
630
|
+
DomainTask,
|
|
631
|
+
DomainTaskMeta,
|
|
632
|
+
DomainReputation,
|
|
633
|
+
DomainTxReceipt,
|
|
634
|
+
ChainSigner,
|
|
635
|
+
} from './chain/domain-types.js';
|
|
636
|
+
export { isEVMNetwork } from './network/resolve.js';
|
package/src/network/presets.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import type { Network } from '
|
|
1
|
+
import type { Network } from '../chain/domain-types.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Known-good network presets. Addresses pinned per SDK version so upgrading
|
|
5
5
|
* the SDK cannot silently move contracts under a consumer.
|
|
6
|
-
*
|
|
7
|
-
* testnet = 0G Galileo (chainId 16602) — addresses from
|
|
8
|
-
* contracts/deployments/0g-testnet.json (deployed 2026-04-15).
|
|
9
6
|
*/
|
|
7
|
+
|
|
8
|
+
export type NetworkName =
|
|
9
|
+
| 'testnet' // deprecated alias → og-testnet
|
|
10
|
+
| 'og-testnet'
|
|
11
|
+
| 'og-mainnet';
|
|
12
|
+
|
|
10
13
|
export const networks = {
|
|
11
|
-
|
|
14
|
+
// ── 0G EVM chains ─────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
'og-testnet': {
|
|
12
17
|
name: '0g-galileo-testnet',
|
|
13
|
-
|
|
18
|
+
chainType: 'evm' as const,
|
|
19
|
+
chainId: 16602,
|
|
14
20
|
rpc: ['https://evmrpc-testnet.0g.ai'],
|
|
15
21
|
contracts: {
|
|
16
22
|
escrow: '0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681',
|
|
@@ -22,6 +28,39 @@ export const networks = {
|
|
|
22
28
|
broker: 'https://broker.testnet.0g.ai',
|
|
23
29
|
explorer: 'https://chainscan-galileo.0g.ai',
|
|
24
30
|
},
|
|
25
|
-
} as const satisfies Record<string, Network>;
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
'og-mainnet': {
|
|
33
|
+
name: '0g-mainnet',
|
|
34
|
+
chainType: 'evm' as const,
|
|
35
|
+
chainId: 16661,
|
|
36
|
+
rpc: ['https://evmrpc.0g.ai'],
|
|
37
|
+
contracts: {
|
|
38
|
+
escrow: '0x3d0374963DaaD43e31d42373eb11156A8e8ce2Ff',
|
|
39
|
+
registry: '0x9CCF9c196006B573FaA9C9c9CebDd1296dbd5cE0',
|
|
40
|
+
reputation: '0x3af9232009C5da30AdA366B6E09849A040162A1a',
|
|
41
|
+
usdc: '0x0000000000000000000000000000000000000000',
|
|
42
|
+
},
|
|
43
|
+
indexer: 'https://indexer-storage-turbo.0g.ai',
|
|
44
|
+
broker: 'https://broker.0g.ai',
|
|
45
|
+
explorer: 'https://chainscan.0g.ai',
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// ── Backward-compat alias ──────────────────────────────────────────────
|
|
49
|
+
// Kept so existing code referencing 'testnet' doesn't break.
|
|
50
|
+
|
|
51
|
+
testnet: {
|
|
52
|
+
name: '0g-galileo-testnet',
|
|
53
|
+
chainType: 'evm' as const,
|
|
54
|
+
chainId: 16602,
|
|
55
|
+
rpc: ['https://evmrpc-testnet.0g.ai'],
|
|
56
|
+
contracts: {
|
|
57
|
+
escrow: '0xFd4F93F5A7BE144c405D1D8fbEC63Fb776207681',
|
|
58
|
+
registry: '0xeE52d780A47F77E8a4a1cEb236e3C65A48FbD828',
|
|
59
|
+
reputation: '0x4A6374Fae37E19E69ba43E7cf6994AC15F63256e',
|
|
60
|
+
usdc: '0x317227efcA18D004E12CA8046AEf7E1597458F25',
|
|
61
|
+
},
|
|
62
|
+
indexer: 'https://indexer-storage-testnet-turbo.0g.ai',
|
|
63
|
+
broker: 'https://broker.testnet.0g.ai',
|
|
64
|
+
explorer: 'https://chainscan-galileo.0g.ai',
|
|
65
|
+
},
|
|
66
|
+
} as const satisfies Record<NetworkName, Network>;
|
package/src/network/resolve.ts
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
import { ConfigError } from '../errors/index.js';
|
|
2
2
|
import { networks, type NetworkName } from './presets.js';
|
|
3
|
-
import type { Network } from '
|
|
3
|
+
import type { Network } from '../chain/domain-types.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Resolve a preset name or a
|
|
7
|
-
*
|
|
6
|
+
* Resolve a network preset name or a Network object to a canonical Network.
|
|
7
|
+
*
|
|
8
|
+
* When given a string, looks up the preset. When given a Network object,
|
|
9
|
+
* returns it as-is (pass-through for callers that already have a resolved
|
|
10
|
+
* network config).
|
|
8
11
|
*/
|
|
9
12
|
export function resolveNetwork(arg: NetworkName | Network): Network {
|
|
10
13
|
if (typeof arg === 'string') {
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
const net = networks[arg];
|
|
15
|
+
if (!net) {
|
|
16
|
+
throw new ConfigError(
|
|
17
|
+
'CONFIG/INVALID_NETWORK',
|
|
18
|
+
`Unknown network: "${arg}". Known presets: ${Object.keys(networks).join(', ')}`,
|
|
19
|
+
);
|
|
15
20
|
}
|
|
16
|
-
return
|
|
21
|
+
return net as unknown as Network;
|
|
17
22
|
}
|
|
18
23
|
return arg;
|
|
19
24
|
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Type guard: check if a Network is an EVM network.
|
|
28
|
+
*/
|
|
29
|
+
export function isEVMNetwork(network: Network): network is Network & { chainType: 'evm' } {
|
|
30
|
+
return network.chainType === 'evm';
|
|
31
|
+
}
|
package/src/network/types.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Network,
|
|
3
|
+
EVMNetwork,
|
|
4
|
+
} from '../chain/domain-types.js';
|
|
5
|
+
import type { NetworkName } from './presets.js';
|
|
2
6
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
export type {
|
|
8
|
+
Network,
|
|
9
|
+
EVMNetwork,
|
|
10
|
+
NetworkBase,
|
|
11
|
+
BlockchainType,
|
|
12
|
+
CreateTaskParams,
|
|
13
|
+
DomainTask,
|
|
14
|
+
DomainTaskMeta,
|
|
15
|
+
DomainReputation,
|
|
16
|
+
DomainTxReceipt,
|
|
17
|
+
ChainSigner,
|
|
18
|
+
} from '../chain/domain-types.js';
|
|
9
19
|
|
|
10
|
-
export
|
|
11
|
-
name: string;
|
|
12
|
-
chainId: bigint;
|
|
13
|
-
rpc: string[];
|
|
14
|
-
contracts: NetworkContracts;
|
|
15
|
-
indexer: string;
|
|
16
|
-
broker: string;
|
|
17
|
-
explorer?: string;
|
|
18
|
-
}
|
|
20
|
+
export type { NetworkName };
|
package/src/signer/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
import { A as Address, H as Hex, T as TaskId, b as TxReceiptLike, e as TaskStatus } from './types-BOG5Ub1z.cjs';
|
|
3
|
-
|
|
4
|
-
interface CreateTaskArgs {
|
|
5
|
-
taskHash: Hex;
|
|
6
|
-
token: Address;
|
|
7
|
-
amount: bigint;
|
|
8
|
-
category: string;
|
|
9
|
-
locationZone: string;
|
|
10
|
-
deadline: bigint;
|
|
11
|
-
}
|
|
12
|
-
interface OnChainTask {
|
|
13
|
-
taskId: TaskId;
|
|
14
|
-
agent: Address;
|
|
15
|
-
worker: Address;
|
|
16
|
-
token: Address;
|
|
17
|
-
amount: bigint;
|
|
18
|
-
taskHash: Hex;
|
|
19
|
-
evidenceHash: Hex;
|
|
20
|
-
status: TaskStatus;
|
|
21
|
-
createdAt: Date;
|
|
22
|
-
deadline: Date;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Typed ethers v6 wrapper for the BlindEscrow contract. Every state-changing
|
|
26
|
-
* method awaits one confirmation and returns a TxReceiptLike; every read
|
|
27
|
-
* returns decoded values. Ethers errors are mapped to ChainError via
|
|
28
|
-
* wrapChainError().
|
|
29
|
-
*/
|
|
30
|
-
declare class BlindEscrowClient {
|
|
31
|
-
readonly contract: ethers.Contract;
|
|
32
|
-
readonly address: Address;
|
|
33
|
-
constructor(address: Address, runner: ethers.ContractRunner);
|
|
34
|
-
/** Create a task and return its id + receipt. Reads the TaskCreated event for the id. */
|
|
35
|
-
createTask(args: CreateTaskArgs): Promise<{
|
|
36
|
-
taskId: TaskId;
|
|
37
|
-
receipt: TxReceiptLike;
|
|
38
|
-
}>;
|
|
39
|
-
assignWorker(taskId: TaskId, worker: Address): Promise<TxReceiptLike>;
|
|
40
|
-
submitEvidence(taskId: TaskId, evidenceHash: Hex): Promise<TxReceiptLike>;
|
|
41
|
-
completeVerification(taskId: TaskId, passed: boolean): Promise<TxReceiptLike>;
|
|
42
|
-
cancelTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
43
|
-
raiseDispute(taskId: TaskId): Promise<TxReceiptLike>;
|
|
44
|
-
resolveDispute(taskId: TaskId, workerFavored: boolean): Promise<TxReceiptLike>;
|
|
45
|
-
claimTimeout(taskId: TaskId): Promise<TxReceiptLike>;
|
|
46
|
-
getTask(taskId: TaskId): Promise<OnChainTask>;
|
|
47
|
-
isTaskExpired(taskId: TaskId): Promise<boolean>;
|
|
48
|
-
nextTaskId(): Promise<TaskId>;
|
|
49
|
-
feeBps(): Promise<bigint>;
|
|
50
|
-
private sendTx;
|
|
51
|
-
private extractTaskIdFromReceipt;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export { BlindEscrowClient as B, type CreateTaskArgs as C, type OnChainTask as O };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
import { A as Address, H as Hex, T as TaskId, b as TxReceiptLike, e as TaskStatus } from './types-BOG5Ub1z.js';
|
|
3
|
-
|
|
4
|
-
interface CreateTaskArgs {
|
|
5
|
-
taskHash: Hex;
|
|
6
|
-
token: Address;
|
|
7
|
-
amount: bigint;
|
|
8
|
-
category: string;
|
|
9
|
-
locationZone: string;
|
|
10
|
-
deadline: bigint;
|
|
11
|
-
}
|
|
12
|
-
interface OnChainTask {
|
|
13
|
-
taskId: TaskId;
|
|
14
|
-
agent: Address;
|
|
15
|
-
worker: Address;
|
|
16
|
-
token: Address;
|
|
17
|
-
amount: bigint;
|
|
18
|
-
taskHash: Hex;
|
|
19
|
-
evidenceHash: Hex;
|
|
20
|
-
status: TaskStatus;
|
|
21
|
-
createdAt: Date;
|
|
22
|
-
deadline: Date;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Typed ethers v6 wrapper for the BlindEscrow contract. Every state-changing
|
|
26
|
-
* method awaits one confirmation and returns a TxReceiptLike; every read
|
|
27
|
-
* returns decoded values. Ethers errors are mapped to ChainError via
|
|
28
|
-
* wrapChainError().
|
|
29
|
-
*/
|
|
30
|
-
declare class BlindEscrowClient {
|
|
31
|
-
readonly contract: ethers.Contract;
|
|
32
|
-
readonly address: Address;
|
|
33
|
-
constructor(address: Address, runner: ethers.ContractRunner);
|
|
34
|
-
/** Create a task and return its id + receipt. Reads the TaskCreated event for the id. */
|
|
35
|
-
createTask(args: CreateTaskArgs): Promise<{
|
|
36
|
-
taskId: TaskId;
|
|
37
|
-
receipt: TxReceiptLike;
|
|
38
|
-
}>;
|
|
39
|
-
assignWorker(taskId: TaskId, worker: Address): Promise<TxReceiptLike>;
|
|
40
|
-
submitEvidence(taskId: TaskId, evidenceHash: Hex): Promise<TxReceiptLike>;
|
|
41
|
-
completeVerification(taskId: TaskId, passed: boolean): Promise<TxReceiptLike>;
|
|
42
|
-
cancelTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
43
|
-
raiseDispute(taskId: TaskId): Promise<TxReceiptLike>;
|
|
44
|
-
resolveDispute(taskId: TaskId, workerFavored: boolean): Promise<TxReceiptLike>;
|
|
45
|
-
claimTimeout(taskId: TaskId): Promise<TxReceiptLike>;
|
|
46
|
-
getTask(taskId: TaskId): Promise<OnChainTask>;
|
|
47
|
-
isTaskExpired(taskId: TaskId): Promise<boolean>;
|
|
48
|
-
nextTaskId(): Promise<TaskId>;
|
|
49
|
-
feeBps(): Promise<bigint>;
|
|
50
|
-
private sendTx;
|
|
51
|
-
private extractTaskIdFromReceipt;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export { BlindEscrowClient as B, type CreateTaskArgs as C, type OnChainTask as O };
|