@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 +48 -38
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +445 -0
- package/package.json +4 -1
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
|
|
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
|
|
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
|
-
|
|
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 @@
|
|
|
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.
|
|
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",
|