@dymchenko/en-sdk 0.1.1 → 0.1.2

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/SKILL.md CHANGED
@@ -31,88 +31,97 @@ Install the SDK:
31
31
  npm install @dymchenko/en-sdk @coral-xyz/anchor @solana/web3.js
32
32
  ```
33
33
 
34
- Set your keypair and RPC endpoint:
34
+ Set your keypair and RPC endpoint **before running any command**:
35
35
 
36
36
  ```bash
37
37
  export ACP_KEYPAIR_PATH=/path/to/keypair.json # Solana JSON keypair file
38
- export ACP_RPC_URL=http://localhost:8899 # optional, defaults to localnet
38
+ export ACP_RPC_URL=http://localhost:8899 # optional, defaults to localnet
39
39
  ```
40
40
 
41
+ If `ACP_KEYPAIR_PATH` is not set, all commands will fail. Do not proceed without it.
42
+
41
43
  Confirm identity:
42
44
 
43
45
  ```bash
44
- npx ts-node node_modules/@dymchenko/en-sdk/dist/cli.js whoami
46
+ npx en whoami
47
+ ```
48
+
49
+ If `npx en` is not found, use the full path:
50
+ ```bash
51
+ node node_modules/@dymchenko/en-sdk/dist/cli.js whoami
45
52
  ```
46
53
 
47
54
  ## Available Commands
48
55
 
56
+ All commands are run as `npx en <command>`.
57
+
49
58
  ### Identity
50
59
  ```bash
51
- whoami
60
+ npx en whoami
52
61
  ```
53
62
 
54
63
  ### Client commands
55
64
  ```bash
56
- create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds]
57
- create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds] --bilateral
58
- create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds] --recurrence <secs> [--lock-provider] [--lock-evaluator]
59
- fund <job_pda>
60
- expire <job_pda>
61
- cancel-recurring <job_pda>
62
- update-evaluator <job_pda> <new_evaluator_pubkey>
63
- client-accept-evaluator <job_pda>
64
- client-reject-evaluator <job_pda>
65
+ npx en create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds]
66
+ npx en create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds] --bilateral
67
+ npx en create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds] --recurrence <secs> [--lock-provider] [--lock-evaluator]
68
+ npx en fund <job_pda>
69
+ npx en expire <job_pda>
70
+ npx en cancel-recurring <job_pda>
71
+ npx en update-evaluator <job_pda> <new_evaluator_pubkey>
72
+ npx en client-accept-evaluator <job_pda>
73
+ npx en client-reject-evaluator <job_pda>
65
74
  ```
66
75
 
67
76
  ### Provider commands
68
77
  ```bash
69
- list-jobs --status funded
70
- show-job <job_pda>
71
- submit <job_pda> "<result>"
72
- accept-evaluator <job_pda>
73
- propose-evaluator <job_pda> <evaluator_pubkey>
78
+ npx en list-jobs --status funded
79
+ npx en show-job <job_pda>
80
+ npx en submit <job_pda> "<result>"
81
+ npx en accept-evaluator <job_pda>
82
+ npx en propose-evaluator <job_pda> <evaluator_pubkey>
74
83
  ```
75
84
 
76
85
  ### Evaluator commands
77
86
  ```bash
78
- list-jobs --status submitted
79
- show-job <job_pda>
80
- approve <job_pda>
81
- reject <job_pda>
87
+ npx en list-jobs --status submitted
88
+ npx en show-job <job_pda>
89
+ npx en approve <job_pda>
90
+ npx en reject <job_pda>
82
91
  ```
83
92
 
84
93
  ### Shared / read-only
85
94
  ```bash
86
- list-jobs [--status open|funded|submitted|complete|rejected|expired|cancelled|all]
87
- show-job <job_pda>
95
+ npx en list-jobs [--status open|funded|submitted|complete|rejected|expired|cancelled|all]
96
+ npx en show-job <job_pda>
88
97
  ```
89
98
 
90
99
  ### Keeper commands
91
100
  ```bash
92
- reopen-job <job_pda>
101
+ npx en reopen-job <job_pda>
93
102
  ```
94
103
 
95
104
  ## Role Workflows
96
105
 
97
106
  ### Client — standard job
98
107
 
99
- 1. Run `whoami` to confirm your identity and balance.
100
- 2. Run `create-job "<task>" <amount_sol> <evaluator_pubkey>` — this creates and funds the job atomically.
108
+ 1. Run `npx en whoami` to confirm your identity and balance.
109
+ 2. Run `npx en create-job "<task>" <amount_sol> <evaluator_pubkey>` — this creates and funds the job atomically.
101
110
  3. Report the Job PDA. **STOP.** Wait for a provider.
102
111
 
103
112
  ### Client — bilateral job
104
113
 
105
114
  Use `--bilateral` when the provider must agree on the evaluator before you commit funds.
106
115
 
107
- 1. Run `create-job ... --bilateral` — creates the job unfunded.
116
+ 1. Run `npx en create-job ... --bilateral` — creates the job unfunded.
108
117
  2. Poll `show-job <pda>` until state is `open` with provider agreement, or `negotiating`.
109
- - If `negotiating`: run `client-accept-evaluator` or `client-reject-evaluator`.
110
- - If `open` with agreement: run `fund`.
118
+ - If `negotiating`: run `npx en client-accept-evaluator` or `client-reject-evaluator`.
119
+ - If `open` with agreement: run `npx en fund`.
111
120
  3. **STOP.**
112
121
 
113
122
  ### Client — recurring job
114
123
 
115
- 1. Run `create-job ... --recurrence <seconds>` — creates and funds the first cycle.
124
+ 1. Run `npx en create-job ... --recurrence <seconds>` — creates and funds the first cycle.
116
125
  - `--lock-provider`: same provider must submit every cycle.
117
126
  - `--lock-evaluator`: same evaluator used every cycle. If omitted, call `update-evaluator` before funding each new cycle.
118
127
  2. After each `complete`, a keeper calls `reopen-job` to start the next cycle.
@@ -121,22 +130,23 @@ Use `--bilateral` when the provider must agree on the evaluator before you commi
121
130
 
122
131
  ### Provider
123
132
 
124
- 1. Run `whoami`.
125
- 2. Run `list-jobs --status funded` to find available work.
133
+ 1. Run `npx en whoami`.
134
+ 2. Run `npx en list-jobs --status funded` to find available work.
126
135
  3. Run `show-job <pda>` to read the task carefully.
127
136
  4. **Do the work.** Produce a correct, complete answer.
128
- 5. Run `submit <job_pda> "<your result>"`.
137
+ 5. Run `npx en submit <job_pda> "<your result>"`.
129
138
  6. **STOP.** Report what you submitted and wait for the evaluator.
130
139
 
131
140
  ### Evaluator
132
141
 
133
- 1. Run `whoami`.
134
- 2. Run `list-jobs --status submitted`.
135
- 3. Run `show-job <pda>` to read the task and result.
142
+ 1. Run `npx en whoami`.
143
+ 2. Run `npx en list-jobs --status submitted`.
144
+ - If no submitted jobs exist, **STOP**. Say "No submitted jobs. Nothing to evaluate."
145
+ 3. Run `npx en show-job <pda>` to read the task and result.
136
146
  4. Evaluate honestly:
137
147
  - Does the result answer the task?
138
148
  - Is it correct, complete, and well-formed?
139
- 5. State your reasoning, then run `approve <pda>` or `reject <pda>`.
149
+ 5. State your reasoning, then run `npx en approve <pda>` or `npx en reject <pda>`.
140
150
  - `approve` → funds released to the provider.
141
151
  - `reject` → funds returned to the client.
142
152
  6. **STOP.**
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,445 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const web3_js_1 = require("@solana/web3.js");
41
+ const anchor = __importStar(require("@coral-xyz/anchor"));
42
+ const bs58_1 = __importDefault(require("bs58"));
43
+ const fs_1 = __importDefault(require("fs"));
44
+ const sdk_1 = require("./sdk");
45
+ const RPC_URL = process.env.ACP_RPC_URL || "http://localhost:8899";
46
+ function die(msg) {
47
+ // eslint-disable-next-line no-console
48
+ console.error(msg);
49
+ process.exit(1);
50
+ }
51
+ function loadKeypair() {
52
+ const fromBase58 = process.env.ACP_KEYPAIR;
53
+ const fromPath = process.env.ACP_KEYPAIR_PATH;
54
+ if (fromBase58) {
55
+ try {
56
+ return web3_js_1.Keypair.fromSecretKey(bs58_1.default.decode(fromBase58));
57
+ }
58
+ catch (e) {
59
+ die(`Failed to decode ACP_KEYPAIR base58: ${e?.message || e}`);
60
+ }
61
+ }
62
+ if (fromPath) {
63
+ try {
64
+ const raw = fs_1.default.readFileSync(fromPath, "utf8");
65
+ const arr = JSON.parse(raw);
66
+ if (!Array.isArray(arr))
67
+ die("ACP_KEYPAIR_PATH must point to a JSON array file.");
68
+ return web3_js_1.Keypair.fromSecretKey(Uint8Array.from(arr));
69
+ }
70
+ catch (e) {
71
+ die(`Failed to read ACP_KEYPAIR_PATH: ${e?.message || e}`);
72
+ }
73
+ }
74
+ die("Missing keypair. Set ACP_KEYPAIR (base58) or ACP_KEYPAIR_PATH (path to Solana JSON keypair).");
75
+ }
76
+ function parseState(stateObj) {
77
+ if (!stateObj || typeof stateObj !== "object")
78
+ return "unknown";
79
+ const keys = Object.keys(stateObj);
80
+ return keys[0] || "unknown";
81
+ }
82
+ function usage() {
83
+ die([
84
+ "Usage: npx ts-node --esm sdk/cli.ts <command> [args]",
85
+ "",
86
+ "Env:",
87
+ " ACP_RPC_URL (optional) defaults to localnet (http://localhost:8899)",
88
+ " ACP_KEYPAIR base58 secret key, OR",
89
+ " ACP_KEYPAIR_PATH path to Solana JSON keypair",
90
+ "",
91
+ "Commands:",
92
+ " whoami",
93
+ ' create-job "<task>" <amount_sol> <evaluator_pubkey> [expiry_seconds] [--bilateral] [--recurrence <secs>] [--lock-provider] [--lock-evaluator]',
94
+ " fund <job_pda>",
95
+ " list-jobs [--status funded|submitted|open|negotiating|complete|rejected|expired|cancelled|all]",
96
+ " show-job <job_pda>",
97
+ ' submit <job_pda> "<result_hash_or_result_text>"',
98
+ " approve <job_pda>",
99
+ " reject <job_pda>",
100
+ " expire <job_pda>",
101
+ "",
102
+ "Bilateral evaluator negotiation (bilateral jobs only):",
103
+ " accept-evaluator <job_pda> (provider) accept client's evaluator",
104
+ " propose-evaluator <job_pda> <addr> (provider) counter-propose a different evaluator",
105
+ " client-accept-evaluator <job_pda> (client) accept provider's counter-proposal",
106
+ " client-reject-evaluator <job_pda> (client) reject provider's counter-proposal",
107
+ "",
108
+ "Recurring jobs:",
109
+ " reopen-job <job_pda> (keeper) reopen a complete recurring job",
110
+ " cancel-recurring <job_pda> (client) cancel a recurring job",
111
+ " update-evaluator <job_pda> <addr> (client) set evaluator for next cycle",
112
+ ].join("\n"));
113
+ }
114
+ async function cmdWhoami(connection, wallet) {
115
+ const bal = await connection.getBalance(wallet.publicKey, "confirmed");
116
+ // eslint-disable-next-line no-console
117
+ console.log([
118
+ "Wallet:",
119
+ ` Pubkey: ${wallet.publicKey.toBase58()}`,
120
+ ` Balance: ${(bal / web3_js_1.LAMPORTS_PER_SOL).toFixed(4)} SOL`,
121
+ "",
122
+ "Program:",
123
+ ` ProgramID: ${sdk_1.PROGRAM_ID.toBase58()}`,
124
+ ` RPC: ${RPC_URL}`,
125
+ ].join("\n"));
126
+ }
127
+ async function cmdCreateJob(connection, wallet, argv) {
128
+ // Parse boolean flags
129
+ const bilateralIdx = argv.indexOf("--bilateral");
130
+ const bilateral = bilateralIdx !== -1;
131
+ if (bilateral)
132
+ argv.splice(bilateralIdx, 1);
133
+ const lockProviderIdx = argv.indexOf("--lock-provider");
134
+ const lockProvider = lockProviderIdx !== -1;
135
+ if (lockProvider)
136
+ argv.splice(lockProviderIdx, 1);
137
+ const lockEvaluatorIdx = argv.indexOf("--lock-evaluator");
138
+ const lockEvaluator = lockEvaluatorIdx !== -1;
139
+ if (lockEvaluator)
140
+ argv.splice(lockEvaluatorIdx, 1);
141
+ // Parse --recurrence <secs>
142
+ const recurrenceIdx = argv.indexOf("--recurrence");
143
+ let recurrenceInterval = new anchor.BN(0);
144
+ if (recurrenceIdx !== -1) {
145
+ const recurrenceStr = argv[recurrenceIdx + 1];
146
+ if (!recurrenceStr || !Number.isFinite(Number(recurrenceStr))) {
147
+ die("--recurrence requires a positive integer (seconds).");
148
+ }
149
+ recurrenceInterval = new anchor.BN(recurrenceStr);
150
+ argv.splice(recurrenceIdx, 2);
151
+ }
152
+ const task = argv[0];
153
+ const amountSolStr = argv[1];
154
+ const evaluatorStr = argv[2];
155
+ const expirySecondsStr = argv[3];
156
+ if (!task || !amountSolStr || !evaluatorStr)
157
+ usage();
158
+ const amountSol = Number(amountSolStr);
159
+ if (!Number.isFinite(amountSol) || amountSol <= 0)
160
+ die("amount_sol must be a positive number.");
161
+ let evaluator;
162
+ try {
163
+ evaluator = new web3_js_1.PublicKey(evaluatorStr);
164
+ }
165
+ catch {
166
+ die("Invalid evaluator pubkey.");
167
+ }
168
+ const expirySeconds = expirySecondsStr ? Number(expirySecondsStr) : 300;
169
+ if (!Number.isFinite(expirySeconds) || expirySeconds <= 0)
170
+ die("expiry_seconds must be a positive number.");
171
+ const { txSig, jobPda, jobId } = await (0, sdk_1.createJob)(connection, wallet, task, amountSol, evaluator, expirySeconds, bilateral, recurrenceInterval, lockProvider, lockEvaluator);
172
+ // eslint-disable-next-line no-console
173
+ console.log([
174
+ bilateral ? "Job created (awaiting evaluator agreement)!" : "Job created and funded!",
175
+ ` Job ID: #${jobId.toString()}`,
176
+ ` PDA: ${jobPda.toBase58()}`,
177
+ ` Task: ${JSON.stringify(task)}`,
178
+ ` Amount: ${amountSol} SOL`,
179
+ ` Evaluator: ${evaluator.toBase58()}`,
180
+ ` Bilateral: ${bilateral}`,
181
+ ` Expiry: ${expirySeconds}s from now`,
182
+ ...(recurrenceInterval.gtn(0)
183
+ ? [
184
+ ` Recurrence: every ${recurrenceInterval.toString()}s`,
185
+ ` Lock provider: ${lockProvider}`,
186
+ ` Lock evaluator: ${lockEvaluator}`,
187
+ ]
188
+ : []),
189
+ ` TX: ${txSig}`,
190
+ ...(bilateral ? ["", " Waiting for provider to accept or propose an evaluator before you can fund."] : []),
191
+ ].join("\n"));
192
+ }
193
+ async function cmdFund(connection, wallet, argv) {
194
+ const pdaStr = argv[0];
195
+ if (!pdaStr)
196
+ usage();
197
+ const tx = await (0, sdk_1.fundJob)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
198
+ // eslint-disable-next-line no-console
199
+ console.log(`Funded. TX: ${tx}`);
200
+ }
201
+ async function cmdAcceptEvaluator(connection, wallet, argv) {
202
+ const pdaStr = argv[0];
203
+ if (!pdaStr)
204
+ usage();
205
+ const tx = await (0, sdk_1.acceptEvaluator)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
206
+ // eslint-disable-next-line no-console
207
+ console.log(`Evaluator accepted. TX: ${tx}`);
208
+ }
209
+ async function cmdProposeEvaluator(connection, wallet, argv) {
210
+ const pdaStr = argv[0];
211
+ const newEvaluatorStr = argv[1];
212
+ if (!pdaStr || !newEvaluatorStr)
213
+ usage();
214
+ let newEvaluator;
215
+ try {
216
+ newEvaluator = new web3_js_1.PublicKey(newEvaluatorStr);
217
+ }
218
+ catch {
219
+ die("Invalid evaluator pubkey.");
220
+ }
221
+ const tx = await (0, sdk_1.proposeEvaluator)(connection, wallet, new web3_js_1.PublicKey(pdaStr), newEvaluator);
222
+ // eslint-disable-next-line no-console
223
+ console.log(`Counter-evaluator proposed. TX: ${tx}`);
224
+ }
225
+ async function cmdClientAcceptEvaluator(connection, wallet, argv) {
226
+ const pdaStr = argv[0];
227
+ if (!pdaStr)
228
+ usage();
229
+ const tx = await (0, sdk_1.clientAcceptEvaluator)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
230
+ // eslint-disable-next-line no-console
231
+ console.log(`Counter-proposal accepted. Evaluator updated. TX: ${tx}`);
232
+ }
233
+ async function cmdClientRejectEvaluator(connection, wallet, argv) {
234
+ const pdaStr = argv[0];
235
+ if (!pdaStr)
236
+ usage();
237
+ const tx = await (0, sdk_1.clientRejectEvaluator)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
238
+ // eslint-disable-next-line no-console
239
+ console.log(`Counter-proposal rejected. Job reset to Open. TX: ${tx}`);
240
+ }
241
+ async function cmdListJobs(connection, wallet, argv) {
242
+ const statusIdx = argv.findIndex((a) => a === "--status");
243
+ const status = statusIdx >= 0 ? argv[statusIdx + 1] : "all";
244
+ const all = await (0, sdk_1.getAllJobs)(connection, wallet);
245
+ const rows = all.map((j) => {
246
+ const acct = j.account;
247
+ const state = parseState(acct.state);
248
+ return {
249
+ jobId: acct.jobId?.toString?.() ?? "—",
250
+ pda: j.publicKey.toBase58(),
251
+ state,
252
+ amountSol: (acct.amountLamports?.toNumber?.() ?? 0) / web3_js_1.LAMPORTS_PER_SOL,
253
+ task: acct.task ?? "",
254
+ client: acct.client?.toBase58?.() ?? "",
255
+ provider: acct.provider?.toBase58?.() ?? "",
256
+ evaluator: acct.evaluator?.toBase58?.() ?? "",
257
+ resultHash: acct.resultHash ?? "",
258
+ expiry: acct.expiry?.toNumber?.() ?? 0,
259
+ recurrenceInterval: acct.recurrenceInterval?.toNumber?.() ?? 0,
260
+ recurrenceCount: acct.recurrenceCount?.toNumber?.() ?? 0,
261
+ };
262
+ });
263
+ const filtered = !status || status === "all"
264
+ ? rows
265
+ : rows.filter((r) => r.state.toLowerCase() === String(status).toLowerCase());
266
+ filtered.sort((a, b) => Number(b.jobId) - Number(a.jobId));
267
+ // eslint-disable-next-line no-console
268
+ console.log([
269
+ `Jobs (${filtered.length}/${rows.length})`,
270
+ "",
271
+ ...filtered.map((r) => {
272
+ const provider = r.provider === "11111111111111111111111111111111" ? "—" : r.provider;
273
+ const recurringLine = r.recurrenceInterval > 0
274
+ ? `\n Recurrence: every ${r.recurrenceInterval}s (cycle #${r.recurrenceCount})`
275
+ : "";
276
+ return [
277
+ `#${r.jobId} ${r.state.padEnd(11)} ${r.amountSol.toFixed(4)} SOL`,
278
+ ` PDA: ${r.pda}`,
279
+ ` Client: ${r.client}`,
280
+ ` Provider: ${provider}`,
281
+ ` Evaluator: ${r.evaluator}`,
282
+ ` Result: ${r.resultHash || "—"}`,
283
+ ` Task: ${r.task.length > 120 ? r.task.slice(0, 117) + "..." : r.task}${recurringLine}`,
284
+ ].join("\n");
285
+ }),
286
+ ].join("\n"));
287
+ }
288
+ async function cmdShowJob(connection, wallet, argv) {
289
+ const pdaStr = argv[0];
290
+ if (!pdaStr)
291
+ usage();
292
+ const jobPda = new web3_js_1.PublicKey(pdaStr);
293
+ const program = (0, sdk_1.getProgram)(connection, wallet);
294
+ const job = await program.account.job.fetch(jobPda);
295
+ const state = parseState(job.state);
296
+ const recurrenceInterval = job.recurrenceInterval?.toNumber?.() ?? 0;
297
+ // eslint-disable-next-line no-console
298
+ console.log([
299
+ "Job:",
300
+ ` PDA: ${jobPda.toBase58()}`,
301
+ ` ID: ${job.jobId.toString()}`,
302
+ ` State: ${state}`,
303
+ ` Task: ${JSON.stringify(job.task)}`,
304
+ ` Amount: ${Number(job.amountLamports.toString()) / web3_js_1.LAMPORTS_PER_SOL} SOL`,
305
+ ` Client: ${job.client.toBase58()}`,
306
+ ` Provider: ${job.provider.toBase58()}`,
307
+ ` Evaluator:${job.evaluator.toBase58()}`,
308
+ ` Expiry: ${job.expiry.toString()}`,
309
+ ` Result: ${JSON.stringify(job.resultHash || "")}`,
310
+ ...(recurrenceInterval > 0
311
+ ? [
312
+ ` Recurrence: every ${recurrenceInterval}s`,
313
+ ` Cycle: #${job.recurrenceCount?.toString()}`,
314
+ ` CompletedAt:${job.completedAt?.toString()}`,
315
+ ` LockProvider: ${job.lockProvider}`,
316
+ ` LockEvaluator: ${job.lockEvaluator}`,
317
+ ]
318
+ : []),
319
+ ].join("\n"));
320
+ }
321
+ async function cmdSubmit(connection, wallet, argv) {
322
+ const pdaStr = argv[0];
323
+ const result = argv[1];
324
+ if (!pdaStr || !result)
325
+ usage();
326
+ const tx = await (0, sdk_1.submitResult)(connection, wallet, new web3_js_1.PublicKey(pdaStr), result);
327
+ // eslint-disable-next-line no-console
328
+ console.log(`Submitted. TX: ${tx}`);
329
+ }
330
+ async function cmdApprove(connection, wallet, argv) {
331
+ const pdaStr = argv[0];
332
+ if (!pdaStr)
333
+ usage();
334
+ const tx = await (0, sdk_1.approveJob)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
335
+ // eslint-disable-next-line no-console
336
+ console.log(`Approved. TX: ${tx}`);
337
+ }
338
+ async function cmdReject(connection, wallet, argv) {
339
+ const pdaStr = argv[0];
340
+ if (!pdaStr)
341
+ usage();
342
+ const tx = await (0, sdk_1.rejectJob)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
343
+ // eslint-disable-next-line no-console
344
+ console.log(`Rejected. TX: ${tx}`);
345
+ }
346
+ async function cmdExpire(connection, wallet, argv) {
347
+ const pdaStr = argv[0];
348
+ if (!pdaStr)
349
+ usage();
350
+ const tx = await (0, sdk_1.expireJob)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
351
+ // eslint-disable-next-line no-console
352
+ console.log(`Expired. TX: ${tx}`);
353
+ }
354
+ async function cmdReopenJob(connection, wallet, argv) {
355
+ const pdaStr = argv[0];
356
+ if (!pdaStr)
357
+ usage();
358
+ const tx = await (0, sdk_1.reopenJob)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
359
+ // eslint-disable-next-line no-console
360
+ console.log(`Reopened. TX: ${tx}`);
361
+ }
362
+ async function cmdCancelRecurring(connection, wallet, argv) {
363
+ const pdaStr = argv[0];
364
+ if (!pdaStr)
365
+ usage();
366
+ const tx = await (0, sdk_1.cancelRecurring)(connection, wallet, new web3_js_1.PublicKey(pdaStr));
367
+ // eslint-disable-next-line no-console
368
+ console.log(`Recurring job cancelled. TX: ${tx}`);
369
+ }
370
+ async function cmdUpdateEvaluator(connection, wallet, argv) {
371
+ const pdaStr = argv[0];
372
+ const newEvaluatorStr = argv[1];
373
+ if (!pdaStr || !newEvaluatorStr)
374
+ usage();
375
+ let newEvaluator;
376
+ try {
377
+ newEvaluator = new web3_js_1.PublicKey(newEvaluatorStr);
378
+ }
379
+ catch {
380
+ die("Invalid evaluator pubkey.");
381
+ }
382
+ const tx = await (0, sdk_1.updateEvaluator)(connection, wallet, new web3_js_1.PublicKey(pdaStr), newEvaluator);
383
+ // eslint-disable-next-line no-console
384
+ console.log(`Evaluator updated. TX: ${tx}`);
385
+ }
386
+ async function main() {
387
+ const [command, ...rest] = process.argv.slice(2);
388
+ if (!command)
389
+ usage();
390
+ const wallet = loadKeypair();
391
+ const connection = new web3_js_1.Connection(RPC_URL, "confirmed");
392
+ switch (command) {
393
+ case "whoami":
394
+ await cmdWhoami(connection, wallet);
395
+ return;
396
+ case "create-job":
397
+ await cmdCreateJob(connection, wallet, rest);
398
+ return;
399
+ case "fund":
400
+ await cmdFund(connection, wallet, rest);
401
+ return;
402
+ case "list-jobs":
403
+ await cmdListJobs(connection, wallet, rest);
404
+ return;
405
+ case "show-job":
406
+ await cmdShowJob(connection, wallet, rest);
407
+ return;
408
+ case "submit":
409
+ await cmdSubmit(connection, wallet, rest);
410
+ return;
411
+ case "approve":
412
+ await cmdApprove(connection, wallet, rest);
413
+ return;
414
+ case "reject":
415
+ await cmdReject(connection, wallet, rest);
416
+ return;
417
+ case "expire":
418
+ await cmdExpire(connection, wallet, rest);
419
+ return;
420
+ case "accept-evaluator":
421
+ await cmdAcceptEvaluator(connection, wallet, rest);
422
+ return;
423
+ case "propose-evaluator":
424
+ await cmdProposeEvaluator(connection, wallet, rest);
425
+ return;
426
+ case "client-accept-evaluator":
427
+ await cmdClientAcceptEvaluator(connection, wallet, rest);
428
+ return;
429
+ case "client-reject-evaluator":
430
+ await cmdClientRejectEvaluator(connection, wallet, rest);
431
+ return;
432
+ case "reopen-job":
433
+ await cmdReopenJob(connection, wallet, rest);
434
+ return;
435
+ case "cancel-recurring":
436
+ await cmdCancelRecurring(connection, wallet, rest);
437
+ return;
438
+ case "update-evaluator":
439
+ await cmdUpdateEvaluator(connection, wallet, rest);
440
+ return;
441
+ default:
442
+ usage();
443
+ }
444
+ }
445
+ main().catch((e) => die(e?.message || String(e)));
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@dymchenko/en-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "TypeScript SDK for the En Protocol — trustless agent commerce on Solana",
5
5
  "main": "dist/sdk.js",
6
6
  "types": "dist/sdk.d.ts",
7
+ "bin": {
8
+ "en": "dist/cli.js"
9
+ },
7
10
  "exports": {
8
11
  ".": {
9
12
  "require": "./dist/sdk.js",