@agenc/sdk 1.0.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/README.md +193 -0
- package/dist/bin/agenc.js +394 -0
- package/dist/bin/agenc.mjs +248 -0
- package/dist/chunk-QRZGQS77.mjs +273 -0
- package/dist/index.js +620 -0
- package/dist/index.mjs +372 -0
- package/package.json +65 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEVNET_RPC,
|
|
3
|
+
MAINNET_RPC,
|
|
4
|
+
PRIVACY_CASH_PROGRAM_ID,
|
|
5
|
+
PROGRAM_ID,
|
|
6
|
+
TaskState,
|
|
7
|
+
VERIFIER_PROGRAM_ID,
|
|
8
|
+
claimTask,
|
|
9
|
+
completeTask,
|
|
10
|
+
completeTaskPrivate,
|
|
11
|
+
createTask,
|
|
12
|
+
generateProof,
|
|
13
|
+
getTask,
|
|
14
|
+
verifyProofLocally
|
|
15
|
+
} from "./chunk-QRZGQS77.mjs";
|
|
16
|
+
|
|
17
|
+
// src/client.ts
|
|
18
|
+
import { Connection as Connection2, LAMPORTS_PER_SOL as LAMPORTS_PER_SOL2 } from "@solana/web3.js";
|
|
19
|
+
import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
|
|
20
|
+
|
|
21
|
+
// src/privacy.ts
|
|
22
|
+
import { PublicKey, Transaction, LAMPORTS_PER_SOL } from "@solana/web3.js";
|
|
23
|
+
import * as fs from "fs";
|
|
24
|
+
import * as path from "path";
|
|
25
|
+
import { execSync } from "child_process";
|
|
26
|
+
var AgenCPrivacyClient = class {
|
|
27
|
+
connection;
|
|
28
|
+
program;
|
|
29
|
+
circuitPath;
|
|
30
|
+
privacyCash = null;
|
|
31
|
+
rpcUrl;
|
|
32
|
+
constructor(connection, program, circuitPath = "./circuits/task_completion", rpcUrl) {
|
|
33
|
+
this.connection = connection;
|
|
34
|
+
this.program = program;
|
|
35
|
+
this.circuitPath = circuitPath;
|
|
36
|
+
this.rpcUrl = rpcUrl || connection.rpcEndpoint;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Set Privacy Cash client instance
|
|
40
|
+
* Users should create their own Privacy Cash instance and pass it here
|
|
41
|
+
*/
|
|
42
|
+
setPrivacyCash(privacyCash) {
|
|
43
|
+
this.privacyCash = privacyCash;
|
|
44
|
+
console.log("Privacy Cash client set for:", privacyCash.publicKey.toBase58());
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Initialize Privacy Cash client for a specific wallet
|
|
48
|
+
* Requires privacycash package to be installed separately
|
|
49
|
+
*/
|
|
50
|
+
async initPrivacyCash(owner) {
|
|
51
|
+
try {
|
|
52
|
+
const { PrivacyCash } = await import("privacycash");
|
|
53
|
+
this.privacyCash = new PrivacyCash({
|
|
54
|
+
RPC_url: this.rpcUrl,
|
|
55
|
+
owner,
|
|
56
|
+
enableDebug: true
|
|
57
|
+
});
|
|
58
|
+
console.log("Privacy Cash client initialized for:", owner.publicKey.toBase58());
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.warn("Privacy Cash SDK not available. Install with: npm install privacycash");
|
|
61
|
+
console.warn("Or use setPrivacyCash() to provide your own instance.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if Privacy Cash is initialized
|
|
66
|
+
*/
|
|
67
|
+
hasPrivacyCash() {
|
|
68
|
+
return this.privacyCash !== null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Shield escrow funds into Privacy Cash pool
|
|
72
|
+
* Called by task creator when creating a private task
|
|
73
|
+
*/
|
|
74
|
+
async shieldEscrow(creator, lamports) {
|
|
75
|
+
if (!this.privacyCash) {
|
|
76
|
+
await this.initPrivacyCash(creator);
|
|
77
|
+
}
|
|
78
|
+
if (!this.privacyCash) {
|
|
79
|
+
throw new Error("Privacy Cash not available. Install privacycash or use setPrivacyCash().");
|
|
80
|
+
}
|
|
81
|
+
console.log(`Shielding ${lamports / LAMPORTS_PER_SOL} SOL into privacy pool...`);
|
|
82
|
+
const result = await this.privacyCash.deposit({ lamports });
|
|
83
|
+
console.log("Escrow shielded successfully");
|
|
84
|
+
return {
|
|
85
|
+
txSignature: result?.signature || result?.tx || "deposited",
|
|
86
|
+
shieldedAmount: lamports
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get shielded balance for current wallet
|
|
91
|
+
*/
|
|
92
|
+
async getShieldedBalance() {
|
|
93
|
+
if (!this.privacyCash) {
|
|
94
|
+
throw new Error("Privacy Cash not initialized. Call initPrivacyCash first.");
|
|
95
|
+
}
|
|
96
|
+
return await this.privacyCash.getPrivateBalance();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Complete a task privately using ZK proofs and Privacy Cash withdrawal
|
|
100
|
+
*
|
|
101
|
+
* Flow:
|
|
102
|
+
* 1. Generate ZK proof that worker completed task correctly (Noir/Sunspot)
|
|
103
|
+
* 2. Submit proof on-chain for verification
|
|
104
|
+
* 3. Upon verification, withdraw shielded escrow to worker via Privacy Cash
|
|
105
|
+
*/
|
|
106
|
+
async completeTaskPrivate(params, worker) {
|
|
107
|
+
const { taskId, output, salt, recipientWallet, escrowLamports } = params;
|
|
108
|
+
await this.initPrivacyCash(worker);
|
|
109
|
+
const task = await this.fetchTask(taskId);
|
|
110
|
+
const constraintHash = task.constraintHash;
|
|
111
|
+
const outputCommitment = await this.computeCommitment(output, salt);
|
|
112
|
+
console.log("Step 1/3: Generating ZK proof of task completion...");
|
|
113
|
+
const { zkProof, publicWitness } = await this.generateTaskCompletionProof({
|
|
114
|
+
taskId,
|
|
115
|
+
agentPubkey: worker.publicKey,
|
|
116
|
+
constraintHash,
|
|
117
|
+
outputCommitment,
|
|
118
|
+
output,
|
|
119
|
+
salt
|
|
120
|
+
});
|
|
121
|
+
console.log("ZK proof generated:", zkProof.length, "bytes");
|
|
122
|
+
console.log("Step 2/3: Submitting proof to on-chain verifier...");
|
|
123
|
+
const tx = await this.buildCompleteTaskPrivateTx({
|
|
124
|
+
taskId,
|
|
125
|
+
zkProof,
|
|
126
|
+
publicWitness,
|
|
127
|
+
worker: worker.publicKey
|
|
128
|
+
});
|
|
129
|
+
const proofTxSignature = await this.connection.sendTransaction(tx, [worker]);
|
|
130
|
+
await this.connection.confirmTransaction(proofTxSignature);
|
|
131
|
+
console.log("Proof verified on-chain:", proofTxSignature);
|
|
132
|
+
console.log("Step 3/3: Withdrawing shielded escrow via Privacy Cash...");
|
|
133
|
+
if (!this.privacyCash) {
|
|
134
|
+
throw new Error("Privacy Cash not initialized");
|
|
135
|
+
}
|
|
136
|
+
const withdrawResult = await this.privacyCash.withdraw({
|
|
137
|
+
lamports: escrowLamports,
|
|
138
|
+
recipientAddress: recipientWallet.toBase58()
|
|
139
|
+
});
|
|
140
|
+
console.log("Private payment completed!");
|
|
141
|
+
return {
|
|
142
|
+
proofTxSignature,
|
|
143
|
+
withdrawResult
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate ZK proof for task completion using Noir/Sunspot
|
|
148
|
+
*/
|
|
149
|
+
async generateTaskCompletionProof(params) {
|
|
150
|
+
const { taskId, agentPubkey, constraintHash, outputCommitment, output, salt } = params;
|
|
151
|
+
const proverToml = this.generateProverToml({
|
|
152
|
+
taskId,
|
|
153
|
+
agentPubkey: Array.from(agentPubkey.toBytes()),
|
|
154
|
+
constraintHash: "0x" + constraintHash.toString("hex"),
|
|
155
|
+
outputCommitment: "0x" + outputCommitment.toString(16),
|
|
156
|
+
output: output.map((o) => o.toString()),
|
|
157
|
+
salt: salt.toString()
|
|
158
|
+
});
|
|
159
|
+
const proverPath = path.join(this.circuitPath, "Prover.toml");
|
|
160
|
+
fs.writeFileSync(proverPath, proverToml);
|
|
161
|
+
execSync("nargo execute", { cwd: this.circuitPath });
|
|
162
|
+
execSync(
|
|
163
|
+
"sunspot prove target/task_completion.ccs target/task_completion.pk target/task_completion.gz -o target/task_completion.proof",
|
|
164
|
+
{ cwd: this.circuitPath }
|
|
165
|
+
);
|
|
166
|
+
const zkProof = fs.readFileSync(
|
|
167
|
+
path.join(this.circuitPath, "target/task_completion.proof")
|
|
168
|
+
);
|
|
169
|
+
const publicWitness = fs.readFileSync(
|
|
170
|
+
path.join(this.circuitPath, "target/task_completion.pw")
|
|
171
|
+
);
|
|
172
|
+
return { zkProof, publicWitness };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build the complete_task_private transaction
|
|
176
|
+
* This submits the ZK proof for on-chain verification
|
|
177
|
+
*/
|
|
178
|
+
async buildCompleteTaskPrivateTx(params) {
|
|
179
|
+
const { taskId, zkProof, publicWitness, worker } = params;
|
|
180
|
+
if (!this.program) {
|
|
181
|
+
throw new Error("Program not initialized");
|
|
182
|
+
}
|
|
183
|
+
const [taskPda] = PublicKey.findProgramAddressSync(
|
|
184
|
+
[Buffer.from("task"), Buffer.from(new Uint8Array(new BigUint64Array([BigInt(taskId)]).buffer))],
|
|
185
|
+
this.program.programId
|
|
186
|
+
);
|
|
187
|
+
const [claimPda] = PublicKey.findProgramAddressSync(
|
|
188
|
+
[Buffer.from("claim"), taskPda.toBuffer(), worker.toBuffer()],
|
|
189
|
+
this.program.programId
|
|
190
|
+
);
|
|
191
|
+
const verifierProgramId = await this.getVerifierProgramId();
|
|
192
|
+
const ix = await this.program.methods.completeTaskPrivate(taskId, {
|
|
193
|
+
zkProof: Array.from(zkProof),
|
|
194
|
+
publicWitness: Array.from(publicWitness)
|
|
195
|
+
}).accounts({
|
|
196
|
+
worker,
|
|
197
|
+
task: taskPda,
|
|
198
|
+
taskClaim: claimPda,
|
|
199
|
+
zkVerifier: verifierProgramId,
|
|
200
|
+
systemProgram: PublicKey.default
|
|
201
|
+
}).instruction();
|
|
202
|
+
const tx = new Transaction().add(ix);
|
|
203
|
+
tx.feePayer = worker;
|
|
204
|
+
tx.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
205
|
+
return tx;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Compute Poseidon commitment for output
|
|
209
|
+
*/
|
|
210
|
+
async computeCommitment(output, salt) {
|
|
211
|
+
console.log("Computing commitment...");
|
|
212
|
+
return BigInt(0);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Generate Prover.toml content
|
|
216
|
+
*/
|
|
217
|
+
generateProverToml(params) {
|
|
218
|
+
return `# Auto-generated Prover.toml
|
|
219
|
+
task_id = "${params.taskId}"
|
|
220
|
+
agent_pubkey = [${params.agentPubkey.join(", ")}]
|
|
221
|
+
constraint_hash = "${params.constraintHash}"
|
|
222
|
+
output_commitment = "${params.outputCommitment}"
|
|
223
|
+
output = [${params.output.map((o) => `"${o}"`).join(", ")}]
|
|
224
|
+
salt = "${params.salt}"
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
async fetchTask(taskId) {
|
|
228
|
+
if (!this.program) {
|
|
229
|
+
throw new Error("Program not initialized");
|
|
230
|
+
}
|
|
231
|
+
const [taskPda] = PublicKey.findProgramAddressSync(
|
|
232
|
+
[Buffer.from("task"), Buffer.from(new Uint8Array(new BigUint64Array([BigInt(taskId)]).buffer))],
|
|
233
|
+
this.program.programId
|
|
234
|
+
);
|
|
235
|
+
return await this.program.account.task.fetch(taskPda);
|
|
236
|
+
}
|
|
237
|
+
async getVerifierProgramId() {
|
|
238
|
+
return new PublicKey("8fHUGmjNzSh76r78v1rPt7BhWmAu2gXrvW9A2XXonwQQ");
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// src/client.ts
|
|
243
|
+
var PrivacyClient = class {
|
|
244
|
+
connection;
|
|
245
|
+
program = null;
|
|
246
|
+
privacyClient = null;
|
|
247
|
+
config;
|
|
248
|
+
wallet = null;
|
|
249
|
+
constructor(config = {}) {
|
|
250
|
+
this.config = {
|
|
251
|
+
devnet: false,
|
|
252
|
+
circuitPath: "./circuits/task_completion",
|
|
253
|
+
debug: false,
|
|
254
|
+
...config
|
|
255
|
+
};
|
|
256
|
+
const rpcUrl = config.rpcUrl || (this.config.devnet ? DEVNET_RPC : MAINNET_RPC);
|
|
257
|
+
this.connection = new Connection2(rpcUrl, "confirmed");
|
|
258
|
+
if (config.wallet) {
|
|
259
|
+
this.wallet = config.wallet;
|
|
260
|
+
}
|
|
261
|
+
if (this.config.debug) {
|
|
262
|
+
console.log("PrivacyClient initialized");
|
|
263
|
+
console.log(" RPC:", rpcUrl);
|
|
264
|
+
console.log(" Circuit:", this.config.circuitPath);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Initialize the client with a wallet
|
|
269
|
+
*/
|
|
270
|
+
async init(wallet) {
|
|
271
|
+
this.wallet = wallet;
|
|
272
|
+
const anchorWallet = new Wallet(wallet);
|
|
273
|
+
const provider = new AnchorProvider(
|
|
274
|
+
this.connection,
|
|
275
|
+
anchorWallet,
|
|
276
|
+
{ commitment: "confirmed" }
|
|
277
|
+
);
|
|
278
|
+
if (this.config.debug) {
|
|
279
|
+
console.log("Wallet initialized:", wallet.publicKey.toBase58());
|
|
280
|
+
}
|
|
281
|
+
this.privacyClient = new AgenCPrivacyClient(
|
|
282
|
+
this.connection,
|
|
283
|
+
this.program,
|
|
284
|
+
this.config.circuitPath,
|
|
285
|
+
this.connection.rpcEndpoint
|
|
286
|
+
);
|
|
287
|
+
await this.privacyClient.initPrivacyCash(wallet);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get connection instance
|
|
291
|
+
*/
|
|
292
|
+
getConnection() {
|
|
293
|
+
return this.connection;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get wallet public key
|
|
297
|
+
*/
|
|
298
|
+
getPublicKey() {
|
|
299
|
+
return this.wallet?.publicKey || null;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Shield SOL into the privacy pool
|
|
303
|
+
*/
|
|
304
|
+
async shield(lamports) {
|
|
305
|
+
if (!this.wallet || !this.privacyClient) {
|
|
306
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
307
|
+
}
|
|
308
|
+
const result = await this.privacyClient.shieldEscrow(this.wallet, lamports);
|
|
309
|
+
return {
|
|
310
|
+
txSignature: result.txSignature,
|
|
311
|
+
amount: result.shieldedAmount
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get shielded balance
|
|
316
|
+
*/
|
|
317
|
+
async getShieldedBalance() {
|
|
318
|
+
if (!this.privacyClient) {
|
|
319
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
320
|
+
}
|
|
321
|
+
const { lamports } = await this.privacyClient.getShieldedBalance();
|
|
322
|
+
return lamports;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Complete a task privately with ZK proof
|
|
326
|
+
*/
|
|
327
|
+
async completeTaskPrivate(params) {
|
|
328
|
+
if (!this.wallet || !this.privacyClient) {
|
|
329
|
+
throw new Error("Client not initialized. Call init() first.");
|
|
330
|
+
}
|
|
331
|
+
return await this.privacyClient.completeTaskPrivate(params, this.wallet);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Get the underlying AgenCPrivacyClient for advanced operations
|
|
335
|
+
*/
|
|
336
|
+
getPrivacyClient() {
|
|
337
|
+
return this.privacyClient;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Format lamports as SOL string
|
|
341
|
+
*/
|
|
342
|
+
static formatSol(lamports) {
|
|
343
|
+
return (lamports / LAMPORTS_PER_SOL2).toFixed(9) + " SOL";
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Parse SOL string to lamports
|
|
347
|
+
*/
|
|
348
|
+
static parseSol(sol) {
|
|
349
|
+
const value = typeof sol === "string" ? parseFloat(sol) : sol;
|
|
350
|
+
return Math.floor(value * LAMPORTS_PER_SOL2);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// src/index.ts
|
|
355
|
+
var VERSION = "1.0.0";
|
|
356
|
+
export {
|
|
357
|
+
DEVNET_RPC,
|
|
358
|
+
MAINNET_RPC,
|
|
359
|
+
PRIVACY_CASH_PROGRAM_ID,
|
|
360
|
+
PROGRAM_ID,
|
|
361
|
+
PrivacyClient,
|
|
362
|
+
TaskState,
|
|
363
|
+
VERIFIER_PROGRAM_ID,
|
|
364
|
+
VERSION,
|
|
365
|
+
claimTask,
|
|
366
|
+
completeTask,
|
|
367
|
+
completeTaskPrivate,
|
|
368
|
+
createTask,
|
|
369
|
+
generateProof,
|
|
370
|
+
getTask,
|
|
371
|
+
verifyProofLocally
|
|
372
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agenc/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript SDK for AgenC - Privacy-preserving agent coordination on Solana",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"agenc": "./dist/bin/agenc.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup src/index.ts src/bin/agenc.ts --format cjs,esm --clean --external privacycash",
|
|
22
|
+
"prepublishOnly": "npm run build",
|
|
23
|
+
"typecheck": "tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"solana",
|
|
27
|
+
"privacy",
|
|
28
|
+
"zk",
|
|
29
|
+
"zero-knowledge",
|
|
30
|
+
"noir",
|
|
31
|
+
"agents",
|
|
32
|
+
"coordination",
|
|
33
|
+
"escrow",
|
|
34
|
+
"privacy-cash"
|
|
35
|
+
],
|
|
36
|
+
"author": "Tetsuo AI",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/tetsuo-ai/AgenC"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/tetsuo-ai/AgenC#readme",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/tetsuo-ai/AgenC/issues"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@coral-xyz/anchor": "^0.30.1",
|
|
48
|
+
"@solana/web3.js": "^1.95.0",
|
|
49
|
+
"chalk": "^5.3.0",
|
|
50
|
+
"commander": "^12.0.0",
|
|
51
|
+
"ora": "^8.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"tsup": "^8.0.0",
|
|
56
|
+
"typescript": "^5.0.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@coral-xyz/anchor": ">=0.29.0",
|
|
60
|
+
"@solana/web3.js": ">=1.90.0"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|