@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.
- package/README.md +72 -0
- package/biome.json +19 -0
- package/dist/BlindEscrowClient-CyPuKMge.d.cts +54 -0
- package/dist/BlindEscrowClient-R7iGpE-n.d.ts +54 -0
- package/dist/KeyStore-Be_SSpCt.d.cts +21 -0
- package/dist/KeyStore-k1JgYPJY.d.ts +21 -0
- package/dist/Signer-BnqH_qew.d.cts +38 -0
- package/dist/Signer-LColE0Uo.d.ts +38 -0
- package/dist/Storage-4QOrh7rm.d.ts +17 -0
- package/dist/Storage-Cf4IJRMk.d.cts +17 -0
- package/dist/TaskRegistryClient-Ch6lYqM_.d.ts +24 -0
- package/dist/TaskRegistryClient-CrQjddDc.d.cts +24 -0
- package/dist/aes-J-7HrHze.d.cts +17 -0
- package/dist/aes-J-7HrHze.d.ts +17 -0
- package/dist/agent/Agent.d.ts +59 -0
- package/dist/agent/Agent.js +73 -0
- package/dist/agent/index.cjs +425 -0
- package/dist/agent/index.cjs.map +1 -0
- package/dist/agent/index.d.cts +63 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/api/index.cjs +4 -0
- package/dist/api/index.cjs.map +1 -0
- package/dist/api/index.d.cts +2 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/index.js.map +1 -0
- package/dist/chain/BlindEscrowClient.d.ts +51 -0
- package/dist/chain/BlindEscrowClient.js +142 -0
- package/dist/chain/BlindReputationClient.d.ts +16 -0
- package/dist/chain/BlindReputationClient.js +45 -0
- package/dist/chain/ChainClient.d.ts +26 -0
- package/dist/chain/ChainClient.js +46 -0
- package/dist/chain/TaskRegistryClient.d.ts +21 -0
- package/dist/chain/TaskRegistryClient.js +70 -0
- package/dist/chain/abi/BlindEscrow.json +1113 -0
- package/dist/chain/abi/BlindReputation.json +447 -0
- package/dist/chain/abi/TaskRegistry.json +586 -0
- package/dist/chain/abi/index.d.ts +4 -0
- package/dist/chain/abi/index.js +4 -0
- package/dist/chain/errors.d.ts +8 -0
- package/dist/chain/errors.js +32 -0
- package/dist/chain/index.cjs +2484 -0
- package/dist/chain/index.cjs.map +1 -0
- package/dist/chain/index.d.cts +2305 -0
- package/dist/chain/index.d.ts +6 -0
- package/dist/chain/index.js +6 -0
- package/dist/chain/index.js.map +1 -0
- package/dist/compute/index.cjs +4 -0
- package/dist/compute/index.cjs.map +1 -0
- package/dist/compute/index.d.cts +2 -0
- package/dist/compute/index.d.ts +1 -0
- package/dist/compute/index.js +1 -0
- package/dist/compute/index.js.map +1 -0
- package/dist/crypto/aes.d.ts +15 -0
- package/dist/crypto/aes.js +81 -0
- package/dist/crypto/constants.d.ts +7 -0
- package/dist/crypto/constants.js +7 -0
- package/dist/crypto/ecies.d.ts +8 -0
- package/dist/crypto/ecies.js +51 -0
- package/dist/crypto/envelope.d.ts +35 -0
- package/dist/crypto/envelope.js +103 -0
- package/dist/crypto/hkdf.d.ts +5 -0
- package/dist/crypto/hkdf.js +34 -0
- package/dist/crypto/index.cjs +424 -0
- package/dist/crypto/index.cjs.map +1 -0
- package/dist/crypto/index.d.cts +74 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/keys.d.ts +12 -0
- package/dist/crypto/keys.js +42 -0
- package/dist/errors/BlindBountyError.d.ts +14 -0
- package/dist/errors/BlindBountyError.js +30 -0
- package/dist/errors/codes.d.ts +19 -0
- package/dist/errors/codes.js +48 -0
- package/dist/errors/index.cjs +136 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +60 -0
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/subclasses.d.ts +26 -0
- package/dist/errors/subclasses.js +41 -0
- package/dist/events/EventBus.d.ts +13 -0
- package/dist/events/EventBus.js +41 -0
- package/dist/events/index.cjs +41 -0
- package/dist/events/index.cjs.map +1 -0
- package/dist/events/index.d.cts +61 -0
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +45 -0
- package/dist/events/types.js +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/dist/keystore/InMemoryKeyStore.d.ts +21 -0
- package/dist/keystore/InMemoryKeyStore.js +111 -0
- package/dist/keystore/KeyStore.d.ts +18 -0
- package/dist/keystore/KeyStore.js +1 -0
- package/dist/keystore/index.cjs +335 -0
- package/dist/keystore/index.cjs.map +1 -0
- package/dist/keystore/index.d.cts +23 -0
- package/dist/keystore/index.d.ts +2 -0
- package/dist/keystore/index.js +2 -0
- package/dist/keystore/index.js.map +1 -0
- package/dist/network/index.cjs +74 -0
- package/dist/network/index.cjs.map +1 -0
- package/dist/network/index.d.cts +36 -0
- package/dist/network/index.d.ts +3 -0
- package/dist/network/index.js +3 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/presets.d.ts +24 -0
- package/dist/network/presets.js +23 -0
- package/dist/network/resolve.d.ts +7 -0
- package/dist/network/resolve.js +17 -0
- package/dist/network/types.d.ts +16 -0
- package/dist/network/types.js +1 -0
- package/dist/signer/EthersSigner.d.ts +24 -0
- package/dist/signer/EthersSigner.js +68 -0
- package/dist/signer/PrivateKeySigner.d.ts +14 -0
- package/dist/signer/PrivateKeySigner.js +18 -0
- package/dist/signer/Signer.d.ts +35 -0
- package/dist/signer/Signer.js +1 -0
- package/dist/signer/index.cjs +121 -0
- package/dist/signer/index.cjs.map +1 -0
- package/dist/signer/index.d.cts +40 -0
- package/dist/signer/index.d.ts +3 -0
- package/dist/signer/index.js +3 -0
- package/dist/signer/index.js.map +1 -0
- package/dist/storage/MemoryStorage.d.ts +18 -0
- package/dist/storage/MemoryStorage.js +40 -0
- package/dist/storage/Storage.d.ts +14 -0
- package/dist/storage/Storage.js +1 -0
- package/dist/storage/ZgStorage.d.ts +24 -0
- package/dist/storage/ZgStorage.js +102 -0
- package/dist/storage/index.cjs +221 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +44 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/testing/index.cjs +4 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +2 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-BOG5Ub1z.d.cts +31 -0
- package/dist/types-BOG5Ub1z.d.ts +31 -0
- package/dist/types-V7_ZmUb-.d.cts +19 -0
- package/dist/types-hAsITUQ7.d.ts +19 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +1 -0
- package/dist/verifier/index.cjs +4 -0
- package/dist/verifier/index.cjs.map +1 -0
- package/dist/verifier/index.d.cts +2 -0
- package/dist/verifier/index.d.ts +1 -0
- package/dist/verifier/index.js +1 -0
- package/dist/verifier/index.js.map +1 -0
- package/dist/worker/Worker.d.ts +53 -0
- package/dist/worker/Worker.js +53 -0
- package/dist/worker/index.cjs +382 -0
- package/dist/worker/index.cjs.map +1 -0
- package/dist/worker/index.d.cts +58 -0
- package/dist/worker/index.d.ts +1 -0
- package/dist/worker/index.js +1 -0
- package/dist/worker/index.js.map +1 -0
- package/examples/agent-demo.ts +121 -0
- package/package.json +46 -0
- package/scripts/gen-crypto-fixtures.mjs +72 -0
- package/src/agent/Agent.ts +122 -0
- package/src/agent/index.ts +1 -0
- package/src/api/index.ts +1 -0
- package/src/chain/BlindEscrowClient.ts +182 -0
- package/src/chain/BlindReputationClient.ts +55 -0
- package/src/chain/ChainClient.ts +59 -0
- package/src/chain/TaskRegistryClient.ts +82 -0
- package/src/chain/abi/BlindEscrow.json +1113 -0
- package/src/chain/abi/BlindReputation.json +447 -0
- package/src/chain/abi/TaskRegistry.json +586 -0
- package/src/chain/abi/index.ts +5 -0
- package/src/chain/errors.ts +43 -0
- package/src/chain/index.ts +6 -0
- package/src/compute/index.ts +1 -0
- package/src/crypto/aes.ts +104 -0
- package/src/crypto/constants.ts +7 -0
- package/src/crypto/ecies.ts +60 -0
- package/src/crypto/envelope.ts +131 -0
- package/src/crypto/hkdf.ts +45 -0
- package/src/crypto/index.ts +6 -0
- package/src/crypto/keys.ts +56 -0
- package/src/errors/BlindMarketError.ts +38 -0
- package/src/errors/codes.ts +67 -0
- package/src/errors/index.ts +3 -0
- package/src/errors/subclasses.ts +59 -0
- package/src/events/EventBus.ts +45 -0
- package/src/events/index.ts +2 -0
- package/src/events/types.ts +13 -0
- package/src/index.ts +222 -0
- package/src/keystore/InMemoryKeyStore.ts +146 -0
- package/src/keystore/KeyStore.ts +19 -0
- package/src/keystore/index.ts +2 -0
- package/src/network/index.ts +3 -0
- package/src/network/presets.ts +27 -0
- package/src/network/resolve.ts +19 -0
- package/src/network/types.ts +18 -0
- package/src/signer/EthersSigner.ts +82 -0
- package/src/signer/PrivateKeySigner.ts +19 -0
- package/src/signer/Signer.ts +40 -0
- package/src/signer/index.ts +3 -0
- package/src/storage/MemoryStorage.ts +49 -0
- package/src/storage/Storage.ts +15 -0
- package/src/storage/ZgStorage.ts +124 -0
- package/src/storage/index.ts +3 -0
- package/src/testing/index.ts +1 -0
- package/src/types.ts +76 -0
- package/src/verifier/index.ts +1 -0
- package/src/worker/Worker.ts +98 -0
- package/src/worker/index.ts +1 -0
- package/test/agent.test.ts +193 -0
- package/test/chain.test.ts +145 -0
- package/test/crypto.aes.test.ts +81 -0
- package/test/crypto.compat.test.ts +33 -0
- package/test/crypto.ecies.test.ts +64 -0
- package/test/envelope.test.ts +82 -0
- package/test/errors.test.ts +64 -0
- package/test/events.test.ts +59 -0
- package/test/fixtures/crypto.json +16 -0
- package/test/keystore.test.ts +103 -0
- package/test/network.test.ts +53 -0
- package/test/signer.test.ts +66 -0
- package/test/smoke.test.ts +7 -0
- package/test/storage.test.ts +55 -0
- package/test/worker.test.ts +181 -0
- package/tsconfig.build.json +1 -0
- package/tsconfig.json +13 -0
- package/tsup.config.ts +32 -0
- package/vitest.config.ts +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @blindmarket/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for [BlindMarket](https://github.com/JemIIahh/BlindMarket) — the privacy-first task marketplace where AI agents delegate real-world tasks to humans, powered by 0G.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @blindmarket/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Agent, PrivateKeySigner, ogTestnet } from '@blindmarket/sdk';
|
|
15
|
+
|
|
16
|
+
const signer = new PrivateKeySigner(process.env.PRIVATE_KEY!);
|
|
17
|
+
|
|
18
|
+
const agent = new Agent({
|
|
19
|
+
signer,
|
|
20
|
+
network: ogTestnet,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Post an encrypted task
|
|
24
|
+
const { taskId } = await agent.createTask({
|
|
25
|
+
instructions: 'Photograph the storefront at 123 Main St',
|
|
26
|
+
amount: '100', // USDC
|
|
27
|
+
token: '0x3af9...',
|
|
28
|
+
durationSeconds: 86400, // 24h
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
console.log('Task created:', taskId);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- **AES-256-GCM** encryption for task instructions and evidence
|
|
37
|
+
- **ECIES** key wrapping — only the assigned worker can decrypt
|
|
38
|
+
- **0G Storage** — encrypted blobs stored on decentralized storage
|
|
39
|
+
- **0G Sealed Inference** — TEE-verified evidence evaluation
|
|
40
|
+
- Full task lifecycle: create → assign → submit → verify → pay
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// Agent
|
|
46
|
+
agent.createTask(options)
|
|
47
|
+
agent.assignWorker(taskId, workerAddress)
|
|
48
|
+
agent.triggerVerification(taskId)
|
|
49
|
+
agent.cancelTask(taskId)
|
|
50
|
+
|
|
51
|
+
// Worker
|
|
52
|
+
worker.getAssignedTask(taskId) // decrypts instructions
|
|
53
|
+
worker.submitEvidence(taskId, evidence)
|
|
54
|
+
|
|
55
|
+
// Reputation
|
|
56
|
+
client.getReputation(address)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Network
|
|
60
|
+
|
|
61
|
+
Deployed on **0G Testnet Galileo** (Chain ID: 16602)
|
|
62
|
+
|
|
63
|
+
| Contract | Address |
|
|
64
|
+
|---|---|
|
|
65
|
+
| BlindEscrow | `0x037529B296a89E6Dd1abAF84D413cb2dD70C5be5` |
|
|
66
|
+
| TaskRegistry | `0x25Bc5be1F8Ab44ADfb7a6Ce1362d37408E74DA95` |
|
|
67
|
+
| BlindReputation | `0x3d0374963DaaD43e31d42373eb11156A8e8ce2Ff` |
|
|
68
|
+
| ValidatorPool | `0xdBb2f891a2584a573a6637500158A99caa19b11D` |
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT
|
package/biome.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
3
|
+
"organizeImports": { "enabled": true },
|
|
4
|
+
"linter": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"rules": {
|
|
7
|
+
"recommended": true,
|
|
8
|
+
"suspicious": { "noExplicitAny": "error" },
|
|
9
|
+
"style": { "useImportType": "error" }
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"formatter": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"indentStyle": "space",
|
|
15
|
+
"indentWidth": 2,
|
|
16
|
+
"lineWidth": 120,
|
|
17
|
+
"lineEnding": "lf"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { A as Address, H as Hex, T as TaskId, b as TxReceiptLike, e as TaskStatus } from './types-BOG5Ub1z.cjs';
|
|
3
|
+
|
|
4
|
+
interface CreateTaskArgs {
|
|
5
|
+
taskHash: Hex;
|
|
6
|
+
token: Address;
|
|
7
|
+
amount: bigint;
|
|
8
|
+
category: string;
|
|
9
|
+
locationZone: string;
|
|
10
|
+
deadline: bigint;
|
|
11
|
+
}
|
|
12
|
+
interface OnChainTask {
|
|
13
|
+
taskId: TaskId;
|
|
14
|
+
agent: Address;
|
|
15
|
+
worker: Address;
|
|
16
|
+
token: Address;
|
|
17
|
+
amount: bigint;
|
|
18
|
+
taskHash: Hex;
|
|
19
|
+
evidenceHash: Hex;
|
|
20
|
+
status: TaskStatus;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
deadline: Date;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Typed ethers v6 wrapper for the BlindEscrow contract. Every state-changing
|
|
26
|
+
* method awaits one confirmation and returns a TxReceiptLike; every read
|
|
27
|
+
* returns decoded values. Ethers errors are mapped to ChainError via
|
|
28
|
+
* wrapChainError().
|
|
29
|
+
*/
|
|
30
|
+
declare class BlindEscrowClient {
|
|
31
|
+
readonly contract: ethers.Contract;
|
|
32
|
+
readonly address: Address;
|
|
33
|
+
constructor(address: Address, runner: ethers.ContractRunner);
|
|
34
|
+
/** Create a task and return its id + receipt. Reads the TaskCreated event for the id. */
|
|
35
|
+
createTask(args: CreateTaskArgs): Promise<{
|
|
36
|
+
taskId: TaskId;
|
|
37
|
+
receipt: TxReceiptLike;
|
|
38
|
+
}>;
|
|
39
|
+
assignWorker(taskId: TaskId, worker: Address): Promise<TxReceiptLike>;
|
|
40
|
+
submitEvidence(taskId: TaskId, evidenceHash: Hex): Promise<TxReceiptLike>;
|
|
41
|
+
completeVerification(taskId: TaskId, passed: boolean): Promise<TxReceiptLike>;
|
|
42
|
+
cancelTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
43
|
+
raiseDispute(taskId: TaskId): Promise<TxReceiptLike>;
|
|
44
|
+
resolveDispute(taskId: TaskId, workerFavored: boolean): Promise<TxReceiptLike>;
|
|
45
|
+
claimTimeout(taskId: TaskId): Promise<TxReceiptLike>;
|
|
46
|
+
getTask(taskId: TaskId): Promise<OnChainTask>;
|
|
47
|
+
isTaskExpired(taskId: TaskId): Promise<boolean>;
|
|
48
|
+
nextTaskId(): Promise<TaskId>;
|
|
49
|
+
feeBps(): Promise<bigint>;
|
|
50
|
+
private sendTx;
|
|
51
|
+
private extractTaskIdFromReceipt;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { BlindEscrowClient as B, type CreateTaskArgs as C, type OnChainTask as O };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { A as Address, H as Hex, T as TaskId, b as TxReceiptLike, e as TaskStatus } from './types-BOG5Ub1z.js';
|
|
3
|
+
|
|
4
|
+
interface CreateTaskArgs {
|
|
5
|
+
taskHash: Hex;
|
|
6
|
+
token: Address;
|
|
7
|
+
amount: bigint;
|
|
8
|
+
category: string;
|
|
9
|
+
locationZone: string;
|
|
10
|
+
deadline: bigint;
|
|
11
|
+
}
|
|
12
|
+
interface OnChainTask {
|
|
13
|
+
taskId: TaskId;
|
|
14
|
+
agent: Address;
|
|
15
|
+
worker: Address;
|
|
16
|
+
token: Address;
|
|
17
|
+
amount: bigint;
|
|
18
|
+
taskHash: Hex;
|
|
19
|
+
evidenceHash: Hex;
|
|
20
|
+
status: TaskStatus;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
deadline: Date;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Typed ethers v6 wrapper for the BlindEscrow contract. Every state-changing
|
|
26
|
+
* method awaits one confirmation and returns a TxReceiptLike; every read
|
|
27
|
+
* returns decoded values. Ethers errors are mapped to ChainError via
|
|
28
|
+
* wrapChainError().
|
|
29
|
+
*/
|
|
30
|
+
declare class BlindEscrowClient {
|
|
31
|
+
readonly contract: ethers.Contract;
|
|
32
|
+
readonly address: Address;
|
|
33
|
+
constructor(address: Address, runner: ethers.ContractRunner);
|
|
34
|
+
/** Create a task and return its id + receipt. Reads the TaskCreated event for the id. */
|
|
35
|
+
createTask(args: CreateTaskArgs): Promise<{
|
|
36
|
+
taskId: TaskId;
|
|
37
|
+
receipt: TxReceiptLike;
|
|
38
|
+
}>;
|
|
39
|
+
assignWorker(taskId: TaskId, worker: Address): Promise<TxReceiptLike>;
|
|
40
|
+
submitEvidence(taskId: TaskId, evidenceHash: Hex): Promise<TxReceiptLike>;
|
|
41
|
+
completeVerification(taskId: TaskId, passed: boolean): Promise<TxReceiptLike>;
|
|
42
|
+
cancelTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
43
|
+
raiseDispute(taskId: TaskId): Promise<TxReceiptLike>;
|
|
44
|
+
resolveDispute(taskId: TaskId, workerFavored: boolean): Promise<TxReceiptLike>;
|
|
45
|
+
claimTimeout(taskId: TaskId): Promise<TxReceiptLike>;
|
|
46
|
+
getTask(taskId: TaskId): Promise<OnChainTask>;
|
|
47
|
+
isTaskExpired(taskId: TaskId): Promise<boolean>;
|
|
48
|
+
nextTaskId(): Promise<TaskId>;
|
|
49
|
+
feeBps(): Promise<bigint>;
|
|
50
|
+
private sendTx;
|
|
51
|
+
private extractTaskIdFromReceipt;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { BlindEscrowClient as B, type CreateTaskArgs as C, type OnChainTask as O };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { T as TaskId, a as TaskKey, A as Address, H as Hex, c as TaskKeyRef } from './types-BOG5Ub1z.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Per-session storage for task AES keys and cached peer public keys. The SDK
|
|
5
|
+
* never logs or serializes anything from here — this is the one place at-rest
|
|
6
|
+
* secrets live. Implementations MUST treat passphrase-protected exports as the
|
|
7
|
+
* only portable format.
|
|
8
|
+
*/
|
|
9
|
+
interface KeyStore {
|
|
10
|
+
putTaskKey(taskId: TaskId, key: TaskKey): Promise<void>;
|
|
11
|
+
getTaskKey(taskId: TaskId): Promise<TaskKey | null>;
|
|
12
|
+
putPeerPubKey(addr: Address, pubkey: Hex): Promise<void>;
|
|
13
|
+
getPeerPubKey(addr: Address): Promise<Hex | null>;
|
|
14
|
+
list(): Promise<TaskKeyRef[]>;
|
|
15
|
+
delete(taskId: TaskId): Promise<void>;
|
|
16
|
+
/** Portable, encrypted-at-rest JSON export for backup/migration. */
|
|
17
|
+
export(passphrase: string): Promise<string>;
|
|
18
|
+
import(data: string, passphrase: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type { KeyStore as K };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { T as TaskId, a as TaskKey, A as Address, H as Hex, c as TaskKeyRef } from './types-BOG5Ub1z.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Per-session storage for task AES keys and cached peer public keys. The SDK
|
|
5
|
+
* never logs or serializes anything from here — this is the one place at-rest
|
|
6
|
+
* secrets live. Implementations MUST treat passphrase-protected exports as the
|
|
7
|
+
* only portable format.
|
|
8
|
+
*/
|
|
9
|
+
interface KeyStore {
|
|
10
|
+
putTaskKey(taskId: TaskId, key: TaskKey): Promise<void>;
|
|
11
|
+
getTaskKey(taskId: TaskId): Promise<TaskKey | null>;
|
|
12
|
+
putPeerPubKey(addr: Address, pubkey: Hex): Promise<void>;
|
|
13
|
+
getPeerPubKey(addr: Address): Promise<Hex | null>;
|
|
14
|
+
list(): Promise<TaskKeyRef[]>;
|
|
15
|
+
delete(taskId: TaskId): Promise<void>;
|
|
16
|
+
/** Portable, encrypted-at-rest JSON export for backup/migration. */
|
|
17
|
+
export(passphrase: string): Promise<string>;
|
|
18
|
+
import(data: string, passphrase: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type { KeyStore as K };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { A as Address, H as Hex } from './types-BOG5Ub1z.cjs';
|
|
2
|
+
|
|
3
|
+
interface TxRequest {
|
|
4
|
+
to: Address;
|
|
5
|
+
from?: Address;
|
|
6
|
+
data?: Hex;
|
|
7
|
+
value?: bigint;
|
|
8
|
+
gasLimit?: bigint;
|
|
9
|
+
nonce?: number;
|
|
10
|
+
chainId?: bigint;
|
|
11
|
+
}
|
|
12
|
+
interface TypedDataDomain {
|
|
13
|
+
name?: string;
|
|
14
|
+
version?: string;
|
|
15
|
+
chainId?: bigint | number;
|
|
16
|
+
verifyingContract?: Address;
|
|
17
|
+
salt?: Hex;
|
|
18
|
+
}
|
|
19
|
+
type TypedDataField = {
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Uniform signing interface used across the SDK. Adapters wrap ethers Signer,
|
|
25
|
+
* raw private keys, EIP-1193 providers, or KMS. Implementations MUST return
|
|
26
|
+
* hex-encoded signatures (0x-prefixed) and addresses (0x-prefixed, 20 bytes).
|
|
27
|
+
*/
|
|
28
|
+
interface Signer {
|
|
29
|
+
getAddress(): Promise<Address>;
|
|
30
|
+
chainId(): Promise<bigint>;
|
|
31
|
+
signMessage(msg: string | Uint8Array): Promise<Hex>;
|
|
32
|
+
signTypedData(domain: TypedDataDomain, types: Record<string, TypedDataField[]>, value: Record<string, unknown>): Promise<Hex>;
|
|
33
|
+
signTransaction(tx: TxRequest): Promise<Hex>;
|
|
34
|
+
/** Uncompressed secp256k1 public key, 0x04-prefixed (hex). */
|
|
35
|
+
getPublicKey(): Promise<Hex>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type { Signer as S, TypedDataDomain as T, TypedDataField as a, TxRequest as b };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { A as Address, H as Hex } from './types-BOG5Ub1z.js';
|
|
2
|
+
|
|
3
|
+
interface TxRequest {
|
|
4
|
+
to: Address;
|
|
5
|
+
from?: Address;
|
|
6
|
+
data?: Hex;
|
|
7
|
+
value?: bigint;
|
|
8
|
+
gasLimit?: bigint;
|
|
9
|
+
nonce?: number;
|
|
10
|
+
chainId?: bigint;
|
|
11
|
+
}
|
|
12
|
+
interface TypedDataDomain {
|
|
13
|
+
name?: string;
|
|
14
|
+
version?: string;
|
|
15
|
+
chainId?: bigint | number;
|
|
16
|
+
verifyingContract?: Address;
|
|
17
|
+
salt?: Hex;
|
|
18
|
+
}
|
|
19
|
+
type TypedDataField = {
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Uniform signing interface used across the SDK. Adapters wrap ethers Signer,
|
|
25
|
+
* raw private keys, EIP-1193 providers, or KMS. Implementations MUST return
|
|
26
|
+
* hex-encoded signatures (0x-prefixed) and addresses (0x-prefixed, 20 bytes).
|
|
27
|
+
*/
|
|
28
|
+
interface Signer {
|
|
29
|
+
getAddress(): Promise<Address>;
|
|
30
|
+
chainId(): Promise<bigint>;
|
|
31
|
+
signMessage(msg: string | Uint8Array): Promise<Hex>;
|
|
32
|
+
signTypedData(domain: TypedDataDomain, types: Record<string, TypedDataField[]>, value: Record<string, unknown>): Promise<Hex>;
|
|
33
|
+
signTransaction(tx: TxRequest): Promise<Hex>;
|
|
34
|
+
/** Uncompressed secp256k1 public key, 0x04-prefixed (hex). */
|
|
35
|
+
getPublicKey(): Promise<Hex>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type { Signer as S, TypedDataDomain as T, TypedDataField as a, TxRequest as b };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { U as UploadResult, d as RootHash } from './types-BOG5Ub1z.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstraction over blob storage. Default implementation (ZgStorage) uses
|
|
5
|
+
* 0G Storage; MemoryStorage is for tests and local fallback. Consumers can
|
|
6
|
+
* provide their own adapter for IPFS, S3, etc.
|
|
7
|
+
*/
|
|
8
|
+
interface Storage {
|
|
9
|
+
/** Upload bytes, return root hash + optional tx hash + size. */
|
|
10
|
+
upload(bytes: Uint8Array): Promise<UploadResult>;
|
|
11
|
+
/** Download bytes by root hash. Throws StorageError('STORAGE/NOT_FOUND') if absent. */
|
|
12
|
+
download(rootHash: RootHash): Promise<Uint8Array>;
|
|
13
|
+
/** Compute the canonical root hash without uploading. */
|
|
14
|
+
hash(bytes: Uint8Array): Promise<RootHash>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type { Storage as S };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { U as UploadResult, d as RootHash } from './types-BOG5Ub1z.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstraction over blob storage. Default implementation (ZgStorage) uses
|
|
5
|
+
* 0G Storage; MemoryStorage is for tests and local fallback. Consumers can
|
|
6
|
+
* provide their own adapter for IPFS, S3, etc.
|
|
7
|
+
*/
|
|
8
|
+
interface Storage {
|
|
9
|
+
/** Upload bytes, return root hash + optional tx hash + size. */
|
|
10
|
+
upload(bytes: Uint8Array): Promise<UploadResult>;
|
|
11
|
+
/** Download bytes by root hash. Throws StorageError('STORAGE/NOT_FOUND') if absent. */
|
|
12
|
+
download(rootHash: RootHash): Promise<Uint8Array>;
|
|
13
|
+
/** Compute the canonical root hash without uploading. */
|
|
14
|
+
hash(bytes: Uint8Array): Promise<RootHash>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type { Storage as S };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { A as Address, T as TaskId, b as TxReceiptLike } from './types-BOG5Ub1z.js';
|
|
3
|
+
|
|
4
|
+
interface OpenTaskMeta {
|
|
5
|
+
taskId: TaskId;
|
|
6
|
+
token: Address;
|
|
7
|
+
category: string;
|
|
8
|
+
locationZone: string;
|
|
9
|
+
reward: bigint;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
}
|
|
12
|
+
declare class TaskRegistryClient {
|
|
13
|
+
readonly contract: ethers.Contract;
|
|
14
|
+
readonly address: Address;
|
|
15
|
+
constructor(address: Address, runner: ethers.ContractRunner);
|
|
16
|
+
getTaskMeta(taskId: TaskId): Promise<OpenTaskMeta>;
|
|
17
|
+
getOpenTasks(offset: bigint, limit: bigint): Promise<TaskId[]>;
|
|
18
|
+
totalTasks(): Promise<bigint>;
|
|
19
|
+
openTaskCount(): Promise<bigint>;
|
|
20
|
+
taskExists(taskId: TaskId): Promise<boolean>;
|
|
21
|
+
closeTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { type OpenTaskMeta as O, TaskRegistryClient as T };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { A as Address, T as TaskId, b as TxReceiptLike } from './types-BOG5Ub1z.cjs';
|
|
3
|
+
|
|
4
|
+
interface OpenTaskMeta {
|
|
5
|
+
taskId: TaskId;
|
|
6
|
+
token: Address;
|
|
7
|
+
category: string;
|
|
8
|
+
locationZone: string;
|
|
9
|
+
reward: bigint;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
}
|
|
12
|
+
declare class TaskRegistryClient {
|
|
13
|
+
readonly contract: ethers.Contract;
|
|
14
|
+
readonly address: Address;
|
|
15
|
+
constructor(address: Address, runner: ethers.ContractRunner);
|
|
16
|
+
getTaskMeta(taskId: TaskId): Promise<OpenTaskMeta>;
|
|
17
|
+
getOpenTasks(offset: bigint, limit: bigint): Promise<TaskId[]>;
|
|
18
|
+
totalTasks(): Promise<bigint>;
|
|
19
|
+
openTaskCount(): Promise<bigint>;
|
|
20
|
+
taskExists(taskId: TaskId): Promise<boolean>;
|
|
21
|
+
closeTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { type OpenTaskMeta as O, TaskRegistryClient as T };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Generate a fresh 32-byte AES-256 key. */
|
|
2
|
+
declare function generateAesKey(): Promise<Uint8Array>;
|
|
3
|
+
/**
|
|
4
|
+
* AES-256-GCM encrypt. Output format: [12 IV][16 tag][ciphertext].
|
|
5
|
+
* This ordering matches backend/src/services/crypto.ts and frontend/src/lib/crypto.ts
|
|
6
|
+
* byte-for-byte, so SDK blobs decrypt anywhere in the stack.
|
|
7
|
+
*/
|
|
8
|
+
declare function aesEncrypt(plaintext: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
|
|
9
|
+
/**
|
|
10
|
+
* AES-256-GCM decrypt. Input format: [12 IV][16 tag][ciphertext].
|
|
11
|
+
* Throws CRYPTO/INTEGRITY_CHECK on truncation or tag mismatch.
|
|
12
|
+
*/
|
|
13
|
+
declare function aesDecrypt(blob: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
|
|
14
|
+
/** SHA-256 of arbitrary bytes. Returns 32-byte digest. */
|
|
15
|
+
declare function sha256(data: Uint8Array): Promise<Uint8Array>;
|
|
16
|
+
|
|
17
|
+
export { aesDecrypt as a, aesEncrypt as b, generateAesKey as g, sha256 as s };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Generate a fresh 32-byte AES-256 key. */
|
|
2
|
+
declare function generateAesKey(): Promise<Uint8Array>;
|
|
3
|
+
/**
|
|
4
|
+
* AES-256-GCM encrypt. Output format: [12 IV][16 tag][ciphertext].
|
|
5
|
+
* This ordering matches backend/src/services/crypto.ts and frontend/src/lib/crypto.ts
|
|
6
|
+
* byte-for-byte, so SDK blobs decrypt anywhere in the stack.
|
|
7
|
+
*/
|
|
8
|
+
declare function aesEncrypt(plaintext: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
|
|
9
|
+
/**
|
|
10
|
+
* AES-256-GCM decrypt. Input format: [12 IV][16 tag][ciphertext].
|
|
11
|
+
* Throws CRYPTO/INTEGRITY_CHECK on truncation or tag mismatch.
|
|
12
|
+
*/
|
|
13
|
+
declare function aesDecrypt(blob: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
|
|
14
|
+
/** SHA-256 of arbitrary bytes. Returns 32-byte digest. */
|
|
15
|
+
declare function sha256(data: Uint8Array): Promise<Uint8Array>;
|
|
16
|
+
|
|
17
|
+
export { aesDecrypt as a, aesEncrypt as b, generateAesKey as g, sha256 as s };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { BlindEscrowClient } from '../chain/index.js';
|
|
2
|
+
import type { EventBus, SdkEvents } from '../events/index.js';
|
|
3
|
+
import type { KeyStore } from '../keystore/index.js';
|
|
4
|
+
import type { Signer } from '../signer/index.js';
|
|
5
|
+
import type { Storage } from '../storage/index.js';
|
|
6
|
+
import type { Address, Hex, Reward, TaskId, TaskKey, TxReceiptLike } from '../types.js';
|
|
7
|
+
export interface AgentDeps {
|
|
8
|
+
escrow: BlindEscrowClient;
|
|
9
|
+
storage: Storage;
|
|
10
|
+
keystore: KeyStore;
|
|
11
|
+
signer: Signer;
|
|
12
|
+
events?: EventBus<SdkEvents>;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateTaskInput {
|
|
15
|
+
instructions: string | Uint8Array;
|
|
16
|
+
category: string;
|
|
17
|
+
locationZone: string;
|
|
18
|
+
reward: Reward & {
|
|
19
|
+
token: Address;
|
|
20
|
+
};
|
|
21
|
+
deadline: Date | bigint;
|
|
22
|
+
}
|
|
23
|
+
export interface CreateTaskResult {
|
|
24
|
+
taskId: TaskId;
|
|
25
|
+
taskKey: TaskKey;
|
|
26
|
+
rootHash: Hex;
|
|
27
|
+
txHash: Hex;
|
|
28
|
+
receipt: TxReceiptLike;
|
|
29
|
+
}
|
|
30
|
+
export interface AssignWorkerResult {
|
|
31
|
+
wrappedKey: Uint8Array;
|
|
32
|
+
receipt: TxReceiptLike;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* End-to-end agent flows. Composes storage + crypto + chain + keystore so a
|
|
36
|
+
* caller can post an encrypted bounty in one call. Key exchange with the
|
|
37
|
+
* worker is intentionally out-of-band: assignWorker() returns the wrapped
|
|
38
|
+
* AES key as bytes, and the caller is responsible for delivering it (backend
|
|
39
|
+
* API, DM, whatever). This keeps the SDK pluggable across different
|
|
40
|
+
* message-passing substrates.
|
|
41
|
+
*/
|
|
42
|
+
export declare class Agent {
|
|
43
|
+
private readonly deps;
|
|
44
|
+
constructor(deps: AgentDeps);
|
|
45
|
+
createTask(input: CreateTaskInput): Promise<CreateTaskResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Wrap the stored AES key for the chosen worker and record the assignment
|
|
48
|
+
* on-chain. The caller must deliver `wrappedKey` to the worker separately
|
|
49
|
+
* (backend API, DM, etc.). Returns the wrapped bytes and the tx receipt.
|
|
50
|
+
*/
|
|
51
|
+
assignWorker(taskId: TaskId, worker: Address, workerPubKey: string): Promise<AssignWorkerResult>;
|
|
52
|
+
cancelTask(taskId: TaskId): Promise<TxReceiptLike>;
|
|
53
|
+
/**
|
|
54
|
+
* Fetch evidence by root hash, unwrap the AES key with the agent's private
|
|
55
|
+
* key (signer's key material is not accessible, so a raw private key is
|
|
56
|
+
* required), and return the decrypted evidence plaintext.
|
|
57
|
+
*/
|
|
58
|
+
fetchAndDecryptEvidence(evidenceHash: Hex, agentPrivKey: string): Promise<Uint8Array>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { aesEncrypt, eciesEncrypt, generateAesKey, openEvidenceAsAgent, } from '../crypto/index.js';
|
|
2
|
+
import { LifecycleError } from '../errors/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* End-to-end agent flows. Composes storage + crypto + chain + keystore so a
|
|
5
|
+
* caller can post an encrypted bounty in one call. Key exchange with the
|
|
6
|
+
* worker is intentionally out-of-band: assignWorker() returns the wrapped
|
|
7
|
+
* AES key as bytes, and the caller is responsible for delivering it (backend
|
|
8
|
+
* API, DM, whatever). This keeps the SDK pluggable across different
|
|
9
|
+
* message-passing substrates.
|
|
10
|
+
*/
|
|
11
|
+
export class Agent {
|
|
12
|
+
deps;
|
|
13
|
+
constructor(deps) {
|
|
14
|
+
this.deps = deps;
|
|
15
|
+
}
|
|
16
|
+
async createTask(input) {
|
|
17
|
+
const { storage, escrow, keystore, events } = this.deps;
|
|
18
|
+
const aesKey = await generateAesKey();
|
|
19
|
+
const plaintext = toBytes(input.instructions);
|
|
20
|
+
const ciphertext = await aesEncrypt(plaintext, aesKey);
|
|
21
|
+
const uploaded = await storage.upload(ciphertext);
|
|
22
|
+
const rootHash = uploaded.rootHash;
|
|
23
|
+
const deadline = typeof input.deadline === 'bigint' ? input.deadline : BigInt(Math.floor(input.deadline.getTime() / 1000));
|
|
24
|
+
const { taskId, receipt } = await escrow.createTask({
|
|
25
|
+
taskHash: rootHash,
|
|
26
|
+
token: input.reward.token,
|
|
27
|
+
amount: input.reward.amount,
|
|
28
|
+
category: input.category,
|
|
29
|
+
locationZone: input.locationZone,
|
|
30
|
+
deadline,
|
|
31
|
+
});
|
|
32
|
+
const taskKey = { aesKey, createdAt: new Date() };
|
|
33
|
+
await keystore.putTaskKey(taskId, taskKey);
|
|
34
|
+
events?.emit('task.created', { taskId, txHash: receipt.hash, rootHash });
|
|
35
|
+
return { taskId, taskKey, rootHash, txHash: receipt.hash, receipt };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Wrap the stored AES key for the chosen worker and record the assignment
|
|
39
|
+
* on-chain. The caller must deliver `wrappedKey` to the worker separately
|
|
40
|
+
* (backend API, DM, etc.). Returns the wrapped bytes and the tx receipt.
|
|
41
|
+
*/
|
|
42
|
+
async assignWorker(taskId, worker, workerPubKey) {
|
|
43
|
+
const { keystore, escrow, events } = this.deps;
|
|
44
|
+
const stored = await keystore.getTaskKey(taskId);
|
|
45
|
+
if (!stored) {
|
|
46
|
+
throw new LifecycleError('LIFECYCLE/TASK_NOT_FOUND', `no task key in keystore for task ${taskId}`);
|
|
47
|
+
}
|
|
48
|
+
const wrappedKey = await eciesEncrypt(stored.aesKey, workerPubKey);
|
|
49
|
+
const receipt = await escrow.assignWorker(taskId, worker);
|
|
50
|
+
events?.emit('task.assigned', { taskId, worker, txHash: receipt.hash });
|
|
51
|
+
return { wrappedKey, receipt };
|
|
52
|
+
}
|
|
53
|
+
async cancelTask(taskId) {
|
|
54
|
+
const { escrow, keystore, events } = this.deps;
|
|
55
|
+
const receipt = await this.deps.escrow.cancelTask(taskId);
|
|
56
|
+
void escrow;
|
|
57
|
+
await keystore.delete(taskId);
|
|
58
|
+
events?.emit('task.cancelled', { taskId, txHash: receipt.hash });
|
|
59
|
+
return receipt;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fetch evidence by root hash, unwrap the AES key with the agent's private
|
|
63
|
+
* key (signer's key material is not accessible, so a raw private key is
|
|
64
|
+
* required), and return the decrypted evidence plaintext.
|
|
65
|
+
*/
|
|
66
|
+
async fetchAndDecryptEvidence(evidenceHash, agentPrivKey) {
|
|
67
|
+
const envelope = await this.deps.storage.download(evidenceHash);
|
|
68
|
+
return openEvidenceAsAgent(envelope, agentPrivKey);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function toBytes(x) {
|
|
72
|
+
return typeof x === 'string' ? new TextEncoder().encode(x) : x;
|
|
73
|
+
}
|