@blindmarket/sdk 0.1.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/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/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 +134 -0
- package/dist/executor/WorkerRuntime.js +277 -0
- package/dist/executor/index.d.ts +1 -0
- package/dist/executor/index.js +1 -0
- package/dist/index.d.ts +82 -9
- package/dist/index.js +60 -6
- 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 +8 -1
- package/biome.json +0 -19
- 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
- package/examples/agent-demo.ts +0 -121
- package/scripts/gen-crypto-fixtures.mjs +0 -72
- package/src/agent/Agent.ts +0 -122
- package/src/agent/index.ts +0 -1
- package/src/chain/BlindEscrowClient.ts +0 -187
- package/src/chain/BlindReputationClient.ts +0 -55
- package/src/chain/ChainClient.ts +0 -59
- package/src/chain/TaskRegistryClient.ts +0 -82
- package/src/chain/abi/BlindEscrow.json +0 -1113
- package/src/chain/abi/BlindReputation.json +0 -447
- package/src/chain/abi/TaskRegistry.json +0 -586
- package/src/chain/abi/index.ts +0 -5
- package/src/chain/errors.ts +0 -43
- package/src/chain/index.ts +0 -6
- package/src/crypto/aes.ts +0 -104
- package/src/crypto/constants.ts +0 -7
- package/src/crypto/ecies.ts +0 -60
- package/src/crypto/envelope.ts +0 -131
- package/src/crypto/hkdf.ts +0 -45
- package/src/crypto/index.ts +0 -6
- package/src/crypto/keys.ts +0 -56
- package/src/errors/BlindMarketError.ts +0 -38
- package/src/errors/codes.ts +0 -67
- package/src/errors/index.ts +0 -3
- package/src/errors/subclasses.ts +0 -59
- package/src/events/EventBus.ts +0 -45
- package/src/events/index.ts +0 -2
- package/src/events/types.ts +0 -13
- package/src/index.ts +0 -617
- package/src/keystore/InMemoryKeyStore.ts +0 -146
- package/src/keystore/KeyStore.ts +0 -19
- package/src/keystore/index.ts +0 -2
- package/src/network/index.ts +0 -3
- package/src/network/presets.ts +0 -27
- package/src/network/resolve.ts +0 -19
- package/src/network/types.ts +0 -18
- package/src/signer/EthersSigner.ts +0 -82
- package/src/signer/PrivateKeySigner.ts +0 -19
- package/src/signer/Signer.ts +0 -40
- package/src/signer/index.ts +0 -3
- package/src/storage/MemoryStorage.ts +0 -49
- package/src/storage/Storage.ts +0 -15
- package/src/storage/ZgStorage.ts +0 -124
- package/src/storage/index.ts +0 -3
- package/src/testing/index.ts +0 -1
- package/src/tools/adapters.ts +0 -177
- package/src/tools/helpers.ts +0 -199
- package/src/tools/index.ts +0 -59
- package/src/tools/types.ts +0 -47
- package/src/types.ts +0 -296
- package/src/verifier/index.ts +0 -1
- package/src/worker/Worker.ts +0 -98
- package/src/worker/index.ts +0 -1
- package/test/agent.test.ts +0 -193
- package/test/chain.test.ts +0 -145
- package/test/crypto.aes.test.ts +0 -81
- package/test/crypto.compat.test.ts +0 -33
- package/test/crypto.ecies.test.ts +0 -64
- package/test/envelope.test.ts +0 -82
- package/test/errors.test.ts +0 -64
- package/test/events.test.ts +0 -59
- package/test/fixtures/crypto.json +0 -16
- package/test/keystore.test.ts +0 -103
- package/test/network.test.ts +0 -53
- package/test/signer.test.ts +0 -66
- package/test/smoke.test.ts +0 -7
- package/test/storage.test.ts +0 -55
- package/test/worker.test.ts +0 -181
- package/tsconfig.build.json +0 -1
- package/tsconfig.json +0 -14
- package/tsup.config.ts +0 -32
- package/vitest.config.ts +0 -17
- /package/{src/api/index.ts → dist/chain/IBlindMarketChain.js} +0 -0
- /package/{src/compute/index.ts → dist/chain/domain-types.js} +0 -0
package/src/crypto/aes.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { CryptoError } from '../errors/index.js';
|
|
2
|
-
import { AES_MIN_BLOB, IV_LENGTH, KEY_LENGTH, TAG_LENGTH } from './constants.js';
|
|
3
|
-
|
|
4
|
-
function getCrypto(): Crypto {
|
|
5
|
-
const c = (globalThis as { crypto?: Crypto }).crypto;
|
|
6
|
-
if (!c?.subtle) {
|
|
7
|
-
throw new CryptoError('CRYPTO/UNSUPPORTED_CIPHER', 'Web Crypto (crypto.subtle) is not available');
|
|
8
|
-
}
|
|
9
|
-
return c;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function toArrayBuffer(u: Uint8Array): ArrayBuffer {
|
|
13
|
-
const ab = new ArrayBuffer(u.byteLength);
|
|
14
|
-
new Uint8Array(ab).set(u);
|
|
15
|
-
return ab;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** Generate a fresh 32-byte AES-256 key. */
|
|
19
|
-
export async function generateAesKey(): Promise<Uint8Array> {
|
|
20
|
-
const key = new Uint8Array(KEY_LENGTH);
|
|
21
|
-
getCrypto().getRandomValues(key);
|
|
22
|
-
return key;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* AES-256-GCM encrypt. Output format: [12 IV][16 tag][ciphertext].
|
|
27
|
-
* This ordering matches backend/src/services/crypto.ts and frontend/src/lib/crypto.ts
|
|
28
|
-
* byte-for-byte, so SDK blobs decrypt anywhere in the stack.
|
|
29
|
-
*/
|
|
30
|
-
export async function aesEncrypt(plaintext: Uint8Array, key: Uint8Array): Promise<Uint8Array> {
|
|
31
|
-
if (key.byteLength !== KEY_LENGTH) {
|
|
32
|
-
throw new CryptoError(
|
|
33
|
-
'CRYPTO/INVALID_KEY',
|
|
34
|
-
`AES key must be ${KEY_LENGTH} bytes, got ${key.byteLength}`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
const c = getCrypto();
|
|
38
|
-
const iv = new Uint8Array(IV_LENGTH);
|
|
39
|
-
c.getRandomValues(iv);
|
|
40
|
-
try {
|
|
41
|
-
const ck = await c.subtle.importKey('raw', toArrayBuffer(key), 'AES-GCM', false, ['encrypt']);
|
|
42
|
-
const wcOut = new Uint8Array(
|
|
43
|
-
await c.subtle.encrypt(
|
|
44
|
-
{ name: 'AES-GCM', iv: toArrayBuffer(iv), tagLength: TAG_LENGTH * 8 },
|
|
45
|
-
ck,
|
|
46
|
-
toArrayBuffer(plaintext),
|
|
47
|
-
),
|
|
48
|
-
);
|
|
49
|
-
// WebCrypto returns [ciphertext || tag]. Rewrite to [IV || tag || ciphertext].
|
|
50
|
-
const ctLen = wcOut.length - TAG_LENGTH;
|
|
51
|
-
const ct = wcOut.subarray(0, ctLen);
|
|
52
|
-
const tag = wcOut.subarray(ctLen);
|
|
53
|
-
const blob = new Uint8Array(IV_LENGTH + TAG_LENGTH + ctLen);
|
|
54
|
-
blob.set(iv, 0);
|
|
55
|
-
blob.set(tag, IV_LENGTH);
|
|
56
|
-
blob.set(ct, IV_LENGTH + TAG_LENGTH);
|
|
57
|
-
return blob;
|
|
58
|
-
} catch (cause) {
|
|
59
|
-
throw new CryptoError('CRYPTO/DECRYPT_FAILED', 'AES-GCM encryption failed', { cause });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* AES-256-GCM decrypt. Input format: [12 IV][16 tag][ciphertext].
|
|
65
|
-
* Throws CRYPTO/INTEGRITY_CHECK on truncation or tag mismatch.
|
|
66
|
-
*/
|
|
67
|
-
export async function aesDecrypt(blob: Uint8Array, key: Uint8Array): Promise<Uint8Array> {
|
|
68
|
-
if (key.byteLength !== KEY_LENGTH) {
|
|
69
|
-
throw new CryptoError(
|
|
70
|
-
'CRYPTO/INVALID_KEY',
|
|
71
|
-
`AES key must be ${KEY_LENGTH} bytes, got ${key.byteLength}`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
if (blob.byteLength < AES_MIN_BLOB) {
|
|
75
|
-
throw new CryptoError(
|
|
76
|
-
'CRYPTO/INTEGRITY_CHECK',
|
|
77
|
-
`AES blob too short: need ≥${AES_MIN_BLOB} bytes, got ${blob.byteLength}`,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
const iv = blob.subarray(0, IV_LENGTH);
|
|
81
|
-
const tag = blob.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
|
|
82
|
-
const ct = blob.subarray(IV_LENGTH + TAG_LENGTH);
|
|
83
|
-
const combined = new Uint8Array(ct.length + TAG_LENGTH);
|
|
84
|
-
combined.set(ct, 0);
|
|
85
|
-
combined.set(tag, ct.length);
|
|
86
|
-
try {
|
|
87
|
-
const c = getCrypto();
|
|
88
|
-
const ck = await c.subtle.importKey('raw', toArrayBuffer(key), 'AES-GCM', false, ['decrypt']);
|
|
89
|
-
const pt = await c.subtle.decrypt(
|
|
90
|
-
{ name: 'AES-GCM', iv: toArrayBuffer(iv), tagLength: TAG_LENGTH * 8 },
|
|
91
|
-
ck,
|
|
92
|
-
toArrayBuffer(combined),
|
|
93
|
-
);
|
|
94
|
-
return new Uint8Array(pt);
|
|
95
|
-
} catch (cause) {
|
|
96
|
-
throw new CryptoError('CRYPTO/DECRYPT_FAILED', 'AES-GCM decryption failed (wrong key or tampered data)', { cause });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** SHA-256 of arbitrary bytes. Returns 32-byte digest. */
|
|
101
|
-
export async function sha256(data: Uint8Array): Promise<Uint8Array> {
|
|
102
|
-
const digest = await getCrypto().subtle.digest('SHA-256', toArrayBuffer(data));
|
|
103
|
-
return new Uint8Array(digest);
|
|
104
|
-
}
|
package/src/crypto/constants.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export const IV_LENGTH = 12;
|
|
2
|
-
export const TAG_LENGTH = 16;
|
|
3
|
-
export const KEY_LENGTH = 32;
|
|
4
|
-
export const ECIES_PUBKEY_LENGTH = 65;
|
|
5
|
-
export const ECIES_HKDF_INFO = new TextEncoder().encode('BlindMarket-ECIES-v1');
|
|
6
|
-
export const AES_MIN_BLOB = IV_LENGTH + TAG_LENGTH;
|
|
7
|
-
export const ECIES_MIN_BLOB = ECIES_PUBKEY_LENGTH + AES_MIN_BLOB;
|
package/src/crypto/ecies.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
import { CryptoError } from '../errors/index.js';
|
|
3
|
-
import { aesDecrypt, aesEncrypt } from './aes.js';
|
|
4
|
-
import { ECIES_MIN_BLOB, ECIES_PUBKEY_LENGTH, KEY_LENGTH } from './constants.js';
|
|
5
|
-
import { hkdfSha256 } from './hkdf.js';
|
|
6
|
-
import { assertUncompressedPubKey, bytesToHex, hexToBytes, strip } from './keys.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* ECIES-secp256k1 encrypt to a recipient's uncompressed public key.
|
|
10
|
-
* Wire format: [65 ephemeral pubkey][12 IV][16 tag][ciphertext].
|
|
11
|
-
* Byte-compatible with backend/src/services/crypto.ts.
|
|
12
|
-
*/
|
|
13
|
-
export async function eciesEncrypt(plaintext: Uint8Array, recipientPubKey: string): Promise<Uint8Array> {
|
|
14
|
-
assertUncompressedPubKey(recipientPubKey);
|
|
15
|
-
const ephemeral = ethers.Wallet.createRandom();
|
|
16
|
-
const shared = deriveSharedSecretX(ephemeral.privateKey, `0x${strip(recipientPubKey)}`);
|
|
17
|
-
const aesKey = await hkdfSha256(shared, KEY_LENGTH);
|
|
18
|
-
const aesBlob = await aesEncrypt(plaintext, aesKey);
|
|
19
|
-
const ephPub = hexToBytes(strip(ephemeral.signingKey.publicKey));
|
|
20
|
-
if (ephPub.byteLength !== ECIES_PUBKEY_LENGTH) {
|
|
21
|
-
throw new CryptoError('CRYPTO/INVALID_KEY', `ephemeral pubkey length ${ephPub.byteLength}`);
|
|
22
|
-
}
|
|
23
|
-
const blob = new Uint8Array(ECIES_PUBKEY_LENGTH + aesBlob.byteLength);
|
|
24
|
-
blob.set(ephPub, 0);
|
|
25
|
-
blob.set(aesBlob, ECIES_PUBKEY_LENGTH);
|
|
26
|
-
return blob;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** ECIES-secp256k1 decrypt with the recipient's private key. */
|
|
30
|
-
export async function eciesDecrypt(blob: Uint8Array, recipientPrivKey: string): Promise<Uint8Array> {
|
|
31
|
-
if (blob.byteLength < ECIES_MIN_BLOB) {
|
|
32
|
-
throw new CryptoError(
|
|
33
|
-
'CRYPTO/INTEGRITY_CHECK',
|
|
34
|
-
`ECIES blob too short: need ≥${ECIES_MIN_BLOB} bytes, got ${blob.byteLength}`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
const ephPub = blob.subarray(0, ECIES_PUBKEY_LENGTH);
|
|
38
|
-
const aesBlob = blob.subarray(ECIES_PUBKEY_LENGTH);
|
|
39
|
-
const shared = deriveSharedSecretX(`0x${strip(recipientPrivKey)}`, `0x${bytesToHex(ephPub)}`);
|
|
40
|
-
const aesKey = await hkdfSha256(shared, KEY_LENGTH);
|
|
41
|
-
return aesDecrypt(aesBlob, aesKey);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Compute the ECDH shared secret X coordinate (32 bytes) between a private key
|
|
46
|
-
* and a peer's public key. Matches Node createECDH.computeSecret() output used by
|
|
47
|
-
* the backend — ethers v6 returns 0x04||X||Y, so we slice X.
|
|
48
|
-
*/
|
|
49
|
-
function deriveSharedSecretX(privHex: string, pubHex: string): Uint8Array {
|
|
50
|
-
const sk = new ethers.SigningKey(privHex);
|
|
51
|
-
const shared = sk.computeSharedSecret(pubHex);
|
|
52
|
-
const bytes = hexToBytes(strip(shared));
|
|
53
|
-
if (bytes.byteLength !== 65 || bytes[0] !== 0x04) {
|
|
54
|
-
throw new CryptoError(
|
|
55
|
-
'CRYPTO/INVALID_KEY',
|
|
56
|
-
`unexpected shared secret shape (len=${bytes.byteLength}, prefix=${bytes[0]?.toString(16) ?? 'none'})`,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
return bytes.subarray(1, 33);
|
|
60
|
-
}
|
package/src/crypto/envelope.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { CryptoError } from '../errors/index.js';
|
|
2
|
-
import { aesDecrypt, aesEncrypt, generateAesKey } from './aes.js';
|
|
3
|
-
import { eciesEncrypt } from './ecies.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Evidence envelope — the single blob a worker uploads to Storage containing:
|
|
7
|
-
* 1. The AES key wrapped to the agent's pubkey (so agent can decrypt later)
|
|
8
|
-
* 2. The AES key wrapped to the TEE enclave's pubkey (so Sealed Inference can decrypt)
|
|
9
|
-
* 3. The evidence ciphertext under that AES key
|
|
10
|
-
*
|
|
11
|
-
* Wire format (big-endian):
|
|
12
|
-
* bytes 0..1 magic = 0x42 0x42 ("BB")
|
|
13
|
-
* byte 2 version = 0x01
|
|
14
|
-
* bytes 3..6 wrappedAgentLen (uint32)
|
|
15
|
-
* bytes 7.. wrappedAgent (ECIES blob)
|
|
16
|
-
* 4-byte uint32 wrappedEnclaveLen
|
|
17
|
-
* bytes wrappedEnclave (ECIES blob)
|
|
18
|
-
* bytes aesCiphertext (rest of the blob — AES blob [IV||tag||ct])
|
|
19
|
-
*
|
|
20
|
-
* The layout is versioned so we can rev it without breaking old blobs.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
const MAGIC_0 = 0x42;
|
|
24
|
-
const MAGIC_1 = 0x42;
|
|
25
|
-
const VERSION = 0x01;
|
|
26
|
-
const HEADER_LEN = 3;
|
|
27
|
-
|
|
28
|
-
export interface EvidenceEnvelope {
|
|
29
|
-
wrappedForAgent: Uint8Array;
|
|
30
|
-
wrappedForEnclave: Uint8Array;
|
|
31
|
-
aesCiphertext: Uint8Array;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface SealEvidenceInput {
|
|
35
|
-
evidence: Uint8Array;
|
|
36
|
-
agentPubKey: string;
|
|
37
|
-
enclavePubKey: string;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface SealEvidenceOutput {
|
|
41
|
-
envelope: Uint8Array;
|
|
42
|
-
aesKey: Uint8Array;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Seal evidence for the agent + TEE enclave. Generates a fresh AES key,
|
|
47
|
-
* encrypts the evidence, ECIES-wraps the key twice, and concatenates the
|
|
48
|
-
* result as an EvidenceEnvelope. Returns both the on-wire envelope and
|
|
49
|
-
* the raw AES key (for audit / diagnostic use — do NOT persist beyond
|
|
50
|
-
* the submission).
|
|
51
|
-
*/
|
|
52
|
-
export async function sealEvidence(input: SealEvidenceInput): Promise<SealEvidenceOutput> {
|
|
53
|
-
const aesKey = await generateAesKey();
|
|
54
|
-
const aesCiphertext = await aesEncrypt(input.evidence, aesKey);
|
|
55
|
-
const wrappedForAgent = await eciesEncrypt(aesKey, input.agentPubKey);
|
|
56
|
-
const wrappedForEnclave = await eciesEncrypt(aesKey, input.enclavePubKey);
|
|
57
|
-
const envelope = pack({ wrappedForAgent, wrappedForEnclave, aesCiphertext });
|
|
58
|
-
return { envelope, aesKey };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Open an evidence envelope as the agent — extracts the AES key wrapped
|
|
63
|
-
* to the agent's pubkey, decrypts the ciphertext, and returns the plaintext
|
|
64
|
-
* evidence. The enclave-wrapped key is ignored by agents (TEE-only).
|
|
65
|
-
*/
|
|
66
|
-
export async function openEvidenceAsAgent(
|
|
67
|
-
envelope: Uint8Array,
|
|
68
|
-
agentPrivKey: string,
|
|
69
|
-
): Promise<Uint8Array> {
|
|
70
|
-
const parsed = parse(envelope);
|
|
71
|
-
const { eciesDecrypt } = await import('./ecies.js');
|
|
72
|
-
const aesKey = await eciesDecrypt(parsed.wrappedForAgent, agentPrivKey);
|
|
73
|
-
return aesDecrypt(parsed.aesCiphertext, aesKey);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function pack(parts: EvidenceEnvelope): Uint8Array {
|
|
77
|
-
const { wrappedForAgent, wrappedForEnclave, aesCiphertext } = parts;
|
|
78
|
-
const total =
|
|
79
|
-
HEADER_LEN +
|
|
80
|
-
4 + wrappedForAgent.byteLength +
|
|
81
|
-
4 + wrappedForEnclave.byteLength +
|
|
82
|
-
aesCiphertext.byteLength;
|
|
83
|
-
const out = new Uint8Array(total);
|
|
84
|
-
const view = new DataView(out.buffer);
|
|
85
|
-
let off = 0;
|
|
86
|
-
out[off++] = MAGIC_0;
|
|
87
|
-
out[off++] = MAGIC_1;
|
|
88
|
-
out[off++] = VERSION;
|
|
89
|
-
view.setUint32(off, wrappedForAgent.byteLength, false);
|
|
90
|
-
off += 4;
|
|
91
|
-
out.set(wrappedForAgent, off);
|
|
92
|
-
off += wrappedForAgent.byteLength;
|
|
93
|
-
view.setUint32(off, wrappedForEnclave.byteLength, false);
|
|
94
|
-
off += 4;
|
|
95
|
-
out.set(wrappedForEnclave, off);
|
|
96
|
-
off += wrappedForEnclave.byteLength;
|
|
97
|
-
out.set(aesCiphertext, off);
|
|
98
|
-
return out;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function parse(blob: Uint8Array): EvidenceEnvelope {
|
|
102
|
-
if (blob.byteLength < HEADER_LEN + 4 + 4) {
|
|
103
|
-
throw new CryptoError('CRYPTO/INTEGRITY_CHECK', `envelope too short: ${blob.byteLength}`);
|
|
104
|
-
}
|
|
105
|
-
if (blob[0] !== MAGIC_0 || blob[1] !== MAGIC_1) {
|
|
106
|
-
throw new CryptoError('CRYPTO/INTEGRITY_CHECK', 'bad envelope magic');
|
|
107
|
-
}
|
|
108
|
-
if (blob[2] !== VERSION) {
|
|
109
|
-
throw new CryptoError('CRYPTO/UNSUPPORTED_CIPHER', `unknown envelope version ${blob[2]}`);
|
|
110
|
-
}
|
|
111
|
-
const view = new DataView(blob.buffer, blob.byteOffset, blob.byteLength);
|
|
112
|
-
let off = HEADER_LEN;
|
|
113
|
-
const agentLen = view.getUint32(off, false);
|
|
114
|
-
off += 4;
|
|
115
|
-
if (off + agentLen + 4 > blob.byteLength) {
|
|
116
|
-
throw new CryptoError('CRYPTO/INTEGRITY_CHECK', 'envelope truncated (agent)');
|
|
117
|
-
}
|
|
118
|
-
const wrappedForAgent = blob.slice(off, off + agentLen);
|
|
119
|
-
off += agentLen;
|
|
120
|
-
const enclaveLen = view.getUint32(off, false);
|
|
121
|
-
off += 4;
|
|
122
|
-
if (off + enclaveLen > blob.byteLength) {
|
|
123
|
-
throw new CryptoError('CRYPTO/INTEGRITY_CHECK', 'envelope truncated (enclave)');
|
|
124
|
-
}
|
|
125
|
-
const wrappedForEnclave = blob.slice(off, off + enclaveLen);
|
|
126
|
-
off += enclaveLen;
|
|
127
|
-
const aesCiphertext = blob.slice(off);
|
|
128
|
-
return { wrappedForAgent, wrappedForEnclave, aesCiphertext };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export const __internals = { pack, parse };
|
package/src/crypto/hkdf.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { CryptoError } from '../errors/index.js';
|
|
2
|
-
import { ECIES_HKDF_INFO } from './constants.js';
|
|
3
|
-
|
|
4
|
-
function getSubtle(): SubtleCrypto {
|
|
5
|
-
const c = (globalThis as { crypto?: Crypto }).crypto;
|
|
6
|
-
if (!c?.subtle) {
|
|
7
|
-
throw new CryptoError('CRYPTO/UNSUPPORTED_CIPHER', 'Web Crypto (crypto.subtle) is not available');
|
|
8
|
-
}
|
|
9
|
-
return c.subtle;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function toArrayBuffer(u: Uint8Array): ArrayBuffer {
|
|
13
|
-
const ab = new ArrayBuffer(u.byteLength);
|
|
14
|
-
new Uint8Array(ab).set(u);
|
|
15
|
-
return ab;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* HKDF-SHA256. Defaults match backend: empty salt, the ECIES domain separation info,
|
|
20
|
-
* 32-byte output length. Pass custom values for other uses.
|
|
21
|
-
*/
|
|
22
|
-
export async function hkdfSha256(
|
|
23
|
-
ikm: Uint8Array,
|
|
24
|
-
length = 32,
|
|
25
|
-
info: Uint8Array = ECIES_HKDF_INFO,
|
|
26
|
-
salt: Uint8Array = new Uint8Array(0),
|
|
27
|
-
): Promise<Uint8Array> {
|
|
28
|
-
try {
|
|
29
|
-
const subtle = getSubtle();
|
|
30
|
-
const baseKey = await subtle.importKey('raw', toArrayBuffer(ikm), 'HKDF', false, ['deriveBits']);
|
|
31
|
-
const derived = await subtle.deriveBits(
|
|
32
|
-
{
|
|
33
|
-
name: 'HKDF',
|
|
34
|
-
hash: 'SHA-256',
|
|
35
|
-
info: toArrayBuffer(info),
|
|
36
|
-
salt: toArrayBuffer(salt),
|
|
37
|
-
},
|
|
38
|
-
baseKey,
|
|
39
|
-
length * 8,
|
|
40
|
-
);
|
|
41
|
-
return new Uint8Array(derived);
|
|
42
|
-
} catch (cause) {
|
|
43
|
-
throw new CryptoError('CRYPTO/INVALID_KEY', 'HKDF derivation failed', { cause });
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/crypto/index.ts
DELETED
package/src/crypto/keys.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
import { CryptoError } from '../errors/index.js';
|
|
3
|
-
|
|
4
|
-
export interface KeyPair {
|
|
5
|
-
privateKey: string;
|
|
6
|
-
publicKey: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/** Fresh secp256k1 keypair. Hex strings returned un-prefixed (no 0x). */
|
|
10
|
-
export function generateKeyPair(): KeyPair {
|
|
11
|
-
const w = ethers.Wallet.createRandom();
|
|
12
|
-
return {
|
|
13
|
-
privateKey: w.privateKey.slice(2),
|
|
14
|
-
publicKey: w.signingKey.publicKey.slice(2),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** Recover the uncompressed public key (un-prefixed hex) from a private key. */
|
|
19
|
-
export function derivePublicKey(privateKey: string): string {
|
|
20
|
-
const sk = new ethers.SigningKey(`0x${strip(privateKey)}`);
|
|
21
|
-
return sk.publicKey.slice(2);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function strip(hex: string): string {
|
|
25
|
-
return hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function assertUncompressedPubKey(pub: string): void {
|
|
29
|
-
const s = strip(pub);
|
|
30
|
-
if (s.length !== 130 || !/^04/i.test(s)) {
|
|
31
|
-
throw new CryptoError(
|
|
32
|
-
'CRYPTO/INVALID_KEY',
|
|
33
|
-
'expected uncompressed secp256k1 pubkey (65 bytes hex, starts with 04)',
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function hexToBytes(hex: string): Uint8Array {
|
|
39
|
-
const s = strip(hex);
|
|
40
|
-
if (s.length % 2 !== 0) {
|
|
41
|
-
throw new CryptoError('CRYPTO/INVALID_KEY', 'hex string has odd length');
|
|
42
|
-
}
|
|
43
|
-
const out = new Uint8Array(s.length / 2);
|
|
44
|
-
for (let i = 0; i < out.length; i++) {
|
|
45
|
-
const byte = Number.parseInt(s.substring(i * 2, i * 2 + 2), 16);
|
|
46
|
-
if (Number.isNaN(byte)) {
|
|
47
|
-
throw new CryptoError('CRYPTO/INVALID_KEY', `invalid hex byte at position ${i * 2}`);
|
|
48
|
-
}
|
|
49
|
-
out[i] = byte;
|
|
50
|
-
}
|
|
51
|
-
return out;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function bytesToHex(u: Uint8Array): string {
|
|
55
|
-
return Array.from(u, (b) => b.toString(16).padStart(2, '0')).join('');
|
|
56
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { ErrorCode } from './codes.js';
|
|
2
|
-
|
|
3
|
-
export interface ErrorOptions {
|
|
4
|
-
retriable?: boolean;
|
|
5
|
-
context?: Record<string, unknown>;
|
|
6
|
-
cause?: unknown;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export abstract class BlindMarketError extends Error {
|
|
10
|
-
readonly code: ErrorCode;
|
|
11
|
-
readonly retriable: boolean;
|
|
12
|
-
readonly context?: Record<string, unknown>;
|
|
13
|
-
override readonly cause?: unknown;
|
|
14
|
-
|
|
15
|
-
constructor(code: ErrorCode, message: string, opts: ErrorOptions = {}) {
|
|
16
|
-
super(message);
|
|
17
|
-
this.code = code;
|
|
18
|
-
this.retriable = opts.retriable ?? false;
|
|
19
|
-
if (opts.context !== undefined) this.context = opts.context;
|
|
20
|
-
if (opts.cause !== undefined) this.cause = opts.cause;
|
|
21
|
-
Object.defineProperty(this, 'name', {
|
|
22
|
-
value: this.constructor.name,
|
|
23
|
-
enumerable: false,
|
|
24
|
-
configurable: true,
|
|
25
|
-
writable: true,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
toJSON(): Record<string, unknown> {
|
|
30
|
-
return {
|
|
31
|
-
name: this.name,
|
|
32
|
-
code: this.code,
|
|
33
|
-
message: this.message,
|
|
34
|
-
retriable: this.retriable,
|
|
35
|
-
...(this.context ? { context: this.context } : {}),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
package/src/errors/codes.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export const ErrorCodes = {
|
|
2
|
-
Config: ['CONFIG/INVALID_NETWORK', 'CONFIG/MISSING_SIGNER', 'CONFIG/BAD_CONFIG'] as const,
|
|
3
|
-
Crypto: [
|
|
4
|
-
'CRYPTO/INVALID_KEY',
|
|
5
|
-
'CRYPTO/DECRYPT_FAILED',
|
|
6
|
-
'CRYPTO/INTEGRITY_CHECK',
|
|
7
|
-
'CRYPTO/UNSUPPORTED_CIPHER',
|
|
8
|
-
] as const,
|
|
9
|
-
Storage: [
|
|
10
|
-
'STORAGE/UPLOAD_FAILED',
|
|
11
|
-
'STORAGE/DOWNLOAD_FAILED',
|
|
12
|
-
'STORAGE/MERKLE_MISMATCH',
|
|
13
|
-
'STORAGE/NOT_FOUND',
|
|
14
|
-
'STORAGE/INDEXER_UNREACHABLE',
|
|
15
|
-
] as const,
|
|
16
|
-
Chain: [
|
|
17
|
-
'CHAIN/TX_REVERTED',
|
|
18
|
-
'CHAIN/TX_TIMED_OUT',
|
|
19
|
-
'CHAIN/NONCE_CONFLICT',
|
|
20
|
-
'CHAIN/INSUFFICIENT_BALANCE',
|
|
21
|
-
'CHAIN/NETWORK_MISMATCH',
|
|
22
|
-
'CHAIN/CONTRACT_NOT_DEPLOYED',
|
|
23
|
-
] as const,
|
|
24
|
-
Compute: [
|
|
25
|
-
'COMPUTE/BROKER_UNREACHABLE',
|
|
26
|
-
'COMPUTE/NO_PROVIDERS',
|
|
27
|
-
'COMPUTE/LEDGER_INSUFFICIENT',
|
|
28
|
-
'COMPUTE/TEE_ATTESTATION_INVALID',
|
|
29
|
-
'COMPUTE/VERIFICATION_TIMEOUT',
|
|
30
|
-
] as const,
|
|
31
|
-
Api: [
|
|
32
|
-
'API/AUTH_REQUIRED',
|
|
33
|
-
'API/AUTH_EXPIRED',
|
|
34
|
-
'API/FORBIDDEN',
|
|
35
|
-
'API/RATE_LIMITED',
|
|
36
|
-
'API/VALIDATION',
|
|
37
|
-
'API/SERVER',
|
|
38
|
-
'API/NOT_FOUND',
|
|
39
|
-
] as const,
|
|
40
|
-
Lifecycle: [
|
|
41
|
-
'LIFECYCLE/ILLEGAL_TRANSITION',
|
|
42
|
-
'LIFECYCLE/TASK_NOT_FOUND',
|
|
43
|
-
'LIFECYCLE/NOT_ASSIGNED',
|
|
44
|
-
'LIFECYCLE/ALREADY_SUBMITTED',
|
|
45
|
-
'LIFECYCLE/CLAIM_NOT_READY',
|
|
46
|
-
] as const,
|
|
47
|
-
Timeout: ['TIMEOUT'] as const,
|
|
48
|
-
} as const;
|
|
49
|
-
|
|
50
|
-
export type ConfigCode = (typeof ErrorCodes.Config)[number];
|
|
51
|
-
export type CryptoCode = (typeof ErrorCodes.Crypto)[number];
|
|
52
|
-
export type StorageCode = (typeof ErrorCodes.Storage)[number];
|
|
53
|
-
export type ChainCode = (typeof ErrorCodes.Chain)[number];
|
|
54
|
-
export type ComputeCode = (typeof ErrorCodes.Compute)[number];
|
|
55
|
-
export type ApiCode = (typeof ErrorCodes.Api)[number];
|
|
56
|
-
export type LifecycleCode = (typeof ErrorCodes.Lifecycle)[number];
|
|
57
|
-
export type TimeoutCode = (typeof ErrorCodes.Timeout)[number];
|
|
58
|
-
|
|
59
|
-
export type ErrorCode =
|
|
60
|
-
| ConfigCode
|
|
61
|
-
| CryptoCode
|
|
62
|
-
| StorageCode
|
|
63
|
-
| ChainCode
|
|
64
|
-
| ComputeCode
|
|
65
|
-
| ApiCode
|
|
66
|
-
| LifecycleCode
|
|
67
|
-
| TimeoutCode;
|
package/src/errors/index.ts
DELETED
package/src/errors/subclasses.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { BlindMarketError, type ErrorOptions } from './BlindMarketError.js';
|
|
2
|
-
import type {
|
|
3
|
-
ApiCode,
|
|
4
|
-
ChainCode,
|
|
5
|
-
ComputeCode,
|
|
6
|
-
ConfigCode,
|
|
7
|
-
CryptoCode,
|
|
8
|
-
LifecycleCode,
|
|
9
|
-
StorageCode,
|
|
10
|
-
TimeoutCode,
|
|
11
|
-
} from './codes.js';
|
|
12
|
-
|
|
13
|
-
export class ConfigError extends BlindMarketError {
|
|
14
|
-
constructor(code: ConfigCode, msg: string, opts?: ErrorOptions) {
|
|
15
|
-
super(code, msg, opts);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class CryptoError extends BlindMarketError {
|
|
20
|
-
constructor(code: CryptoCode, msg: string, opts?: ErrorOptions) {
|
|
21
|
-
super(code, msg, opts);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class StorageError extends BlindMarketError {
|
|
26
|
-
constructor(code: StorageCode, msg: string, opts?: ErrorOptions) {
|
|
27
|
-
super(code, msg, opts);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export class ChainError extends BlindMarketError {
|
|
32
|
-
constructor(code: ChainCode, msg: string, opts?: ErrorOptions) {
|
|
33
|
-
super(code, msg, opts);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class ComputeError extends BlindMarketError {
|
|
38
|
-
constructor(code: ComputeCode, msg: string, opts?: ErrorOptions) {
|
|
39
|
-
super(code, msg, opts);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export class ApiError extends BlindMarketError {
|
|
44
|
-
constructor(code: ApiCode, msg: string, opts?: ErrorOptions) {
|
|
45
|
-
super(code, msg, opts);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export class LifecycleError extends BlindMarketError {
|
|
50
|
-
constructor(code: LifecycleCode, msg: string, opts?: ErrorOptions) {
|
|
51
|
-
super(code, msg, opts);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class TimeoutError extends BlindMarketError {
|
|
56
|
-
constructor(code: TimeoutCode, msg: string, opts?: ErrorOptions) {
|
|
57
|
-
super(code, msg, opts);
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/events/EventBus.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
type Handler<T> = (payload: T) => void;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Typed pub/sub. Listener exceptions are swallowed so one bad subscriber
|
|
5
|
-
* cannot block others — telemetry plugins can observe failures via onError.
|
|
6
|
-
*/
|
|
7
|
-
export class EventBus<E> {
|
|
8
|
-
private handlers: { [K in keyof E]?: Set<Handler<E[K]>> } = {};
|
|
9
|
-
|
|
10
|
-
on<K extends keyof E>(event: K, fn: Handler<E[K]>): () => void {
|
|
11
|
-
let set = this.handlers[event];
|
|
12
|
-
if (!set) {
|
|
13
|
-
set = new Set<Handler<E[K]>>();
|
|
14
|
-
this.handlers[event] = set;
|
|
15
|
-
}
|
|
16
|
-
set.add(fn);
|
|
17
|
-
return () => {
|
|
18
|
-
this.off(event, fn);
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
once<K extends keyof E>(event: K, fn: Handler<E[K]>): () => void {
|
|
23
|
-
const wrapped: Handler<E[K]> = (p) => {
|
|
24
|
-
this.off(event, wrapped);
|
|
25
|
-
fn(p);
|
|
26
|
-
};
|
|
27
|
-
return this.on(event, wrapped);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
off<K extends keyof E>(event: K, fn: Handler<E[K]>): void {
|
|
31
|
-
this.handlers[event]?.delete(fn);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
emit<K extends keyof E>(event: K, payload: E[K]): void {
|
|
35
|
-
const hs = this.handlers[event];
|
|
36
|
-
if (!hs) return;
|
|
37
|
-
for (const h of hs) {
|
|
38
|
-
try {
|
|
39
|
-
h(payload);
|
|
40
|
-
} catch {
|
|
41
|
-
// Isolated per-listener — prevents one bad subscriber from blocking others.
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
package/src/events/index.ts
DELETED
package/src/events/types.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Address, Hex, RootHash, TaskId } from '../types.js';
|
|
2
|
-
|
|
3
|
-
export interface SdkEvents {
|
|
4
|
-
'task.created': { taskId: TaskId; txHash: Hex; rootHash: RootHash };
|
|
5
|
-
'task.assigned': { taskId: TaskId; worker: Address; txHash: Hex };
|
|
6
|
-
'task.cancelled': { taskId: TaskId; txHash: Hex };
|
|
7
|
-
'evidence.submitted': { taskId: TaskId; rootHash: RootHash; txHash: Hex };
|
|
8
|
-
'verification.done': { taskId: TaskId; passed: boolean; confidence: number };
|
|
9
|
-
'payment.claimed': { taskId: TaskId; txHash: Hex; amount: bigint };
|
|
10
|
-
'tx.sent': { hash: Hex; from: Address; to: Address };
|
|
11
|
-
'tx.confirmed': { hash: Hex; blockNumber: number };
|
|
12
|
-
'tx.failed': { hash: Hex; reason: string };
|
|
13
|
-
}
|