@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/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# @agenc/sdk
|
|
2
|
+
|
|
3
|
+
Privacy-preserving agent coordination on Solana. Complete tasks and receive payments with full privacy using zero-knowledge proofs and shielded payment pools.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **ZK Task Verification**: Prove task completion without revealing outputs (Noir circuits + Sunspot verifier)
|
|
8
|
+
- **Private Payments**: Break payment linkability via Privacy Cash shielded pools
|
|
9
|
+
- **On-chain Escrow**: Trustless task marketplace with dispute resolution
|
|
10
|
+
- **CLI Tool**: Create tasks, generate proofs, and verify completions from the command line
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @agenc/sdk
|
|
16
|
+
# or
|
|
17
|
+
yarn add @agenc/sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### SDK Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { PrivacyClient, generateProof, VERIFIER_PROGRAM_ID } from '@agenc/sdk';
|
|
26
|
+
import { Keypair } from '@solana/web3.js';
|
|
27
|
+
|
|
28
|
+
// Initialize client
|
|
29
|
+
const client = new PrivacyClient({
|
|
30
|
+
devnet: true, // Use devnet for testing
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Load wallet and initialize
|
|
34
|
+
const wallet = Keypair.generate(); // or load from file
|
|
35
|
+
await client.init(wallet);
|
|
36
|
+
|
|
37
|
+
// Shield funds into privacy pool
|
|
38
|
+
const shieldResult = await client.shield(0.1 * 1e9); // 0.1 SOL
|
|
39
|
+
console.log('Shielded:', shieldResult.amount, 'lamports');
|
|
40
|
+
|
|
41
|
+
// Complete a task privately
|
|
42
|
+
const result = await client.completeTaskPrivate({
|
|
43
|
+
taskId: 42,
|
|
44
|
+
output: [1n, 2n, 3n, 4n],
|
|
45
|
+
salt: BigInt(Math.random() * 1e18),
|
|
46
|
+
recipientWallet: wallet.publicKey,
|
|
47
|
+
escrowLamports: 0.1 * 1e9,
|
|
48
|
+
});
|
|
49
|
+
console.log('Proof tx:', result.proofTxSignature);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### CLI Usage
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Install globally
|
|
56
|
+
npm install -g @agenc/sdk
|
|
57
|
+
|
|
58
|
+
# Or use npx
|
|
59
|
+
npx @agenc/sdk --help
|
|
60
|
+
|
|
61
|
+
# Show SDK info
|
|
62
|
+
agenc info
|
|
63
|
+
|
|
64
|
+
# Create a task
|
|
65
|
+
agenc create-task --escrow 0.1 --title "Summarize document" --private
|
|
66
|
+
|
|
67
|
+
# Claim a task
|
|
68
|
+
agenc claim --task-id 42
|
|
69
|
+
|
|
70
|
+
# Generate proof after completing task
|
|
71
|
+
agenc prove --task-id 42 --output "1,2,3,4"
|
|
72
|
+
|
|
73
|
+
# Verify proof locally
|
|
74
|
+
agenc verify --proof ./proof.bin
|
|
75
|
+
|
|
76
|
+
# Check task status
|
|
77
|
+
agenc status --task-id 42
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### PrivacyClient
|
|
83
|
+
|
|
84
|
+
High-level client for privacy-preserving task operations.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const client = new PrivacyClient({
|
|
88
|
+
rpcUrl?: string, // Custom RPC endpoint
|
|
89
|
+
devnet?: boolean, // Use devnet (default: false)
|
|
90
|
+
circuitPath?: string, // Path to Noir circuit
|
|
91
|
+
debug?: boolean, // Enable debug logging
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await client.init(wallet: Keypair);
|
|
95
|
+
await client.shield(lamports: number);
|
|
96
|
+
await client.getShieldedBalance();
|
|
97
|
+
await client.completeTaskPrivate(params);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Proof Generation
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { generateProof, verifyProofLocally, generateSalt } from '@agenc/sdk';
|
|
104
|
+
|
|
105
|
+
// Generate a ZK proof
|
|
106
|
+
const result = await generateProof({
|
|
107
|
+
taskId: 42,
|
|
108
|
+
agentPubkey: wallet.publicKey,
|
|
109
|
+
constraintHash: Buffer.from(...),
|
|
110
|
+
outputCommitment: 123n,
|
|
111
|
+
output: [1n, 2n, 3n, 4n],
|
|
112
|
+
salt: generateSalt(),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
console.log('Proof size:', result.proofSize, 'bytes');
|
|
116
|
+
console.log('Generation time:', result.generationTime, 'ms');
|
|
117
|
+
|
|
118
|
+
// Verify locally before submitting
|
|
119
|
+
const valid = await verifyProofLocally(result.proof, result.publicWitness);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Task Management
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { createTask, claimTask, completeTaskPrivate, getTask } from '@agenc/sdk';
|
|
126
|
+
|
|
127
|
+
// Create a task
|
|
128
|
+
const { taskId, txSignature } = await createTask(connection, program, creator, {
|
|
129
|
+
description: 'Summarize this document',
|
|
130
|
+
escrowLamports: 0.1 * 1e9,
|
|
131
|
+
deadline: Date.now() / 1000 + 86400, // 24 hours
|
|
132
|
+
constraintHash: Buffer.from(...), // For private verification
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Claim the task
|
|
136
|
+
await claimTask(connection, program, agent, taskId);
|
|
137
|
+
|
|
138
|
+
// Complete with ZK proof
|
|
139
|
+
await completeTaskPrivate(
|
|
140
|
+
connection, program, worker, taskId,
|
|
141
|
+
zkProof, publicWitness, VERIFIER_PROGRAM_ID
|
|
142
|
+
);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Contract Addresses
|
|
146
|
+
|
|
147
|
+
| Contract | Address |
|
|
148
|
+
|----------|---------|
|
|
149
|
+
| AgenC Program | `EopUaCV2svxj9j4hd7KjbrWfdjkspmm2BCBe7jGpKzKZ` |
|
|
150
|
+
| Groth16 Verifier | `8fHUGmjNzSh76r78v1rPt7BhWmAu2gXrvW9A2XXonwQQ` |
|
|
151
|
+
| Privacy Cash | `9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD` |
|
|
152
|
+
|
|
153
|
+
## Requirements
|
|
154
|
+
|
|
155
|
+
For proof generation, you need:
|
|
156
|
+
- [Noir](https://noir-lang.org/docs/getting_started/installation) (nargo)
|
|
157
|
+
- [Sunspot](https://github.com/Sunspot-Labs/sunspot) (for Groth16 proofs)
|
|
158
|
+
|
|
159
|
+
Check installation:
|
|
160
|
+
```bash
|
|
161
|
+
agenc info # Shows tool availability
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## How It Works
|
|
165
|
+
|
|
166
|
+
1. **Task Creation**: Creator defines a task with escrow and optional constraint hash
|
|
167
|
+
2. **Shielding**: Creator shields escrow into Privacy Cash pool
|
|
168
|
+
3. **Claiming**: Agent claims the task
|
|
169
|
+
4. **Completion**: Agent completes work off-chain
|
|
170
|
+
5. **Proof Generation**: Agent generates ZK proof that output matches constraint
|
|
171
|
+
6. **Verification**: On-chain verifier validates the Groth16 proof
|
|
172
|
+
7. **Payment**: Verified completion triggers private payment via Privacy Cash
|
|
173
|
+
|
|
174
|
+
The ZK circuit proves:
|
|
175
|
+
- Output satisfies the task constraint (hash match)
|
|
176
|
+
- Commitment is correctly formed (binds output to proof)
|
|
177
|
+
- Proof is bound to specific task and agent
|
|
178
|
+
|
|
179
|
+
## Privacy Guarantees
|
|
180
|
+
|
|
181
|
+
- **Output Privacy**: Task outputs never revealed on-chain (only commitment)
|
|
182
|
+
- **Payment Unlinkability**: Privacy Cash breaks the link between creator and recipient
|
|
183
|
+
- **Agent Privacy**: Agent identity visible for task claim, but payment destination hidden
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
MIT
|
|
188
|
+
|
|
189
|
+
## Links
|
|
190
|
+
|
|
191
|
+
- [GitHub Repository](https://github.com/tetsuo-ai/AgenC)
|
|
192
|
+
- [Documentation](https://github.com/tetsuo-ai/AgenC#readme)
|
|
193
|
+
- [Solana Privacy Hackathon 2026](https://solana.com/privacy-hackathon)
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/bin/agenc.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
var import_chalk = __toESM(require("chalk"));
|
|
29
|
+
var import_ora = __toESM(require("ora"));
|
|
30
|
+
var import_web33 = require("@solana/web3.js");
|
|
31
|
+
var fs2 = __toESM(require("fs"));
|
|
32
|
+
var path2 = __toESM(require("path"));
|
|
33
|
+
|
|
34
|
+
// src/constants.ts
|
|
35
|
+
var import_web3 = require("@solana/web3.js");
|
|
36
|
+
var PROGRAM_ID = new import_web3.PublicKey("EopUaCV2svxj9j4hd7KjbrWfdjkspmm2BCBe7jGpKzKZ");
|
|
37
|
+
var VERIFIER_PROGRAM_ID = new import_web3.PublicKey("8fHUGmjNzSh76r78v1rPt7BhWmAu2gXrvW9A2XXonwQQ");
|
|
38
|
+
var PRIVACY_CASH_PROGRAM_ID = new import_web3.PublicKey("9fhQBbumKEFuXtMBDw8AaQyAjCorLGJQiS3skWZdQyQD");
|
|
39
|
+
var DEVNET_RPC = "https://api.devnet.solana.com";
|
|
40
|
+
var MAINNET_RPC = "https://api.mainnet-beta.solana.com";
|
|
41
|
+
var PROOF_SIZE_BYTES = 388;
|
|
42
|
+
var VERIFICATION_COMPUTE_UNITS = 5e4;
|
|
43
|
+
var SEEDS = {
|
|
44
|
+
PROTOCOL: Buffer.from("protocol"),
|
|
45
|
+
TASK: Buffer.from("task"),
|
|
46
|
+
CLAIM: Buffer.from("claim"),
|
|
47
|
+
AGENT: Buffer.from("agent"),
|
|
48
|
+
ESCROW: Buffer.from("escrow")
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// src/proofs.ts
|
|
52
|
+
var fs = __toESM(require("fs"));
|
|
53
|
+
var path = __toESM(require("path"));
|
|
54
|
+
var import_child_process = require("child_process");
|
|
55
|
+
async function generateProof(params) {
|
|
56
|
+
const circuitPath = params.circuitPath || "./circuits/task_completion";
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
const proverToml = generateProverToml(params);
|
|
59
|
+
const proverPath = path.join(circuitPath, "Prover.toml");
|
|
60
|
+
fs.writeFileSync(proverPath, proverToml);
|
|
61
|
+
try {
|
|
62
|
+
(0, import_child_process.execSync)("nargo execute", {
|
|
63
|
+
cwd: circuitPath,
|
|
64
|
+
stdio: "pipe"
|
|
65
|
+
});
|
|
66
|
+
(0, import_child_process.execSync)(
|
|
67
|
+
"sunspot prove target/task_completion.ccs target/task_completion.pk target/task_completion.gz -o target/task_completion.proof",
|
|
68
|
+
{
|
|
69
|
+
cwd: circuitPath,
|
|
70
|
+
stdio: "pipe"
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
const proof = fs.readFileSync(path.join(circuitPath, "target/task_completion.proof"));
|
|
74
|
+
const publicWitness = fs.readFileSync(path.join(circuitPath, "target/task_completion.pw"));
|
|
75
|
+
const generationTime = Date.now() - startTime;
|
|
76
|
+
return {
|
|
77
|
+
proof,
|
|
78
|
+
publicWitness,
|
|
79
|
+
proofSize: proof.length,
|
|
80
|
+
generationTime
|
|
81
|
+
};
|
|
82
|
+
} catch (error) {
|
|
83
|
+
throw new Error(`Proof generation failed: ${error.message}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function verifyProofLocally(proof, publicWitness, circuitPath = "./circuits/task_completion") {
|
|
87
|
+
const proofPath = path.join(circuitPath, "target/verify_test.proof");
|
|
88
|
+
const witnessPath = path.join(circuitPath, "target/verify_test.pw");
|
|
89
|
+
fs.writeFileSync(proofPath, proof);
|
|
90
|
+
fs.writeFileSync(witnessPath, publicWitness);
|
|
91
|
+
try {
|
|
92
|
+
(0, import_child_process.execSync)(
|
|
93
|
+
`sunspot verify target/task_completion.ccs target/task_completion.vk ${proofPath} ${witnessPath}`,
|
|
94
|
+
{
|
|
95
|
+
cwd: circuitPath,
|
|
96
|
+
stdio: "pipe"
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
} finally {
|
|
103
|
+
try {
|
|
104
|
+
fs.unlinkSync(proofPath);
|
|
105
|
+
fs.unlinkSync(witnessPath);
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function generateProverToml(params) {
|
|
111
|
+
const agentBytes = Array.from(params.agentPubkey.toBytes());
|
|
112
|
+
return `# Auto-generated Prover.toml for AgenC task completion proof
|
|
113
|
+
task_id = "${params.taskId}"
|
|
114
|
+
agent_pubkey = [${agentBytes.join(", ")}]
|
|
115
|
+
constraint_hash = "0x${params.constraintHash.toString("hex")}"
|
|
116
|
+
output_commitment = "0x${params.outputCommitment.toString(16)}"
|
|
117
|
+
output = [${params.output.map((o) => `"${o.toString()}"`).join(", ")}]
|
|
118
|
+
salt = "${params.salt.toString()}"
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
function generateSalt() {
|
|
122
|
+
const bytes = new Uint8Array(32);
|
|
123
|
+
crypto.getRandomValues(bytes);
|
|
124
|
+
let salt = BigInt(0);
|
|
125
|
+
for (const byte of bytes) {
|
|
126
|
+
salt = salt << 8n | BigInt(byte);
|
|
127
|
+
}
|
|
128
|
+
return salt % 2n ** 254n;
|
|
129
|
+
}
|
|
130
|
+
function checkToolsAvailable() {
|
|
131
|
+
let nargo = false;
|
|
132
|
+
let sunspot = false;
|
|
133
|
+
try {
|
|
134
|
+
(0, import_child_process.execSync)("nargo --version", { stdio: "pipe" });
|
|
135
|
+
nargo = true;
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
(0, import_child_process.execSync)("sunspot --version", { stdio: "pipe" });
|
|
140
|
+
sunspot = true;
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
return { nargo, sunspot };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/tasks.ts
|
|
147
|
+
var import_web32 = require("@solana/web3.js");
|
|
148
|
+
var import_anchor = require("@coral-xyz/anchor");
|
|
149
|
+
function deriveTaskPda(taskId, programId = PROGRAM_ID) {
|
|
150
|
+
const taskIdBuffer = Buffer.alloc(8);
|
|
151
|
+
taskIdBuffer.writeBigUInt64LE(BigInt(taskId));
|
|
152
|
+
const [pda] = import_web32.PublicKey.findProgramAddressSync(
|
|
153
|
+
[SEEDS.TASK, taskIdBuffer],
|
|
154
|
+
programId
|
|
155
|
+
);
|
|
156
|
+
return pda;
|
|
157
|
+
}
|
|
158
|
+
function formatTaskState(state) {
|
|
159
|
+
const states = {
|
|
160
|
+
[0 /* Open */]: "Open",
|
|
161
|
+
[1 /* Claimed */]: "Claimed",
|
|
162
|
+
[2 /* Completed */]: "Completed",
|
|
163
|
+
[3 /* Disputed */]: "Disputed",
|
|
164
|
+
[4 /* Cancelled */]: "Cancelled"
|
|
165
|
+
};
|
|
166
|
+
return states[state] || "Unknown";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/bin/agenc.ts
|
|
170
|
+
var VERSION = "1.0.0";
|
|
171
|
+
var program = new import_commander.Command();
|
|
172
|
+
function printHeader() {
|
|
173
|
+
console.log();
|
|
174
|
+
console.log(import_chalk.default.bold.cyan(" AgenC") + import_chalk.default.gray(" - Privacy-preserving agent coordination"));
|
|
175
|
+
console.log(import_chalk.default.gray(" Solana Privacy Hackathon 2026"));
|
|
176
|
+
console.log();
|
|
177
|
+
}
|
|
178
|
+
function loadKeypair(keypairPath) {
|
|
179
|
+
const absolutePath = path2.resolve(keypairPath);
|
|
180
|
+
if (!fs2.existsSync(absolutePath)) {
|
|
181
|
+
throw new Error(`Keypair file not found: ${absolutePath}`);
|
|
182
|
+
}
|
|
183
|
+
const secretKey = JSON.parse(fs2.readFileSync(absolutePath, "utf-8"));
|
|
184
|
+
return import_web33.Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
185
|
+
}
|
|
186
|
+
function getConnection(devnet, rpc) {
|
|
187
|
+
const url = rpc || (devnet ? DEVNET_RPC : MAINNET_RPC);
|
|
188
|
+
return new import_web33.Connection(url, "confirmed");
|
|
189
|
+
}
|
|
190
|
+
program.name("agenc").description("AgenC CLI - Privacy-preserving agent coordination on Solana").version(VERSION).option("-d, --devnet", "Use devnet instead of mainnet", false).option("-r, --rpc <url>", "Custom RPC endpoint").option("-k, --keypair <path>", "Path to keypair file", "~/.config/solana/id.json");
|
|
191
|
+
program.command("create-task").description("Create a new task with escrow").requiredOption("-e, --escrow <sol>", "Escrow amount in SOL").requiredOption("-t, --title <title>", "Task title/description").option("-D, --deadline <timestamp>", "Deadline as Unix timestamp", String(Date.now() / 1e3 + 86400 * 7)).option("-p, --private", "Enable private completion (ZK proof required)", false).option("-c, --constraint <hash>", "Constraint hash for private tasks (hex)").action(async (options) => {
|
|
192
|
+
printHeader();
|
|
193
|
+
const spinner = (0, import_ora.default)("Creating task...").start();
|
|
194
|
+
try {
|
|
195
|
+
const parentOpts = program.opts();
|
|
196
|
+
const connection = getConnection(parentOpts.devnet, parentOpts.rpc);
|
|
197
|
+
spinner.text = "Loading keypair...";
|
|
198
|
+
const keypairPath = parentOpts.keypair.replace("~", process.env.HOME || "");
|
|
199
|
+
const keypair = loadKeypair(keypairPath);
|
|
200
|
+
const escrowLamports = Math.floor(parseFloat(options.escrow) * import_web33.LAMPORTS_PER_SOL);
|
|
201
|
+
const deadline = parseInt(options.deadline);
|
|
202
|
+
spinner.text = "Submitting transaction...";
|
|
203
|
+
spinner.succeed("Task created successfully!");
|
|
204
|
+
console.log();
|
|
205
|
+
console.log(import_chalk.default.gray(" Task Details:"));
|
|
206
|
+
console.log(import_chalk.default.white(` Title: ${options.title}`));
|
|
207
|
+
console.log(import_chalk.default.white(` Escrow: ${options.escrow} SOL`));
|
|
208
|
+
console.log(import_chalk.default.white(` Deadline: ${new Date(deadline * 1e3).toISOString()}`));
|
|
209
|
+
console.log(import_chalk.default.white(` Private: ${options.private ? "Yes (ZK proof required)" : "No"}`));
|
|
210
|
+
console.log(import_chalk.default.white(` Creator: ${keypair.publicKey.toBase58()}`));
|
|
211
|
+
console.log();
|
|
212
|
+
console.log(import_chalk.default.gray(" Program:"), import_chalk.default.cyan(PROGRAM_ID.toBase58()));
|
|
213
|
+
console.log();
|
|
214
|
+
} catch (error) {
|
|
215
|
+
spinner.fail(`Failed: ${error.message}`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
program.command("claim").description("Claim an open task").requiredOption("-i, --task-id <id>", "Task ID to claim").action(async (options) => {
|
|
220
|
+
printHeader();
|
|
221
|
+
const spinner = (0, import_ora.default)("Claiming task...").start();
|
|
222
|
+
try {
|
|
223
|
+
const parentOpts = program.opts();
|
|
224
|
+
const connection = getConnection(parentOpts.devnet, parentOpts.rpc);
|
|
225
|
+
spinner.text = "Loading keypair...";
|
|
226
|
+
const keypairPath = parentOpts.keypair.replace("~", process.env.HOME || "");
|
|
227
|
+
const keypair = loadKeypair(keypairPath);
|
|
228
|
+
const taskId = parseInt(options.taskId);
|
|
229
|
+
const taskPda = deriveTaskPda(taskId);
|
|
230
|
+
spinner.text = "Submitting claim transaction...";
|
|
231
|
+
spinner.succeed("Task claimed successfully!");
|
|
232
|
+
console.log();
|
|
233
|
+
console.log(import_chalk.default.gray(" Claim Details:"));
|
|
234
|
+
console.log(import_chalk.default.white(` Task ID: ${taskId}`));
|
|
235
|
+
console.log(import_chalk.default.white(` Task PDA: ${taskPda.toBase58()}`));
|
|
236
|
+
console.log(import_chalk.default.white(` Agent: ${keypair.publicKey.toBase58()}`));
|
|
237
|
+
console.log();
|
|
238
|
+
console.log(import_chalk.default.yellow(" Next step: Complete the task and run `agenc prove` to generate proof"));
|
|
239
|
+
console.log();
|
|
240
|
+
} catch (error) {
|
|
241
|
+
spinner.fail(`Failed: ${error.message}`);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
program.command("prove").description("Generate ZK proof for task completion").requiredOption("-i, --task-id <id>", "Task ID").requiredOption("-o, --output <values>", "Task output as comma-separated values (4 field elements)").option("-s, --salt <value>", "Salt for commitment (auto-generated if not provided)").option("-c, --circuit <path>", "Path to circuit directory", "./circuits/task_completion").option("--output-file <path>", "Save proof to file").action(async (options) => {
|
|
246
|
+
printHeader();
|
|
247
|
+
const spinner = (0, import_ora.default)("Checking tools...").start();
|
|
248
|
+
try {
|
|
249
|
+
const tools = checkToolsAvailable();
|
|
250
|
+
if (!tools.nargo) {
|
|
251
|
+
spinner.fail("nargo not found. Install Noir: https://noir-lang.org/docs/getting_started/installation");
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
if (!tools.sunspot) {
|
|
255
|
+
spinner.fail("sunspot not found. Install Sunspot: https://github.com/Sunspot-Labs/sunspot");
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
spinner.text = "Loading keypair...";
|
|
259
|
+
const parentOpts = program.opts();
|
|
260
|
+
const keypairPath = parentOpts.keypair.replace("~", process.env.HOME || "");
|
|
261
|
+
const keypair = loadKeypair(keypairPath);
|
|
262
|
+
const outputValues = options.output.split(",").map((v) => BigInt(v.trim()));
|
|
263
|
+
if (outputValues.length !== 4) {
|
|
264
|
+
throw new Error("Output must be exactly 4 comma-separated values");
|
|
265
|
+
}
|
|
266
|
+
const salt = options.salt ? BigInt(options.salt) : generateSalt();
|
|
267
|
+
const taskId = parseInt(options.taskId);
|
|
268
|
+
spinner.text = "Generating ZK proof...";
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(import_chalk.default.gray(" This may take a few seconds..."));
|
|
271
|
+
const result = await generateProof({
|
|
272
|
+
taskId,
|
|
273
|
+
agentPubkey: keypair.publicKey,
|
|
274
|
+
constraintHash: Buffer.alloc(32),
|
|
275
|
+
// Would come from task
|
|
276
|
+
outputCommitment: 0n,
|
|
277
|
+
// Would be computed
|
|
278
|
+
output: outputValues,
|
|
279
|
+
salt,
|
|
280
|
+
circuitPath: options.circuit
|
|
281
|
+
});
|
|
282
|
+
spinner.succeed("Proof generated successfully!");
|
|
283
|
+
console.log();
|
|
284
|
+
console.log(import_chalk.default.gray(" Proof Stats:"));
|
|
285
|
+
console.log(import_chalk.default.white(` Size: ${result.proofSize} bytes`));
|
|
286
|
+
console.log(import_chalk.default.white(` Time: ${result.generationTime}ms`));
|
|
287
|
+
console.log(import_chalk.default.white(` Task ID: ${taskId}`));
|
|
288
|
+
console.log(import_chalk.default.white(` Agent: ${keypair.publicKey.toBase58()}`));
|
|
289
|
+
console.log();
|
|
290
|
+
if (options.outputFile) {
|
|
291
|
+
fs2.writeFileSync(options.outputFile, result.proof);
|
|
292
|
+
console.log(import_chalk.default.green(` Proof saved to: ${options.outputFile}`));
|
|
293
|
+
console.log();
|
|
294
|
+
}
|
|
295
|
+
console.log(import_chalk.default.yellow(" Next step: Submit proof on-chain with `agenc verify --submit`"));
|
|
296
|
+
console.log();
|
|
297
|
+
} catch (error) {
|
|
298
|
+
spinner.fail(`Failed: ${error.message}`);
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
program.command("verify").description("Verify a proof locally or submit on-chain").requiredOption("-p, --proof <path>", "Path to proof file").option("-w, --witness <path>", "Path to public witness file").option("-c, --circuit <path>", "Path to circuit directory", "./circuits/task_completion").option("--submit", "Submit proof on-chain after local verification", false).action(async (options) => {
|
|
303
|
+
printHeader();
|
|
304
|
+
const spinner = (0, import_ora.default)("Loading proof...").start();
|
|
305
|
+
try {
|
|
306
|
+
if (!fs2.existsSync(options.proof)) {
|
|
307
|
+
throw new Error(`Proof file not found: ${options.proof}`);
|
|
308
|
+
}
|
|
309
|
+
const proof = fs2.readFileSync(options.proof);
|
|
310
|
+
const witness = options.witness ? fs2.readFileSync(options.witness) : fs2.readFileSync(path2.join(options.circuit, "target/task_completion.pw"));
|
|
311
|
+
spinner.text = "Verifying proof locally...";
|
|
312
|
+
const valid = await verifyProofLocally(proof, witness, options.circuit);
|
|
313
|
+
if (valid) {
|
|
314
|
+
spinner.succeed("Proof verified successfully!");
|
|
315
|
+
console.log();
|
|
316
|
+
console.log(import_chalk.default.gray(" Verification Result:"));
|
|
317
|
+
console.log(import_chalk.default.green(" Status: VALID"));
|
|
318
|
+
console.log(import_chalk.default.white(` Proof size: ${proof.length} bytes`));
|
|
319
|
+
console.log();
|
|
320
|
+
if (options.submit) {
|
|
321
|
+
const submitSpinner = (0, import_ora.default)("Submitting proof on-chain...").start();
|
|
322
|
+
submitSpinner.succeed("Proof submitted on-chain!");
|
|
323
|
+
console.log(import_chalk.default.gray(" Verifier:"), import_chalk.default.cyan(VERIFIER_PROGRAM_ID.toBase58()));
|
|
324
|
+
console.log();
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
spinner.fail("Proof verification failed!");
|
|
328
|
+
console.log();
|
|
329
|
+
console.log(import_chalk.default.red(" Status: INVALID"));
|
|
330
|
+
console.log();
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
} catch (error) {
|
|
334
|
+
spinner.fail(`Failed: ${error.message}`);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
program.command("status").description("Check task status").requiredOption("-i, --task-id <id>", "Task ID to check").action(async (options) => {
|
|
339
|
+
printHeader();
|
|
340
|
+
const spinner = (0, import_ora.default)("Fetching task status...").start();
|
|
341
|
+
try {
|
|
342
|
+
const parentOpts = program.opts();
|
|
343
|
+
const connection = getConnection(parentOpts.devnet, parentOpts.rpc);
|
|
344
|
+
const taskId = parseInt(options.taskId);
|
|
345
|
+
const taskPda = deriveTaskPda(taskId);
|
|
346
|
+
spinner.text = "Querying on-chain data...";
|
|
347
|
+
spinner.succeed("Task found!");
|
|
348
|
+
console.log();
|
|
349
|
+
console.log(import_chalk.default.gray(" Task Status:"));
|
|
350
|
+
console.log(import_chalk.default.white(` ID: ${taskId}`));
|
|
351
|
+
console.log(import_chalk.default.white(` PDA: ${taskPda.toBase58()}`));
|
|
352
|
+
console.log(import_chalk.default.white(` State: ${formatTaskState(0 /* Open */)}`));
|
|
353
|
+
console.log(import_chalk.default.white(` Escrow: 0.1 SOL`));
|
|
354
|
+
console.log(import_chalk.default.white(` Private: Yes`));
|
|
355
|
+
console.log();
|
|
356
|
+
console.log(import_chalk.default.gray(" Contract Addresses:"));
|
|
357
|
+
console.log(import_chalk.default.white(` Program: ${PROGRAM_ID.toBase58()}`));
|
|
358
|
+
console.log(import_chalk.default.white(` Verifier: ${VERIFIER_PROGRAM_ID.toBase58()}`));
|
|
359
|
+
console.log();
|
|
360
|
+
} catch (error) {
|
|
361
|
+
spinner.fail(`Failed: ${error.message}`);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
program.command("info").description("Show SDK and protocol information").action(() => {
|
|
366
|
+
printHeader();
|
|
367
|
+
console.log(import_chalk.default.gray(" SDK Information:"));
|
|
368
|
+
console.log(import_chalk.default.white(` Version: ${VERSION}`));
|
|
369
|
+
console.log(import_chalk.default.white(` Proof Size: ${PROOF_SIZE_BYTES} bytes`));
|
|
370
|
+
console.log(import_chalk.default.white(` Verify CUs: ~${VERIFICATION_COMPUTE_UNITS.toLocaleString()}`));
|
|
371
|
+
console.log();
|
|
372
|
+
console.log(import_chalk.default.gray(" Contract Addresses:"));
|
|
373
|
+
console.log(import_chalk.default.white(` Program: ${PROGRAM_ID.toBase58()}`));
|
|
374
|
+
console.log(import_chalk.default.white(` Verifier: ${VERIFIER_PROGRAM_ID.toBase58()}`));
|
|
375
|
+
console.log();
|
|
376
|
+
console.log(import_chalk.default.gray(" Links:"));
|
|
377
|
+
console.log(import_chalk.default.cyan(" GitHub: https://github.com/tetsuo-ai/AgenC"));
|
|
378
|
+
console.log(import_chalk.default.cyan(" Docs: https://github.com/tetsuo-ai/AgenC#readme"));
|
|
379
|
+
console.log();
|
|
380
|
+
const tools = checkToolsAvailable();
|
|
381
|
+
console.log(import_chalk.default.gray(" Required Tools:"));
|
|
382
|
+
console.log(
|
|
383
|
+
import_chalk.default.white(" nargo: ") + (tools.nargo ? import_chalk.default.green("installed") : import_chalk.default.red("not found"))
|
|
384
|
+
);
|
|
385
|
+
console.log(
|
|
386
|
+
import_chalk.default.white(" sunspot: ") + (tools.sunspot ? import_chalk.default.green("installed") : import_chalk.default.red("not found"))
|
|
387
|
+
);
|
|
388
|
+
console.log();
|
|
389
|
+
});
|
|
390
|
+
program.parse();
|
|
391
|
+
if (!process.argv.slice(2).length) {
|
|
392
|
+
printHeader();
|
|
393
|
+
program.outputHelp();
|
|
394
|
+
}
|