@blindmarket/sdk 0.1.4

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 (244) hide show
  1. package/README.md +72 -0
  2. package/biome.json +19 -0
  3. package/dist/BlindEscrowClient-CyPuKMge.d.cts +54 -0
  4. package/dist/BlindEscrowClient-R7iGpE-n.d.ts +54 -0
  5. package/dist/KeyStore-Be_SSpCt.d.cts +21 -0
  6. package/dist/KeyStore-k1JgYPJY.d.ts +21 -0
  7. package/dist/Signer-BnqH_qew.d.cts +38 -0
  8. package/dist/Signer-LColE0Uo.d.ts +38 -0
  9. package/dist/Storage-4QOrh7rm.d.ts +17 -0
  10. package/dist/Storage-Cf4IJRMk.d.cts +17 -0
  11. package/dist/TaskRegistryClient-Ch6lYqM_.d.ts +24 -0
  12. package/dist/TaskRegistryClient-CrQjddDc.d.cts +24 -0
  13. package/dist/aes-J-7HrHze.d.cts +17 -0
  14. package/dist/aes-J-7HrHze.d.ts +17 -0
  15. package/dist/agent/Agent.d.ts +59 -0
  16. package/dist/agent/Agent.js +73 -0
  17. package/dist/agent/index.cjs +425 -0
  18. package/dist/agent/index.cjs.map +1 -0
  19. package/dist/agent/index.d.cts +63 -0
  20. package/dist/agent/index.d.ts +1 -0
  21. package/dist/agent/index.js +1 -0
  22. package/dist/agent/index.js.map +1 -0
  23. package/dist/api/index.cjs +4 -0
  24. package/dist/api/index.cjs.map +1 -0
  25. package/dist/api/index.d.cts +2 -0
  26. package/dist/api/index.d.ts +1 -0
  27. package/dist/api/index.js +1 -0
  28. package/dist/api/index.js.map +1 -0
  29. package/dist/chain/BlindEscrowClient.d.ts +51 -0
  30. package/dist/chain/BlindEscrowClient.js +142 -0
  31. package/dist/chain/BlindReputationClient.d.ts +16 -0
  32. package/dist/chain/BlindReputationClient.js +45 -0
  33. package/dist/chain/ChainClient.d.ts +26 -0
  34. package/dist/chain/ChainClient.js +46 -0
  35. package/dist/chain/TaskRegistryClient.d.ts +21 -0
  36. package/dist/chain/TaskRegistryClient.js +70 -0
  37. package/dist/chain/abi/BlindEscrow.json +1113 -0
  38. package/dist/chain/abi/BlindReputation.json +447 -0
  39. package/dist/chain/abi/TaskRegistry.json +586 -0
  40. package/dist/chain/abi/index.d.ts +4 -0
  41. package/dist/chain/abi/index.js +4 -0
  42. package/dist/chain/errors.d.ts +8 -0
  43. package/dist/chain/errors.js +32 -0
  44. package/dist/chain/index.cjs +2484 -0
  45. package/dist/chain/index.cjs.map +1 -0
  46. package/dist/chain/index.d.cts +2305 -0
  47. package/dist/chain/index.d.ts +6 -0
  48. package/dist/chain/index.js +6 -0
  49. package/dist/chain/index.js.map +1 -0
  50. package/dist/compute/index.cjs +4 -0
  51. package/dist/compute/index.cjs.map +1 -0
  52. package/dist/compute/index.d.cts +2 -0
  53. package/dist/compute/index.d.ts +1 -0
  54. package/dist/compute/index.js +1 -0
  55. package/dist/compute/index.js.map +1 -0
  56. package/dist/crypto/aes.d.ts +15 -0
  57. package/dist/crypto/aes.js +81 -0
  58. package/dist/crypto/constants.d.ts +7 -0
  59. package/dist/crypto/constants.js +7 -0
  60. package/dist/crypto/ecies.d.ts +8 -0
  61. package/dist/crypto/ecies.js +51 -0
  62. package/dist/crypto/envelope.d.ts +35 -0
  63. package/dist/crypto/envelope.js +103 -0
  64. package/dist/crypto/hkdf.d.ts +5 -0
  65. package/dist/crypto/hkdf.js +34 -0
  66. package/dist/crypto/index.cjs +424 -0
  67. package/dist/crypto/index.cjs.map +1 -0
  68. package/dist/crypto/index.d.cts +74 -0
  69. package/dist/crypto/index.d.ts +6 -0
  70. package/dist/crypto/index.js +6 -0
  71. package/dist/crypto/index.js.map +1 -0
  72. package/dist/crypto/keys.d.ts +12 -0
  73. package/dist/crypto/keys.js +42 -0
  74. package/dist/errors/BlindBountyError.d.ts +14 -0
  75. package/dist/errors/BlindBountyError.js +30 -0
  76. package/dist/errors/codes.d.ts +19 -0
  77. package/dist/errors/codes.js +48 -0
  78. package/dist/errors/index.cjs +136 -0
  79. package/dist/errors/index.cjs.map +1 -0
  80. package/dist/errors/index.d.cts +60 -0
  81. package/dist/errors/index.d.ts +3 -0
  82. package/dist/errors/index.js +3 -0
  83. package/dist/errors/index.js.map +1 -0
  84. package/dist/errors/subclasses.d.ts +26 -0
  85. package/dist/errors/subclasses.js +41 -0
  86. package/dist/events/EventBus.d.ts +13 -0
  87. package/dist/events/EventBus.js +41 -0
  88. package/dist/events/index.cjs +41 -0
  89. package/dist/events/index.cjs.map +1 -0
  90. package/dist/events/index.d.cts +61 -0
  91. package/dist/events/index.d.ts +2 -0
  92. package/dist/events/index.js +2 -0
  93. package/dist/events/index.js.map +1 -0
  94. package/dist/events/types.d.ts +45 -0
  95. package/dist/events/types.js +1 -0
  96. package/dist/index.cjs +4 -0
  97. package/dist/index.cjs.map +1 -0
  98. package/dist/index.d.cts +2 -0
  99. package/dist/index.d.ts +129 -0
  100. package/dist/index.js +154 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/keystore/InMemoryKeyStore.d.ts +21 -0
  103. package/dist/keystore/InMemoryKeyStore.js +111 -0
  104. package/dist/keystore/KeyStore.d.ts +18 -0
  105. package/dist/keystore/KeyStore.js +1 -0
  106. package/dist/keystore/index.cjs +335 -0
  107. package/dist/keystore/index.cjs.map +1 -0
  108. package/dist/keystore/index.d.cts +23 -0
  109. package/dist/keystore/index.d.ts +2 -0
  110. package/dist/keystore/index.js +2 -0
  111. package/dist/keystore/index.js.map +1 -0
  112. package/dist/network/index.cjs +74 -0
  113. package/dist/network/index.cjs.map +1 -0
  114. package/dist/network/index.d.cts +36 -0
  115. package/dist/network/index.d.ts +3 -0
  116. package/dist/network/index.js +3 -0
  117. package/dist/network/index.js.map +1 -0
  118. package/dist/network/presets.d.ts +24 -0
  119. package/dist/network/presets.js +23 -0
  120. package/dist/network/resolve.d.ts +7 -0
  121. package/dist/network/resolve.js +17 -0
  122. package/dist/network/types.d.ts +16 -0
  123. package/dist/network/types.js +1 -0
  124. package/dist/signer/EthersSigner.d.ts +24 -0
  125. package/dist/signer/EthersSigner.js +68 -0
  126. package/dist/signer/PrivateKeySigner.d.ts +14 -0
  127. package/dist/signer/PrivateKeySigner.js +18 -0
  128. package/dist/signer/Signer.d.ts +35 -0
  129. package/dist/signer/Signer.js +1 -0
  130. package/dist/signer/index.cjs +121 -0
  131. package/dist/signer/index.cjs.map +1 -0
  132. package/dist/signer/index.d.cts +40 -0
  133. package/dist/signer/index.d.ts +3 -0
  134. package/dist/signer/index.js +3 -0
  135. package/dist/signer/index.js.map +1 -0
  136. package/dist/storage/MemoryStorage.d.ts +18 -0
  137. package/dist/storage/MemoryStorage.js +40 -0
  138. package/dist/storage/Storage.d.ts +14 -0
  139. package/dist/storage/Storage.js +1 -0
  140. package/dist/storage/ZgStorage.d.ts +24 -0
  141. package/dist/storage/ZgStorage.js +102 -0
  142. package/dist/storage/index.cjs +221 -0
  143. package/dist/storage/index.cjs.map +1 -0
  144. package/dist/storage/index.d.cts +44 -0
  145. package/dist/storage/index.d.ts +3 -0
  146. package/dist/storage/index.js +3 -0
  147. package/dist/storage/index.js.map +1 -0
  148. package/dist/testing/index.cjs +4 -0
  149. package/dist/testing/index.cjs.map +1 -0
  150. package/dist/testing/index.d.cts +2 -0
  151. package/dist/testing/index.d.ts +1 -0
  152. package/dist/testing/index.js +1 -0
  153. package/dist/testing/index.js.map +1 -0
  154. package/dist/types-BOG5Ub1z.d.cts +31 -0
  155. package/dist/types-BOG5Ub1z.d.ts +31 -0
  156. package/dist/types-V7_ZmUb-.d.cts +19 -0
  157. package/dist/types-hAsITUQ7.d.ts +19 -0
  158. package/dist/types.d.ts +58 -0
  159. package/dist/types.js +1 -0
  160. package/dist/verifier/index.cjs +4 -0
  161. package/dist/verifier/index.cjs.map +1 -0
  162. package/dist/verifier/index.d.cts +2 -0
  163. package/dist/verifier/index.d.ts +1 -0
  164. package/dist/verifier/index.js +1 -0
  165. package/dist/verifier/index.js.map +1 -0
  166. package/dist/worker/Worker.d.ts +53 -0
  167. package/dist/worker/Worker.js +53 -0
  168. package/dist/worker/index.cjs +382 -0
  169. package/dist/worker/index.cjs.map +1 -0
  170. package/dist/worker/index.d.cts +58 -0
  171. package/dist/worker/index.d.ts +1 -0
  172. package/dist/worker/index.js +1 -0
  173. package/dist/worker/index.js.map +1 -0
  174. package/examples/agent-demo.ts +121 -0
  175. package/package.json +46 -0
  176. package/scripts/gen-crypto-fixtures.mjs +72 -0
  177. package/src/agent/Agent.ts +122 -0
  178. package/src/agent/index.ts +1 -0
  179. package/src/api/index.ts +1 -0
  180. package/src/chain/BlindEscrowClient.ts +182 -0
  181. package/src/chain/BlindReputationClient.ts +55 -0
  182. package/src/chain/ChainClient.ts +59 -0
  183. package/src/chain/TaskRegistryClient.ts +82 -0
  184. package/src/chain/abi/BlindEscrow.json +1113 -0
  185. package/src/chain/abi/BlindReputation.json +447 -0
  186. package/src/chain/abi/TaskRegistry.json +586 -0
  187. package/src/chain/abi/index.ts +5 -0
  188. package/src/chain/errors.ts +43 -0
  189. package/src/chain/index.ts +6 -0
  190. package/src/compute/index.ts +1 -0
  191. package/src/crypto/aes.ts +104 -0
  192. package/src/crypto/constants.ts +7 -0
  193. package/src/crypto/ecies.ts +60 -0
  194. package/src/crypto/envelope.ts +131 -0
  195. package/src/crypto/hkdf.ts +45 -0
  196. package/src/crypto/index.ts +6 -0
  197. package/src/crypto/keys.ts +56 -0
  198. package/src/errors/BlindMarketError.ts +38 -0
  199. package/src/errors/codes.ts +67 -0
  200. package/src/errors/index.ts +3 -0
  201. package/src/errors/subclasses.ts +59 -0
  202. package/src/events/EventBus.ts +45 -0
  203. package/src/events/index.ts +2 -0
  204. package/src/events/types.ts +13 -0
  205. package/src/index.ts +222 -0
  206. package/src/keystore/InMemoryKeyStore.ts +146 -0
  207. package/src/keystore/KeyStore.ts +19 -0
  208. package/src/keystore/index.ts +2 -0
  209. package/src/network/index.ts +3 -0
  210. package/src/network/presets.ts +27 -0
  211. package/src/network/resolve.ts +19 -0
  212. package/src/network/types.ts +18 -0
  213. package/src/signer/EthersSigner.ts +82 -0
  214. package/src/signer/PrivateKeySigner.ts +19 -0
  215. package/src/signer/Signer.ts +40 -0
  216. package/src/signer/index.ts +3 -0
  217. package/src/storage/MemoryStorage.ts +49 -0
  218. package/src/storage/Storage.ts +15 -0
  219. package/src/storage/ZgStorage.ts +124 -0
  220. package/src/storage/index.ts +3 -0
  221. package/src/testing/index.ts +1 -0
  222. package/src/types.ts +76 -0
  223. package/src/verifier/index.ts +1 -0
  224. package/src/worker/Worker.ts +98 -0
  225. package/src/worker/index.ts +1 -0
  226. package/test/agent.test.ts +193 -0
  227. package/test/chain.test.ts +145 -0
  228. package/test/crypto.aes.test.ts +81 -0
  229. package/test/crypto.compat.test.ts +33 -0
  230. package/test/crypto.ecies.test.ts +64 -0
  231. package/test/envelope.test.ts +82 -0
  232. package/test/errors.test.ts +64 -0
  233. package/test/events.test.ts +59 -0
  234. package/test/fixtures/crypto.json +16 -0
  235. package/test/keystore.test.ts +103 -0
  236. package/test/network.test.ts +53 -0
  237. package/test/signer.test.ts +66 -0
  238. package/test/smoke.test.ts +7 -0
  239. package/test/storage.test.ts +55 -0
  240. package/test/worker.test.ts +181 -0
  241. package/tsconfig.build.json +1 -0
  242. package/tsconfig.json +13 -0
  243. package/tsup.config.ts +32 -0
  244. package/vitest.config.ts +17 -0
@@ -0,0 +1,31 @@
1
+ type Address = `0x${string}`;
2
+ type Hex = `0x${string}`;
3
+ type TaskId = bigint;
4
+ type RootHash = Hex;
5
+ type TokenSymbol = 'USDC' | 'A0GI' | string;
6
+ interface Reward {
7
+ token: Address | TokenSymbol;
8
+ amount: bigint;
9
+ }
10
+ type TaskStatus = 'funded' | 'assigned' | 'submitted' | 'verified' | 'completed' | 'cancelled';
11
+ interface TaskKey {
12
+ /** AES-256 symmetric key (32 bytes) used to encrypt task content. */
13
+ aesKey: Uint8Array;
14
+ createdAt: Date;
15
+ }
16
+ interface TaskKeyRef {
17
+ taskId: TaskId;
18
+ createdAt: Date;
19
+ }
20
+ interface UploadResult {
21
+ rootHash: RootHash;
22
+ txHash?: Hex;
23
+ size: number;
24
+ }
25
+ interface TxReceiptLike {
26
+ hash: Hex;
27
+ blockNumber: number;
28
+ gasUsed: bigint;
29
+ }
30
+
31
+ export type { Address as A, Hex as H, Reward as R, TaskId as T, UploadResult as U, TaskKey as a, TxReceiptLike as b, TaskKeyRef as c, RootHash as d, TaskStatus as e };
@@ -0,0 +1,19 @@
1
+ import { A as Address } from './types-BOG5Ub1z.cjs';
2
+
3
+ interface NetworkContracts {
4
+ escrow: Address;
5
+ registry: Address;
6
+ reputation: Address;
7
+ usdc: Address;
8
+ }
9
+ interface Network {
10
+ name: string;
11
+ chainId: bigint;
12
+ rpc: string[];
13
+ contracts: NetworkContracts;
14
+ indexer: string;
15
+ broker: string;
16
+ explorer?: string;
17
+ }
18
+
19
+ export type { Network as N, NetworkContracts as a };
@@ -0,0 +1,19 @@
1
+ import { A as Address } from './types-BOG5Ub1z.js';
2
+
3
+ interface NetworkContracts {
4
+ escrow: Address;
5
+ registry: Address;
6
+ reputation: Address;
7
+ usdc: Address;
8
+ }
9
+ interface Network {
10
+ name: string;
11
+ chainId: bigint;
12
+ rpc: string[];
13
+ contracts: NetworkContracts;
14
+ indexer: string;
15
+ broker: string;
16
+ explorer?: string;
17
+ }
18
+
19
+ export type { Network as N, NetworkContracts as a };
@@ -0,0 +1,58 @@
1
+ export type Address = `0x${string}`;
2
+ export type Hex = `0x${string}`;
3
+ export type TaskId = bigint;
4
+ export type RootHash = Hex;
5
+ export type TokenSymbol = 'USDC' | 'A0GI' | string;
6
+ export interface TokenRef {
7
+ address: Address;
8
+ symbol?: TokenSymbol;
9
+ decimals?: number;
10
+ }
11
+ export interface Reward {
12
+ token: Address | TokenSymbol;
13
+ amount: bigint;
14
+ }
15
+ export type TaskStatus = 'funded' | 'assigned' | 'submitted' | 'verified' | 'completed' | 'cancelled';
16
+ export interface TaskMetadata {
17
+ category: string;
18
+ locationZone: string;
19
+ reward: Reward;
20
+ deadline?: Date;
21
+ extra?: Record<string, string>;
22
+ }
23
+ export interface TaskRecord extends TaskMetadata {
24
+ taskId: TaskId;
25
+ agent: Address;
26
+ worker?: Address;
27
+ taskHash: RootHash;
28
+ evidenceHash?: RootHash;
29
+ status: TaskStatus;
30
+ createdAt: Date;
31
+ }
32
+ export interface TaskKey {
33
+ /** AES-256 symmetric key (32 bytes) used to encrypt task content. */
34
+ aesKey: Uint8Array;
35
+ createdAt: Date;
36
+ }
37
+ export interface TaskKeyRef {
38
+ taskId: TaskId;
39
+ createdAt: Date;
40
+ }
41
+ export interface UploadResult {
42
+ rootHash: RootHash;
43
+ txHash?: Hex;
44
+ size: number;
45
+ }
46
+ export interface VerificationResult {
47
+ passed: boolean;
48
+ confidence: number;
49
+ model: string;
50
+ attestation?: Hex;
51
+ completedAt: Date;
52
+ }
53
+ export interface TxReceiptLike {
54
+ hash: Hex;
55
+ blockNumber: number;
56
+ gasUsed: bigint;
57
+ }
58
+ export type Awaitable<T> = T | Promise<T>;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ //# sourceMappingURL=index.cjs.map
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,53 @@
1
+ import type { BlindEscrowClient, OnChainTask, TaskRegistryClient } from '../chain/index.js';
2
+ import type { EventBus, SdkEvents } from '../events/index.js';
3
+ import type { Signer } from '../signer/index.js';
4
+ import type { Storage } from '../storage/index.js';
5
+ import type { Hex, RootHash, TaskId, TxReceiptLike } from '../types.js';
6
+ export interface WorkerDeps {
7
+ escrow: BlindEscrowClient;
8
+ registry: TaskRegistryClient;
9
+ storage: Storage;
10
+ signer: Signer;
11
+ events?: EventBus<SdkEvents>;
12
+ }
13
+ export interface DecryptInstructionsInput {
14
+ /** ECIES-wrapped AES key delivered out-of-band by the agent (e.g. via the backend API). */
15
+ wrappedKey: Uint8Array;
16
+ /** Worker's private key, hex with or without 0x prefix. */
17
+ workerPrivKey: string;
18
+ /** Storage root hash from the on-chain task metadata. */
19
+ taskHash: RootHash;
20
+ }
21
+ export interface SubmitEvidenceInput {
22
+ taskId: TaskId;
23
+ evidence: string | Uint8Array;
24
+ /** Agent's uncompressed secp256k1 pubkey (retrieved via the backend or chain). */
25
+ agentPubKey: string;
26
+ /** TEE enclave pubkey for Sealed Inference (from 0G Compute broker). */
27
+ enclavePubKey: string;
28
+ }
29
+ export interface SubmitEvidenceResult {
30
+ rootHash: RootHash;
31
+ txHash: Hex;
32
+ receipt: TxReceiptLike;
33
+ }
34
+ /**
35
+ * Worker-side flows: browse open tasks, decrypt assigned instructions, seal
36
+ * evidence for agent + TEE, and claim payment after the deadline if
37
+ * verification stalls. Peer pubkeys and wrapped keys are passed explicitly;
38
+ * the SDK does not assume a specific message-passing substrate.
39
+ */
40
+ export declare class Worker {
41
+ private readonly deps;
42
+ constructor(deps: WorkerDeps);
43
+ browse(offset: bigint, limit: bigint): Promise<TaskId[]>;
44
+ getTaskDetail(taskId: TaskId): Promise<OnChainTask>;
45
+ decryptInstructions(input: DecryptInstructionsInput): Promise<Uint8Array>;
46
+ submitEvidence(input: SubmitEvidenceInput): Promise<SubmitEvidenceResult>;
47
+ /**
48
+ * Worker escape hatch: reclaim escrow after the deadline if completeVerification
49
+ * was never called. Payment released per contract logic (85% worker, 15% treasury
50
+ * or full refund depending on submission state — see BlindEscrow.claimTimeout).
51
+ */
52
+ claimTimeout(taskId: TaskId): Promise<TxReceiptLike>;
53
+ }
@@ -0,0 +1,53 @@
1
+ import { aesDecrypt, eciesDecrypt, sealEvidence } from '../crypto/index.js';
2
+ /**
3
+ * Worker-side flows: browse open tasks, decrypt assigned instructions, seal
4
+ * evidence for agent + TEE, and claim payment after the deadline if
5
+ * verification stalls. Peer pubkeys and wrapped keys are passed explicitly;
6
+ * the SDK does not assume a specific message-passing substrate.
7
+ */
8
+ export class Worker {
9
+ deps;
10
+ constructor(deps) {
11
+ this.deps = deps;
12
+ }
13
+ async browse(offset, limit) {
14
+ return this.deps.registry.getOpenTasks(offset, limit);
15
+ }
16
+ async getTaskDetail(taskId) {
17
+ return this.deps.escrow.getTask(taskId);
18
+ }
19
+ async decryptInstructions(input) {
20
+ const aesKey = await eciesDecrypt(input.wrappedKey, input.workerPrivKey);
21
+ const ciphertext = await this.deps.storage.download(input.taskHash);
22
+ return aesDecrypt(ciphertext, aesKey);
23
+ }
24
+ async submitEvidence(input) {
25
+ const evidenceBytes = typeof input.evidence === 'string'
26
+ ? new TextEncoder().encode(input.evidence)
27
+ : input.evidence;
28
+ const { envelope } = await sealEvidence({
29
+ evidence: evidenceBytes,
30
+ agentPubKey: input.agentPubKey,
31
+ enclavePubKey: input.enclavePubKey,
32
+ });
33
+ const uploaded = await this.deps.storage.upload(envelope);
34
+ const rootHash = uploaded.rootHash;
35
+ const receipt = await this.deps.escrow.submitEvidence(input.taskId, rootHash);
36
+ this.deps.events?.emit('evidence.submitted', {
37
+ taskId: input.taskId,
38
+ rootHash,
39
+ txHash: receipt.hash,
40
+ });
41
+ return { rootHash, txHash: receipt.hash, receipt };
42
+ }
43
+ /**
44
+ * Worker escape hatch: reclaim escrow after the deadline if completeVerification
45
+ * was never called. Payment released per contract logic (85% worker, 15% treasury
46
+ * or full refund depending on submission state — see BlindEscrow.claimTimeout).
47
+ */
48
+ async claimTimeout(taskId) {
49
+ const receipt = await this.deps.escrow.claimTimeout(taskId);
50
+ this.deps.events?.emit('payment.claimed', { taskId, txHash: receipt.hash, amount: 0n });
51
+ return receipt;
52
+ }
53
+ }
@@ -0,0 +1,382 @@
1
+ 'use strict';
2
+
3
+ var ethers = require('ethers');
4
+
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+
10
+ // src/crypto/constants.ts
11
+ var IV_LENGTH, TAG_LENGTH, KEY_LENGTH, ECIES_PUBKEY_LENGTH, ECIES_HKDF_INFO, AES_MIN_BLOB, ECIES_MIN_BLOB;
12
+ var init_constants = __esm({
13
+ "src/crypto/constants.ts"() {
14
+ IV_LENGTH = 12;
15
+ TAG_LENGTH = 16;
16
+ KEY_LENGTH = 32;
17
+ ECIES_PUBKEY_LENGTH = 65;
18
+ ECIES_HKDF_INFO = new TextEncoder().encode("BlindBounty-ECIES-v1");
19
+ AES_MIN_BLOB = IV_LENGTH + TAG_LENGTH;
20
+ ECIES_MIN_BLOB = ECIES_PUBKEY_LENGTH + AES_MIN_BLOB;
21
+ }
22
+ });
23
+
24
+ // src/errors/codes.ts
25
+ var init_codes = __esm({
26
+ "src/errors/codes.ts"() {
27
+ }
28
+ });
29
+
30
+ // src/errors/BlindBountyError.ts
31
+ var BlindBountyError;
32
+ var init_BlindBountyError = __esm({
33
+ "src/errors/BlindBountyError.ts"() {
34
+ BlindBountyError = class extends Error {
35
+ code;
36
+ retriable;
37
+ context;
38
+ cause;
39
+ constructor(code, message, opts = {}) {
40
+ super(message);
41
+ this.code = code;
42
+ this.retriable = opts.retriable ?? false;
43
+ if (opts.context !== void 0) this.context = opts.context;
44
+ if (opts.cause !== void 0) this.cause = opts.cause;
45
+ Object.defineProperty(this, "name", {
46
+ value: this.constructor.name,
47
+ enumerable: false,
48
+ configurable: true,
49
+ writable: true
50
+ });
51
+ }
52
+ toJSON() {
53
+ return {
54
+ name: this.name,
55
+ code: this.code,
56
+ message: this.message,
57
+ retriable: this.retriable,
58
+ ...this.context ? { context: this.context } : {}
59
+ };
60
+ }
61
+ };
62
+ }
63
+ });
64
+
65
+ // src/errors/subclasses.ts
66
+ var CryptoError;
67
+ var init_subclasses = __esm({
68
+ "src/errors/subclasses.ts"() {
69
+ init_BlindBountyError();
70
+ CryptoError = class extends BlindBountyError {
71
+ constructor(code, msg, opts) {
72
+ super(code, msg, opts);
73
+ }
74
+ };
75
+ }
76
+ });
77
+
78
+ // src/errors/index.ts
79
+ var init_errors = __esm({
80
+ "src/errors/index.ts"() {
81
+ init_codes();
82
+ init_BlindBountyError();
83
+ init_subclasses();
84
+ }
85
+ });
86
+
87
+ // src/crypto/aes.ts
88
+ function getCrypto() {
89
+ const c = globalThis.crypto;
90
+ if (!c?.subtle) {
91
+ throw new CryptoError("CRYPTO/UNSUPPORTED_CIPHER", "Web Crypto (crypto.subtle) is not available");
92
+ }
93
+ return c;
94
+ }
95
+ function toArrayBuffer(u) {
96
+ const ab = new ArrayBuffer(u.byteLength);
97
+ new Uint8Array(ab).set(u);
98
+ return ab;
99
+ }
100
+ async function generateAesKey() {
101
+ const key = new Uint8Array(KEY_LENGTH);
102
+ getCrypto().getRandomValues(key);
103
+ return key;
104
+ }
105
+ async function aesEncrypt(plaintext, key) {
106
+ if (key.byteLength !== KEY_LENGTH) {
107
+ throw new CryptoError(
108
+ "CRYPTO/INVALID_KEY",
109
+ `AES key must be ${KEY_LENGTH} bytes, got ${key.byteLength}`
110
+ );
111
+ }
112
+ const c = getCrypto();
113
+ const iv = new Uint8Array(IV_LENGTH);
114
+ c.getRandomValues(iv);
115
+ try {
116
+ const ck = await c.subtle.importKey("raw", toArrayBuffer(key), "AES-GCM", false, ["encrypt"]);
117
+ const wcOut = new Uint8Array(
118
+ await c.subtle.encrypt(
119
+ { name: "AES-GCM", iv: toArrayBuffer(iv), tagLength: TAG_LENGTH * 8 },
120
+ ck,
121
+ toArrayBuffer(plaintext)
122
+ )
123
+ );
124
+ const ctLen = wcOut.length - TAG_LENGTH;
125
+ const ct = wcOut.subarray(0, ctLen);
126
+ const tag = wcOut.subarray(ctLen);
127
+ const blob = new Uint8Array(IV_LENGTH + TAG_LENGTH + ctLen);
128
+ blob.set(iv, 0);
129
+ blob.set(tag, IV_LENGTH);
130
+ blob.set(ct, IV_LENGTH + TAG_LENGTH);
131
+ return blob;
132
+ } catch (cause) {
133
+ throw new CryptoError("CRYPTO/DECRYPT_FAILED", "AES-GCM encryption failed", { cause });
134
+ }
135
+ }
136
+ async function aesDecrypt(blob, key) {
137
+ if (key.byteLength !== KEY_LENGTH) {
138
+ throw new CryptoError(
139
+ "CRYPTO/INVALID_KEY",
140
+ `AES key must be ${KEY_LENGTH} bytes, got ${key.byteLength}`
141
+ );
142
+ }
143
+ if (blob.byteLength < AES_MIN_BLOB) {
144
+ throw new CryptoError(
145
+ "CRYPTO/INTEGRITY_CHECK",
146
+ `AES blob too short: need \u2265${AES_MIN_BLOB} bytes, got ${blob.byteLength}`
147
+ );
148
+ }
149
+ const iv = blob.subarray(0, IV_LENGTH);
150
+ const tag = blob.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
151
+ const ct = blob.subarray(IV_LENGTH + TAG_LENGTH);
152
+ const combined = new Uint8Array(ct.length + TAG_LENGTH);
153
+ combined.set(ct, 0);
154
+ combined.set(tag, ct.length);
155
+ try {
156
+ const c = getCrypto();
157
+ const ck = await c.subtle.importKey("raw", toArrayBuffer(key), "AES-GCM", false, ["decrypt"]);
158
+ const pt = await c.subtle.decrypt(
159
+ { name: "AES-GCM", iv: toArrayBuffer(iv), tagLength: TAG_LENGTH * 8 },
160
+ ck,
161
+ toArrayBuffer(combined)
162
+ );
163
+ return new Uint8Array(pt);
164
+ } catch (cause) {
165
+ throw new CryptoError("CRYPTO/DECRYPT_FAILED", "AES-GCM decryption failed (wrong key or tampered data)", { cause });
166
+ }
167
+ }
168
+ var init_aes = __esm({
169
+ "src/crypto/aes.ts"() {
170
+ init_errors();
171
+ init_constants();
172
+ }
173
+ });
174
+
175
+ // src/crypto/hkdf.ts
176
+ function getSubtle() {
177
+ const c = globalThis.crypto;
178
+ if (!c?.subtle) {
179
+ throw new CryptoError("CRYPTO/UNSUPPORTED_CIPHER", "Web Crypto (crypto.subtle) is not available");
180
+ }
181
+ return c.subtle;
182
+ }
183
+ function toArrayBuffer2(u) {
184
+ const ab = new ArrayBuffer(u.byteLength);
185
+ new Uint8Array(ab).set(u);
186
+ return ab;
187
+ }
188
+ async function hkdfSha256(ikm, length = 32, info = ECIES_HKDF_INFO, salt = new Uint8Array(0)) {
189
+ try {
190
+ const subtle = getSubtle();
191
+ const baseKey = await subtle.importKey("raw", toArrayBuffer2(ikm), "HKDF", false, ["deriveBits"]);
192
+ const derived = await subtle.deriveBits(
193
+ {
194
+ name: "HKDF",
195
+ hash: "SHA-256",
196
+ info: toArrayBuffer2(info),
197
+ salt: toArrayBuffer2(salt)
198
+ },
199
+ baseKey,
200
+ length * 8
201
+ );
202
+ return new Uint8Array(derived);
203
+ } catch (cause) {
204
+ throw new CryptoError("CRYPTO/INVALID_KEY", "HKDF derivation failed", { cause });
205
+ }
206
+ }
207
+ var init_hkdf = __esm({
208
+ "src/crypto/hkdf.ts"() {
209
+ init_errors();
210
+ init_constants();
211
+ }
212
+ });
213
+ function strip(hex) {
214
+ return hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
215
+ }
216
+ function assertUncompressedPubKey(pub) {
217
+ const s = strip(pub);
218
+ if (s.length !== 130 || !/^04/i.test(s)) {
219
+ throw new CryptoError(
220
+ "CRYPTO/INVALID_KEY",
221
+ "expected uncompressed secp256k1 pubkey (65 bytes hex, starts with 04)"
222
+ );
223
+ }
224
+ }
225
+ function hexToBytes(hex) {
226
+ const s = strip(hex);
227
+ if (s.length % 2 !== 0) {
228
+ throw new CryptoError("CRYPTO/INVALID_KEY", "hex string has odd length");
229
+ }
230
+ const out = new Uint8Array(s.length / 2);
231
+ for (let i = 0; i < out.length; i++) {
232
+ const byte = Number.parseInt(s.substring(i * 2, i * 2 + 2), 16);
233
+ if (Number.isNaN(byte)) {
234
+ throw new CryptoError("CRYPTO/INVALID_KEY", `invalid hex byte at position ${i * 2}`);
235
+ }
236
+ out[i] = byte;
237
+ }
238
+ return out;
239
+ }
240
+ function bytesToHex(u) {
241
+ return Array.from(u, (b) => b.toString(16).padStart(2, "0")).join("");
242
+ }
243
+ var init_keys = __esm({
244
+ "src/crypto/keys.ts"() {
245
+ init_errors();
246
+ }
247
+ });
248
+ async function eciesEncrypt(plaintext, recipientPubKey) {
249
+ assertUncompressedPubKey(recipientPubKey);
250
+ const ephemeral = ethers.ethers.Wallet.createRandom();
251
+ const shared = deriveSharedSecretX(ephemeral.privateKey, `0x${strip(recipientPubKey)}`);
252
+ const aesKey = await hkdfSha256(shared, KEY_LENGTH);
253
+ const aesBlob = await aesEncrypt(plaintext, aesKey);
254
+ const ephPub = hexToBytes(strip(ephemeral.signingKey.publicKey));
255
+ if (ephPub.byteLength !== ECIES_PUBKEY_LENGTH) {
256
+ throw new CryptoError("CRYPTO/INVALID_KEY", `ephemeral pubkey length ${ephPub.byteLength}`);
257
+ }
258
+ const blob = new Uint8Array(ECIES_PUBKEY_LENGTH + aesBlob.byteLength);
259
+ blob.set(ephPub, 0);
260
+ blob.set(aesBlob, ECIES_PUBKEY_LENGTH);
261
+ return blob;
262
+ }
263
+ async function eciesDecrypt(blob, recipientPrivKey) {
264
+ if (blob.byteLength < ECIES_MIN_BLOB) {
265
+ throw new CryptoError(
266
+ "CRYPTO/INTEGRITY_CHECK",
267
+ `ECIES blob too short: need \u2265${ECIES_MIN_BLOB} bytes, got ${blob.byteLength}`
268
+ );
269
+ }
270
+ const ephPub = blob.subarray(0, ECIES_PUBKEY_LENGTH);
271
+ const aesBlob = blob.subarray(ECIES_PUBKEY_LENGTH);
272
+ const shared = deriveSharedSecretX(`0x${strip(recipientPrivKey)}`, `0x${bytesToHex(ephPub)}`);
273
+ const aesKey = await hkdfSha256(shared, KEY_LENGTH);
274
+ return aesDecrypt(aesBlob, aesKey);
275
+ }
276
+ function deriveSharedSecretX(privHex, pubHex) {
277
+ const sk = new ethers.ethers.SigningKey(privHex);
278
+ const shared = sk.computeSharedSecret(pubHex);
279
+ const bytes = hexToBytes(strip(shared));
280
+ if (bytes.byteLength !== 65 || bytes[0] !== 4) {
281
+ throw new CryptoError(
282
+ "CRYPTO/INVALID_KEY",
283
+ `unexpected shared secret shape (len=${bytes.byteLength}, prefix=${bytes[0]?.toString(16) ?? "none"})`
284
+ );
285
+ }
286
+ return bytes.subarray(1, 33);
287
+ }
288
+ var init_ecies = __esm({
289
+ "src/crypto/ecies.ts"() {
290
+ init_errors();
291
+ init_aes();
292
+ init_constants();
293
+ init_hkdf();
294
+ init_keys();
295
+ }
296
+ });
297
+
298
+ // src/crypto/envelope.ts
299
+ init_aes();
300
+ init_ecies();
301
+ var MAGIC_0 = 66;
302
+ var MAGIC_1 = 66;
303
+ var VERSION = 1;
304
+ var HEADER_LEN = 3;
305
+ async function sealEvidence(input) {
306
+ const aesKey = await generateAesKey();
307
+ const aesCiphertext = await aesEncrypt(input.evidence, aesKey);
308
+ const wrappedForAgent = await eciesEncrypt(aesKey, input.agentPubKey);
309
+ const wrappedForEnclave = await eciesEncrypt(aesKey, input.enclavePubKey);
310
+ const envelope = pack({ wrappedForAgent, wrappedForEnclave, aesCiphertext });
311
+ return { envelope, aesKey };
312
+ }
313
+ function pack(parts) {
314
+ const { wrappedForAgent, wrappedForEnclave, aesCiphertext } = parts;
315
+ const total = HEADER_LEN + 4 + wrappedForAgent.byteLength + 4 + wrappedForEnclave.byteLength + aesCiphertext.byteLength;
316
+ const out = new Uint8Array(total);
317
+ const view = new DataView(out.buffer);
318
+ let off = 0;
319
+ out[off++] = MAGIC_0;
320
+ out[off++] = MAGIC_1;
321
+ out[off++] = VERSION;
322
+ view.setUint32(off, wrappedForAgent.byteLength, false);
323
+ off += 4;
324
+ out.set(wrappedForAgent, off);
325
+ off += wrappedForAgent.byteLength;
326
+ view.setUint32(off, wrappedForEnclave.byteLength, false);
327
+ off += 4;
328
+ out.set(wrappedForEnclave, off);
329
+ off += wrappedForEnclave.byteLength;
330
+ out.set(aesCiphertext, off);
331
+ return out;
332
+ }
333
+
334
+ // src/worker/Worker.ts
335
+ var Worker = class {
336
+ constructor(deps) {
337
+ this.deps = deps;
338
+ }
339
+ deps;
340
+ async browse(offset, limit) {
341
+ return this.deps.registry.getOpenTasks(offset, limit);
342
+ }
343
+ async getTaskDetail(taskId) {
344
+ return this.deps.escrow.getTask(taskId);
345
+ }
346
+ async decryptInstructions(input) {
347
+ const aesKey = await eciesDecrypt(input.wrappedKey, input.workerPrivKey);
348
+ const ciphertext = await this.deps.storage.download(input.taskHash);
349
+ return aesDecrypt(ciphertext, aesKey);
350
+ }
351
+ async submitEvidence(input) {
352
+ const evidenceBytes = typeof input.evidence === "string" ? new TextEncoder().encode(input.evidence) : input.evidence;
353
+ const { envelope } = await sealEvidence({
354
+ evidence: evidenceBytes,
355
+ agentPubKey: input.agentPubKey,
356
+ enclavePubKey: input.enclavePubKey
357
+ });
358
+ const uploaded = await this.deps.storage.upload(envelope);
359
+ const rootHash = uploaded.rootHash;
360
+ const receipt = await this.deps.escrow.submitEvidence(input.taskId, rootHash);
361
+ this.deps.events?.emit("evidence.submitted", {
362
+ taskId: input.taskId,
363
+ rootHash,
364
+ txHash: receipt.hash
365
+ });
366
+ return { rootHash, txHash: receipt.hash, receipt };
367
+ }
368
+ /**
369
+ * Worker escape hatch: reclaim escrow after the deadline if completeVerification
370
+ * was never called. Payment released per contract logic (85% worker, 15% treasury
371
+ * or full refund depending on submission state — see BlindEscrow.claimTimeout).
372
+ */
373
+ async claimTimeout(taskId) {
374
+ const receipt = await this.deps.escrow.claimTimeout(taskId);
375
+ this.deps.events?.emit("payment.claimed", { taskId, txHash: receipt.hash, amount: 0n });
376
+ return receipt;
377
+ }
378
+ };
379
+
380
+ exports.Worker = Worker;
381
+ //# sourceMappingURL=index.cjs.map
382
+ //# sourceMappingURL=index.cjs.map