@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,113 @@
|
|
|
1
|
+
import type { A2ATaskState, AgentCapability, ExecutorProfile, Message } from '../types.js';
|
|
2
|
+
export interface WorkerRuntimeConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiBase?: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
capabilities: AgentCapability[];
|
|
7
|
+
executeTask: ExecuteTaskHandler;
|
|
8
|
+
existingPrivateKey?: string;
|
|
9
|
+
existingAddress?: string;
|
|
10
|
+
existingPublicKey?: string;
|
|
11
|
+
minReward?: string;
|
|
12
|
+
preferredCapabilities?: AgentCapability[];
|
|
13
|
+
browseIntervalMs?: number;
|
|
14
|
+
watchIntervalMs?: number;
|
|
15
|
+
maxConcurrentTasks?: number;
|
|
16
|
+
}
|
|
17
|
+
export type ExecuteTaskHandler = (ctx: TaskContext) => Promise<Record<string, unknown>>;
|
|
18
|
+
export interface TaskContext {
|
|
19
|
+
taskId: string;
|
|
20
|
+
task: A2ATaskState;
|
|
21
|
+
instructions: string;
|
|
22
|
+
}
|
|
23
|
+
export interface TaskExecutionInfo {
|
|
24
|
+
taskId: string;
|
|
25
|
+
status: 'bidding' | 'assigned' | 'working' | 'submitted' | 'completed' | 'failed';
|
|
26
|
+
task?: A2ATaskState;
|
|
27
|
+
error?: string;
|
|
28
|
+
startedAt: number;
|
|
29
|
+
}
|
|
30
|
+
export type WorkerRuntimeEvent = {
|
|
31
|
+
type: 'started';
|
|
32
|
+
} | {
|
|
33
|
+
type: 'stopped';
|
|
34
|
+
} | {
|
|
35
|
+
type: 'paused';
|
|
36
|
+
} | {
|
|
37
|
+
type: 'resumed';
|
|
38
|
+
} | {
|
|
39
|
+
type: 'registered';
|
|
40
|
+
profile: ExecutorProfile;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'task_found';
|
|
43
|
+
taskId: string;
|
|
44
|
+
task: A2ATaskState;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'task_bidded';
|
|
47
|
+
taskId: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'task_assigned';
|
|
50
|
+
taskId: string;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'task_accepted';
|
|
53
|
+
taskId: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'task_working';
|
|
56
|
+
taskId: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: 'task_executed';
|
|
59
|
+
taskId: string;
|
|
60
|
+
} | {
|
|
61
|
+
type: 'task_submitted';
|
|
62
|
+
taskId: string;
|
|
63
|
+
result: Record<string, unknown>;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'task_failed';
|
|
66
|
+
taskId: string;
|
|
67
|
+
error: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'message_received';
|
|
70
|
+
message: Message;
|
|
71
|
+
count: number;
|
|
72
|
+
} | {
|
|
73
|
+
type: 'browse_done';
|
|
74
|
+
found: number;
|
|
75
|
+
} | {
|
|
76
|
+
type: 'error';
|
|
77
|
+
error: string;
|
|
78
|
+
};
|
|
79
|
+
export declare class WorkerRuntime {
|
|
80
|
+
private bb;
|
|
81
|
+
private config;
|
|
82
|
+
private wallet?;
|
|
83
|
+
private profile?;
|
|
84
|
+
private running;
|
|
85
|
+
private paused;
|
|
86
|
+
private browseTimer?;
|
|
87
|
+
private watchTimers;
|
|
88
|
+
private executions;
|
|
89
|
+
private listeners;
|
|
90
|
+
constructor(config: WorkerRuntimeConfig);
|
|
91
|
+
get isRunning(): boolean;
|
|
92
|
+
get isPaused(): boolean;
|
|
93
|
+
get activeExecutions(): TaskExecutionInfo[];
|
|
94
|
+
/** Get own executor profile (available after start). */
|
|
95
|
+
get executorProfile(): ExecutorProfile | undefined;
|
|
96
|
+
/** Get own wallet info (available after start). */
|
|
97
|
+
get executorWallet(): {
|
|
98
|
+
address: string;
|
|
99
|
+
publicKey: string;
|
|
100
|
+
} | undefined;
|
|
101
|
+
on(listener: (event: WorkerRuntimeEvent) => void): () => void;
|
|
102
|
+
private emit;
|
|
103
|
+
start(): Promise<ExecutorProfile>;
|
|
104
|
+
stop(): void;
|
|
105
|
+
pause(): void;
|
|
106
|
+
resume(): void;
|
|
107
|
+
private startBrowseLoop;
|
|
108
|
+
private browse;
|
|
109
|
+
private watchForAssignment;
|
|
110
|
+
private executeTask;
|
|
111
|
+
private decodeWrappedKey;
|
|
112
|
+
private hexToBytes;
|
|
113
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { BlindMarket } from '../index.js';
|
|
2
|
+
import { eciesDecrypt, aesDecrypt } from '../crypto/index.js';
|
|
3
|
+
// ── Defaults ────────────────────────────────────────────────────────────────
|
|
4
|
+
const DEFAULTS = {
|
|
5
|
+
browseIntervalMs: 15_000,
|
|
6
|
+
watchIntervalMs: 5_000,
|
|
7
|
+
maxConcurrentTasks: 3,
|
|
8
|
+
};
|
|
9
|
+
// ── WorkerRuntime ───────────────────────────────────────────────────────────
|
|
10
|
+
export class WorkerRuntime {
|
|
11
|
+
bb;
|
|
12
|
+
config;
|
|
13
|
+
wallet;
|
|
14
|
+
profile;
|
|
15
|
+
running = false;
|
|
16
|
+
paused = false;
|
|
17
|
+
browseTimer;
|
|
18
|
+
watchTimers = new Map();
|
|
19
|
+
executions = new Map();
|
|
20
|
+
listeners = new Set();
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.config = { ...DEFAULTS, ...config };
|
|
23
|
+
this.bb = new BlindMarket({ apiKey: config.apiKey, apiBase: config.apiBase });
|
|
24
|
+
}
|
|
25
|
+
// ── Status ──────────────────────────────────────────────────────────────
|
|
26
|
+
get isRunning() {
|
|
27
|
+
return this.running;
|
|
28
|
+
}
|
|
29
|
+
get isPaused() {
|
|
30
|
+
return this.paused;
|
|
31
|
+
}
|
|
32
|
+
get activeExecutions() {
|
|
33
|
+
return [...this.executions.values()];
|
|
34
|
+
}
|
|
35
|
+
/** Get own executor profile (available after start). */
|
|
36
|
+
get executorProfile() {
|
|
37
|
+
return this.profile;
|
|
38
|
+
}
|
|
39
|
+
/** Get own wallet info (available after start). */
|
|
40
|
+
get executorWallet() {
|
|
41
|
+
return this.wallet;
|
|
42
|
+
}
|
|
43
|
+
// ── Events ──────────────────────────────────────────────────────────────
|
|
44
|
+
on(listener) {
|
|
45
|
+
this.listeners.add(listener);
|
|
46
|
+
return () => this.listeners.delete(listener);
|
|
47
|
+
}
|
|
48
|
+
emit(event) {
|
|
49
|
+
for (const l of this.listeners)
|
|
50
|
+
l(event);
|
|
51
|
+
}
|
|
52
|
+
// ── Lifecycle ───────────────────────────────────────────────────────────
|
|
53
|
+
async start() {
|
|
54
|
+
if (this.running)
|
|
55
|
+
return this.profile;
|
|
56
|
+
// 1. Register or restore executor
|
|
57
|
+
if (this.config.existingPrivateKey && this.config.existingAddress && this.config.existingPublicKey) {
|
|
58
|
+
this.wallet = {
|
|
59
|
+
address: this.config.existingAddress,
|
|
60
|
+
privateKey: this.config.existingPrivateKey,
|
|
61
|
+
publicKey: this.config.existingPublicKey,
|
|
62
|
+
};
|
|
63
|
+
// Fetch existing profile — backend identifies by API key
|
|
64
|
+
const result = await this.bb.getExecutorProfile();
|
|
65
|
+
this.profile = result.agent;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const result = await this.bb.createAgent({
|
|
69
|
+
displayName: this.config.displayName,
|
|
70
|
+
capabilities: this.config.capabilities,
|
|
71
|
+
minReward: this.config.minReward,
|
|
72
|
+
preferredCapabilities: this.config.preferredCapabilities,
|
|
73
|
+
});
|
|
74
|
+
this.wallet = {
|
|
75
|
+
address: result.wallet.address,
|
|
76
|
+
privateKey: result.wallet.privateKey,
|
|
77
|
+
publicKey: result.wallet.publicKey,
|
|
78
|
+
};
|
|
79
|
+
this.profile = result.executor;
|
|
80
|
+
}
|
|
81
|
+
this.emit({ type: 'registered', profile: this.profile });
|
|
82
|
+
// 2. Start the browse loop
|
|
83
|
+
this.running = true;
|
|
84
|
+
this.startBrowseLoop();
|
|
85
|
+
this.emit({ type: 'started' });
|
|
86
|
+
return this.profile;
|
|
87
|
+
}
|
|
88
|
+
stop() {
|
|
89
|
+
this.running = false;
|
|
90
|
+
if (this.browseTimer) {
|
|
91
|
+
clearInterval(this.browseTimer);
|
|
92
|
+
this.browseTimer = undefined;
|
|
93
|
+
}
|
|
94
|
+
for (const t of this.watchTimers.values())
|
|
95
|
+
clearInterval(t);
|
|
96
|
+
this.watchTimers.clear();
|
|
97
|
+
this.emit({ type: 'stopped' });
|
|
98
|
+
}
|
|
99
|
+
pause() {
|
|
100
|
+
if (!this.running || this.paused)
|
|
101
|
+
return;
|
|
102
|
+
this.paused = true;
|
|
103
|
+
this.emit({ type: 'paused' });
|
|
104
|
+
}
|
|
105
|
+
resume() {
|
|
106
|
+
if (!this.running || !this.paused)
|
|
107
|
+
return;
|
|
108
|
+
this.paused = false;
|
|
109
|
+
this.emit({ type: 'resumed' });
|
|
110
|
+
// Immediately browse instead of waiting for next interval
|
|
111
|
+
this.browse();
|
|
112
|
+
}
|
|
113
|
+
// ── Browse loop ─────────────────────────────────────────────────────────
|
|
114
|
+
startBrowseLoop() {
|
|
115
|
+
const ms = this.config.browseIntervalMs;
|
|
116
|
+
this.browseTimer = setInterval(() => this.browse(), ms);
|
|
117
|
+
this.browse();
|
|
118
|
+
}
|
|
119
|
+
async browse() {
|
|
120
|
+
if (this.paused)
|
|
121
|
+
return;
|
|
122
|
+
try {
|
|
123
|
+
const active = this.activeExecutions;
|
|
124
|
+
const inFlight = active.filter(e => e.status === 'bidding' || e.status === 'working').length;
|
|
125
|
+
if (inFlight >= this.config.maxConcurrentTasks)
|
|
126
|
+
return;
|
|
127
|
+
const result = await this.bb.browseA2ATasks({
|
|
128
|
+
capabilities: this.config.capabilities,
|
|
129
|
+
});
|
|
130
|
+
this.emit({ type: 'browse_done', found: result.tasks.length });
|
|
131
|
+
for (const task of result.tasks) {
|
|
132
|
+
if (this.executions.has(task.taskId))
|
|
133
|
+
continue;
|
|
134
|
+
if (task.status !== 'open' && task.status !== 'bidding')
|
|
135
|
+
continue;
|
|
136
|
+
if (task.executorAddress && task.executorAddress !== this.wallet?.address)
|
|
137
|
+
continue;
|
|
138
|
+
this.executions.set(task.taskId, {
|
|
139
|
+
taskId: task.taskId,
|
|
140
|
+
status: 'bidding',
|
|
141
|
+
task,
|
|
142
|
+
startedAt: Date.now(),
|
|
143
|
+
});
|
|
144
|
+
this.emit({ type: 'task_found', taskId: task.taskId, task });
|
|
145
|
+
await this.bb.bidOnTask(task.taskId);
|
|
146
|
+
this.emit({ type: 'task_bidded', taskId: task.taskId });
|
|
147
|
+
this.watchForAssignment(task.taskId);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
this.emit({ type: 'error', error: `Browse failed: ${err}` });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// ── Assignment watching ─────────────────────────────────────────────────
|
|
155
|
+
watchForAssignment(taskId) {
|
|
156
|
+
if (!this.running)
|
|
157
|
+
return;
|
|
158
|
+
const ms = this.config.watchIntervalMs;
|
|
159
|
+
const timer = setInterval(async () => {
|
|
160
|
+
if (!this.running || this.paused)
|
|
161
|
+
return;
|
|
162
|
+
try {
|
|
163
|
+
const detail = await this.bb.getTask(taskId);
|
|
164
|
+
const a2a = detail.a2aState;
|
|
165
|
+
if (!a2a)
|
|
166
|
+
return;
|
|
167
|
+
if (a2a.status === 'assigned') {
|
|
168
|
+
clearInterval(timer);
|
|
169
|
+
this.watchTimers.delete(taskId);
|
|
170
|
+
this.emit({ type: 'task_assigned', taskId });
|
|
171
|
+
await this.executeTask(taskId, a2a);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Retry next tick
|
|
176
|
+
}
|
|
177
|
+
}, ms);
|
|
178
|
+
this.watchTimers.set(taskId, timer);
|
|
179
|
+
}
|
|
180
|
+
// ── Task execution ──────────────────────────────────────────────────────
|
|
181
|
+
async executeTask(taskId, a2a) {
|
|
182
|
+
const exec = this.executions.get(taskId);
|
|
183
|
+
if (!exec)
|
|
184
|
+
return;
|
|
185
|
+
try {
|
|
186
|
+
exec.status = 'assigned';
|
|
187
|
+
// Accept task — get the ECIES-wrapped AES key
|
|
188
|
+
const acceptResult = await this.bb.acceptTask(taskId);
|
|
189
|
+
exec.task = acceptResult.task;
|
|
190
|
+
this.emit({ type: 'task_accepted', taskId });
|
|
191
|
+
// Get full task detail for the storage root hash
|
|
192
|
+
const detail = await this.bb.getTask(taskId);
|
|
193
|
+
const taskHash = detail.taskHash;
|
|
194
|
+
// Decrypt the wrapped key with the worker's private key
|
|
195
|
+
let instructions = '';
|
|
196
|
+
if (acceptResult.wrappedKey && taskHash) {
|
|
197
|
+
const wrappedBytes = this.decodeWrappedKey(acceptResult.wrappedKey);
|
|
198
|
+
const aesKey = await eciesDecrypt(wrappedBytes, this.wallet.privateKey);
|
|
199
|
+
// Download ciphertext from storage via REST API
|
|
200
|
+
const storageResult = await this.bb.downloadBlob(taskHash);
|
|
201
|
+
const ciphertext = this.hexToBytes(storageResult.data);
|
|
202
|
+
// AES decrypt to get plaintext instructions
|
|
203
|
+
const plaintext = await aesDecrypt(ciphertext, aesKey);
|
|
204
|
+
instructions = new TextDecoder().decode(plaintext);
|
|
205
|
+
}
|
|
206
|
+
exec.status = 'working';
|
|
207
|
+
this.emit({ type: 'task_working', taskId });
|
|
208
|
+
// Call the user-provided execution handler with decrypted instructions
|
|
209
|
+
const result = await this.config.executeTask({
|
|
210
|
+
taskId,
|
|
211
|
+
task: acceptResult.task,
|
|
212
|
+
instructions,
|
|
213
|
+
});
|
|
214
|
+
exec.status = 'submitted';
|
|
215
|
+
this.emit({ type: 'task_executed', taskId });
|
|
216
|
+
// Submit result
|
|
217
|
+
const submitResult = await this.bb.submitResult(taskId, result);
|
|
218
|
+
exec.status = 'completed';
|
|
219
|
+
this.emit({ type: 'task_submitted', taskId, result: submitResult });
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
exec.status = 'failed';
|
|
223
|
+
exec.error = String(err);
|
|
224
|
+
this.emit({ type: 'task_failed', taskId, error: String(err) });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
228
|
+
decodeWrappedKey(wrappedKey) {
|
|
229
|
+
// Backend returns wrapped key as hex or base64 in a record
|
|
230
|
+
const hex = Object.values(wrappedKey)[0];
|
|
231
|
+
if (!hex)
|
|
232
|
+
throw new Error('Empty wrapped key');
|
|
233
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
234
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
235
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
236
|
+
bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
237
|
+
}
|
|
238
|
+
return bytes;
|
|
239
|
+
}
|
|
240
|
+
hexToBytes(hex) {
|
|
241
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
242
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
243
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
244
|
+
bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
|
|
245
|
+
}
|
|
246
|
+
return bytes;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WorkerRuntime, type WorkerRuntimeConfig, type ExecuteTaskHandler, type TaskContext, type TaskExecutionInfo, type WorkerRuntimeEvent, } from './WorkerRuntime.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WorkerRuntime, } from './WorkerRuntime.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -343,4 +343,11 @@ export { ApiError };
|
|
|
343
343
|
export { tools, createBlindMarketTools, createTaskTools, createAgentManagementTools, createA2ATools, toLangChainTools, toVercelTools, toOpenAITools, toClaudeTools, } from './tools/index.js';
|
|
344
344
|
export type { Tool, ToolKit, ToolDefinition } from './tools/types.js';
|
|
345
345
|
export type { BlindMarketTools } from './tools/index.js';
|
|
346
|
+
export * from './executor/index.js';
|
|
346
347
|
export * from './types.js';
|
|
348
|
+
export { EVMChainAdapter } from './chain/evm/index.js';
|
|
349
|
+
export { createChainAdapter } from './chain/createChainAdapter.js';
|
|
350
|
+
export type { CreateChainAdapterOptions } from './chain/createChainAdapter.js';
|
|
351
|
+
export type { IBlindMarketChain } from './chain/IBlindMarketChain.js';
|
|
352
|
+
export type { Network, EVMNetwork, BlockchainType, CreateTaskParams, DomainTask, DomainTaskMeta, DomainReputation, DomainTxReceipt, ChainSigner, } from './chain/domain-types.js';
|
|
353
|
+
export { isEVMNetwork } from './network/resolve.js';
|
package/dist/index.js
CHANGED
|
@@ -130,7 +130,7 @@ export class BlindMarket {
|
|
|
130
130
|
async submitEvidence(params) {
|
|
131
131
|
return this.req('POST', '/api/v1/submissions/submit', params);
|
|
132
132
|
}
|
|
133
|
-
// ── Agent deployment & management
|
|
133
|
+
// ── Agent deployment & management ─────────────────────────────────────────
|
|
134
134
|
/**
|
|
135
135
|
* Deploy a new agent. The backend generates a wallet, mints an INFT,
|
|
136
136
|
* and returns the agent descriptor.
|
|
@@ -274,7 +274,7 @@ export class BlindMarket {
|
|
|
274
274
|
* Trigger TEE / AI verification for a task.
|
|
275
275
|
*/
|
|
276
276
|
async verify(params) {
|
|
277
|
-
return this.req('POST', '/api/v1/verification/
|
|
277
|
+
return this.req('POST', '/api/v1/verification/verify', {
|
|
278
278
|
taskId: params.taskId,
|
|
279
279
|
taskCategory: params.taskCategory,
|
|
280
280
|
taskRequirements: params.taskRequirements,
|
|
@@ -307,7 +307,7 @@ export class BlindMarket {
|
|
|
307
307
|
async downloadBlob(rootHash) {
|
|
308
308
|
return this.req('GET', `/api/v1/storage/${rootHash}`);
|
|
309
309
|
}
|
|
310
|
-
// ── Messages
|
|
310
|
+
// ── Messages ─────────────────────────────────────────────────────────────
|
|
311
311
|
/** Send a message to another user or agent. */
|
|
312
312
|
async sendMessage(params) {
|
|
313
313
|
return this.req('POST', '/api/v1/messages/send', params);
|
|
@@ -458,4 +458,9 @@ export class BlindMarket {
|
|
|
458
458
|
export { ethers };
|
|
459
459
|
export { ApiError };
|
|
460
460
|
export { tools, createBlindMarketTools, createTaskTools, createAgentManagementTools, createA2ATools, toLangChainTools, toVercelTools, toOpenAITools, toClaudeTools, } from './tools/index.js';
|
|
461
|
+
export * from './executor/index.js';
|
|
461
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,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
|
|
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;
|
package/dist/network/presets.js
CHANGED
|
@@ -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
|
-
|
|
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 '
|
|
2
|
+
import type { Network } from '../chain/domain-types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Resolve a preset name or a
|
|
5
|
-
*
|
|
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
|
+
};
|
package/dist/network/resolve.js
CHANGED
|
@@ -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
|
|
5
|
-
*
|
|
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
|
|
10
|
-
if (!
|
|
11
|
-
|
|
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
|
|
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
|
+
}
|
package/dist/network/types.d.ts
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
registry: Address;
|
|
5
|
-
reputation: Address;
|
|
6
|
-
usdc: Address;
|
|
7
|
-
}
|
|
8
|
-
export interface Network {
|
|
9
|
-
name: string;
|
|
10
|
-
chainId: bigint;
|
|
11
|
-
rpc: string[];
|
|
12
|
-
contracts: NetworkContracts;
|
|
13
|
-
indexer: string;
|
|
14
|
-
broker: string;
|
|
15
|
-
explorer?: string;
|
|
16
|
-
}
|
|
1
|
+
import type { NetworkName } from './presets.js';
|
|
2
|
+
export type { Network, EVMNetwork, NetworkBase, BlockchainType, CreateTaskParams, DomainTask, DomainTaskMeta, DomainReputation, DomainTxReceipt, ChainSigner, } from '../chain/domain-types.js';
|
|
3
|
+
export type { NetworkName };
|
package/dist/types.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export interface Reward {
|
|
|
12
12
|
token: Address | TokenSymbol;
|
|
13
13
|
amount: bigint;
|
|
14
14
|
}
|
|
15
|
-
export type TaskStatus = 'funded' | 'assigned' | 'submitted' | 'verified' | 'completed' | 'cancelled';
|
|
15
|
+
export type TaskStatus = 'funded' | 'assigned' | 'submitted' | 'verified' | 'completed' | 'cancelled' | 'disputed';
|
|
16
16
|
export interface TaskMetadata {
|
|
17
17
|
category: string;
|
|
18
18
|
locationZone: string;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import type { Address, Hex, TaskId, TaskStatus, TxReceiptLike } from '../types.j
|
|
|
3
3
|
import { BlindEscrowAbi } from './abi/index.js';
|
|
4
4
|
import { wrapChainError } from './errors.js';
|
|
5
5
|
|
|
6
|
-
const STATUS_BY_INDEX: TaskStatus[] = ['funded', 'assigned', 'submitted', 'verified', 'completed', 'cancelled'];
|
|
6
|
+
const STATUS_BY_INDEX: TaskStatus[] = ['funded', 'assigned', 'submitted', 'verified', 'completed', 'cancelled', 'disputed'];
|
|
7
7
|
|
|
8
8
|
export interface CreateTaskArgs {
|
|
9
9
|
taskHash: Hex;
|
|
@@ -23,6 +23,8 @@ export interface OnChainTask {
|
|
|
23
23
|
taskHash: Hex;
|
|
24
24
|
evidenceHash: Hex;
|
|
25
25
|
status: TaskStatus;
|
|
26
|
+
category: string;
|
|
27
|
+
locationZone: string;
|
|
26
28
|
createdAt: Date;
|
|
27
29
|
deadline: Date;
|
|
28
30
|
}
|
|
@@ -168,10 +170,15 @@ function toReceipt(rec: ethers.ContractTransactionReceipt | null): TxReceiptLike
|
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
function decodeTask(taskId: TaskId, raw: ethers.Result): OnChainTask {
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
+
// Live Task struct (12 fields) from BlindEscrow.getTask(): agent, worker,
|
|
174
|
+
// token, amount, taskHash, evidenceHash, status, category, locationZone,
|
|
175
|
+
// createdAt, deadline, submissionAttempts. The old decode read createdAt from
|
|
176
|
+
// arr[7] (actually category) and deadline from arr[8] (actually locationZone),
|
|
177
|
+
// yielding Invalid Date and discarding category/locationZone.
|
|
173
178
|
const arr = raw as unknown as unknown[];
|
|
174
179
|
const statusIndex = Number(arr[6]);
|
|
180
|
+
const status = STATUS_BY_INDEX[statusIndex];
|
|
181
|
+
if (!status) throw new Error(`BlindEscrow.getTask returned unknown status index ${statusIndex}`);
|
|
175
182
|
return {
|
|
176
183
|
taskId,
|
|
177
184
|
agent: arr[0] as Address,
|
|
@@ -180,8 +187,10 @@ function decodeTask(taskId: TaskId, raw: ethers.Result): OnChainTask {
|
|
|
180
187
|
amount: BigInt(arr[3] as bigint | number),
|
|
181
188
|
taskHash: arr[4] as Hex,
|
|
182
189
|
evidenceHash: arr[5] as Hex,
|
|
183
|
-
status
|
|
184
|
-
|
|
185
|
-
|
|
190
|
+
status,
|
|
191
|
+
category: arr[7] as string,
|
|
192
|
+
locationZone: arr[8] as string,
|
|
193
|
+
createdAt: new Date(Number(arr[9] as bigint | number) * 1000),
|
|
194
|
+
deadline: new Date(Number(arr[10] as bigint | number) * 1000),
|
|
186
195
|
};
|
|
187
196
|
}
|