zk-agent-cli 0.1.0-rc.3 → 0.1.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/index.js +765 -68
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -34,6 +34,18 @@ What each step is doing:
|
|
|
34
34
|
- `workflow pay` is the flagship zkSync-native AA native-send path
|
|
35
35
|
- `suite` is the packaged surface
|
|
36
36
|
|
|
37
|
+
The packaged default story is payment-first: send native value now, stay on
|
|
38
|
+
the approval-based pay path when fee-token/default state matters, and recover
|
|
39
|
+
funding only when the workflow says the write path is blocked.
|
|
40
|
+
|
|
41
|
+
The first Agent Pay platform primitive now exists as a local-first payment
|
|
42
|
+
request surface:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
zk-agent payment create --wallet main --to <address> --amount <amount>
|
|
46
|
+
zk-agent payment list
|
|
47
|
+
```
|
|
48
|
+
|
|
37
49
|
If readiness is unclear before you choose a fix, use:
|
|
38
50
|
|
|
39
51
|
```bash
|
|
@@ -116,6 +128,7 @@ ZK_AGENT_STORAGE_DIR=
|
|
|
116
128
|
`zk-agent wallet next --name <wallet>`: wallet-scoped repair and readiness
|
|
117
129
|
- `zk-agent workflow ...`: explicit workflow planning, persistence, status, and
|
|
118
130
|
resume questions
|
|
131
|
+
- `zk-agent payment ...`: local-first payment request capture and settlement-state tracking for the Agent Pay platform layer
|
|
119
132
|
- `zk-agent suite`: the packaged post-flagship catalog once wallet readiness is
|
|
120
133
|
no longer the blocker
|
|
121
134
|
|
|
@@ -225,6 +238,9 @@ Current `suite` operator journeys:
|
|
|
225
238
|
- `unstick a write`
|
|
226
239
|
- `recover remote approval`
|
|
227
240
|
|
|
241
|
+
If you only need one default starting point inside `suite`, start with
|
|
242
|
+
`send value now`.
|
|
243
|
+
|
|
228
244
|
Use `--wallet <name>` or `--chain <chain>` when the returned suite commands
|
|
229
245
|
should stay on a non-default wallet or chain.
|
|
230
246
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command14, CommanderError } from "commander";
|
|
5
5
|
import { config as loadEnv } from "dotenv";
|
|
6
6
|
|
|
7
7
|
// src/commands/operations.ts
|
|
@@ -79,6 +79,9 @@ import fs from "node:fs";
|
|
|
79
79
|
import os from "node:os";
|
|
80
80
|
import path from "node:path";
|
|
81
81
|
|
|
82
|
+
// ../agent-core/src/wallet-session.ts
|
|
83
|
+
import { createHash } from "node:crypto";
|
|
84
|
+
|
|
82
85
|
// ../agent-session-protocol/src/constants.ts
|
|
83
86
|
var PROTOCOL_VERSION = "zk-agent-session-v1";
|
|
84
87
|
|
|
@@ -239,6 +242,10 @@ function buildApprovedSessionPayload(input) {
|
|
|
239
242
|
function isHexPrivateKey(value) {
|
|
240
243
|
return /^0x[a-fA-F0-9]{64}$/.test(value);
|
|
241
244
|
}
|
|
245
|
+
function deriveStableWalletId(wallet) {
|
|
246
|
+
const seed = `${wallet.walletAddress.trim().toLowerCase()}:${wallet.chainId}:${wallet.createdAt.trim()}`;
|
|
247
|
+
return `wal_${createHash("sha256").update(seed).digest("hex").slice(0, 24)}`;
|
|
248
|
+
}
|
|
242
249
|
function deriveLocalExecutionSignerAddress(privateKey) {
|
|
243
250
|
if (!privateKey || !isHexPrivateKey(privateKey)) return void 0;
|
|
244
251
|
try {
|
|
@@ -263,15 +270,25 @@ function resolveLocalExecutionPrivateKey(wallet) {
|
|
|
263
270
|
function migrateWalletSessionRecord(wallet) {
|
|
264
271
|
const legacyPrivateKey = wallet.sessionPayload?.sessionPrivateKey;
|
|
265
272
|
const existingAuthority = wallet.localExecutionAuthority;
|
|
273
|
+
const walletId = wallet.walletId || deriveStableWalletId(wallet);
|
|
266
274
|
if (!existingAuthority && !legacyPrivateKey) {
|
|
267
|
-
return wallet;
|
|
275
|
+
if (wallet.walletId === walletId) return wallet;
|
|
276
|
+
return {
|
|
277
|
+
...wallet,
|
|
278
|
+
walletId
|
|
279
|
+
};
|
|
268
280
|
}
|
|
269
281
|
const privateKey = existingAuthority?.privateKey || legacyPrivateKey;
|
|
270
282
|
if (!privateKey) {
|
|
271
|
-
return wallet;
|
|
283
|
+
if (wallet.walletId === walletId) return wallet;
|
|
284
|
+
return {
|
|
285
|
+
...wallet,
|
|
286
|
+
walletId
|
|
287
|
+
};
|
|
272
288
|
}
|
|
273
289
|
return {
|
|
274
290
|
...wallet,
|
|
291
|
+
walletId,
|
|
275
292
|
localExecutionAuthority: {
|
|
276
293
|
privateKey,
|
|
277
294
|
signerAddress: existingAuthority?.signerAddress || deriveLocalExecutionSignerAddress(privateKey),
|
|
@@ -375,6 +392,33 @@ function readEncryptedJson(filePath) {
|
|
|
375
392
|
function storageDir() {
|
|
376
393
|
return ensureStorageDir();
|
|
377
394
|
}
|
|
395
|
+
function ensureStorageCollectionDir(collectionName) {
|
|
396
|
+
const storageDirectory = ensureStorageDir();
|
|
397
|
+
const collectionDirectory = path.join(storageDirectory, collectionName);
|
|
398
|
+
if (!fs.existsSync(collectionDirectory)) {
|
|
399
|
+
fs.mkdirSync(collectionDirectory, { recursive: true, mode: 448 });
|
|
400
|
+
}
|
|
401
|
+
return collectionDirectory;
|
|
402
|
+
}
|
|
403
|
+
async function saveEncryptedStorageRecord(collectionName, recordId, value) {
|
|
404
|
+
const collectionDirectory = ensureStorageCollectionDir(collectionName);
|
|
405
|
+
writeEncryptedJson(path.join(collectionDirectory, `${recordId}.json`), value);
|
|
406
|
+
}
|
|
407
|
+
async function loadEncryptedStorageRecord(collectionName, recordId) {
|
|
408
|
+
const filePath = storagePath(collectionName, `${recordId}.json`);
|
|
409
|
+
if (!fs.existsSync(filePath)) return null;
|
|
410
|
+
return readEncryptedJson(filePath);
|
|
411
|
+
}
|
|
412
|
+
async function listEncryptedStorageRecordIds(collectionName) {
|
|
413
|
+
const collectionDirectory = ensureStorageCollectionDir(collectionName);
|
|
414
|
+
return fs.readdirSync(collectionDirectory).filter((entry) => entry.endsWith(".json")).map((entry) => entry.replace(/\.json$/, ""));
|
|
415
|
+
}
|
|
416
|
+
async function deleteEncryptedStorageRecord(collectionName, recordId) {
|
|
417
|
+
const filePath = storagePath(collectionName, `${recordId}.json`);
|
|
418
|
+
if (!fs.existsSync(filePath)) return false;
|
|
419
|
+
fs.unlinkSync(filePath);
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
378
422
|
async function saveProjectConfig(config) {
|
|
379
423
|
const storageDirectory = ensureStorageDir();
|
|
380
424
|
writeJson(path.join(storageDirectory, "config.json"), config);
|
|
@@ -385,64 +429,42 @@ async function loadProjectConfig() {
|
|
|
385
429
|
return readJson(filePath);
|
|
386
430
|
}
|
|
387
431
|
async function saveWalletSession(record) {
|
|
388
|
-
|
|
389
|
-
writeEncryptedJson(
|
|
390
|
-
path.join(storageDirectory, "wallets", `${record.walletName}.json`),
|
|
391
|
-
migrateWalletSessionRecord(record)
|
|
392
|
-
);
|
|
432
|
+
await saveEncryptedStorageRecord("wallets", record.walletName, migrateWalletSessionRecord(record));
|
|
393
433
|
}
|
|
394
434
|
async function loadWalletSession(walletName) {
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
return migrateWalletSessionRecord(readEncryptedJson(filePath));
|
|
435
|
+
const record = await loadEncryptedStorageRecord("wallets", walletName);
|
|
436
|
+
return record ? migrateWalletSessionRecord(record) : null;
|
|
398
437
|
}
|
|
399
438
|
async function listWalletNames() {
|
|
400
|
-
|
|
401
|
-
return fs.readdirSync(path.join(storageDirectory, "wallets")).filter((entry) => entry.endsWith(".json")).map((entry) => entry.replace(/\.json$/, ""));
|
|
439
|
+
return listEncryptedStorageRecordIds("wallets");
|
|
402
440
|
}
|
|
403
441
|
async function listWalletRequestIds() {
|
|
404
442
|
const storageDirectory = ensureStorageDir();
|
|
405
443
|
return fs.readdirSync(path.join(storageDirectory, "requests")).filter((entry) => entry.endsWith(".json")).map((entry) => entry.replace(/\.json$/, ""));
|
|
406
444
|
}
|
|
407
445
|
async function deleteWalletSession(walletName) {
|
|
408
|
-
|
|
409
|
-
if (!fs.existsSync(filePath)) return false;
|
|
410
|
-
fs.unlinkSync(filePath);
|
|
411
|
-
return true;
|
|
446
|
+
return deleteEncryptedStorageRecord("wallets", walletName);
|
|
412
447
|
}
|
|
413
448
|
async function saveWalletRequest(record) {
|
|
414
|
-
|
|
415
|
-
writeEncryptedJson(path.join(storageDirectory, "requests", `${record.requestId}.json`), record);
|
|
449
|
+
await saveEncryptedStorageRecord("requests", record.requestId, record);
|
|
416
450
|
}
|
|
417
451
|
async function loadWalletRequest(requestId) {
|
|
418
|
-
|
|
419
|
-
if (!fs.existsSync(filePath)) return null;
|
|
420
|
-
return readEncryptedJson(filePath);
|
|
452
|
+
return loadEncryptedStorageRecord("requests", requestId);
|
|
421
453
|
}
|
|
422
454
|
async function deleteWalletRequest(requestId) {
|
|
423
|
-
|
|
424
|
-
if (!fs.existsSync(filePath)) return false;
|
|
425
|
-
fs.unlinkSync(filePath);
|
|
426
|
-
return true;
|
|
455
|
+
return deleteEncryptedStorageRecord("requests", requestId);
|
|
427
456
|
}
|
|
428
457
|
async function saveWorkflowCheckpoint(record) {
|
|
429
|
-
|
|
430
|
-
writeEncryptedJson(path.join(storageDirectory, "workflows", `${record.requestId}.json`), record);
|
|
458
|
+
await saveEncryptedStorageRecord("workflows", record.requestId, record);
|
|
431
459
|
}
|
|
432
460
|
async function loadWorkflowCheckpoint(requestId) {
|
|
433
|
-
|
|
434
|
-
if (!fs.existsSync(filePath)) return null;
|
|
435
|
-
return readEncryptedJson(filePath);
|
|
461
|
+
return loadEncryptedStorageRecord("workflows", requestId);
|
|
436
462
|
}
|
|
437
463
|
async function listWorkflowCheckpointIds() {
|
|
438
|
-
|
|
439
|
-
return fs.readdirSync(path.join(storageDirectory, "workflows")).filter((entry) => entry.endsWith(".json")).map((entry) => entry.replace(/\.json$/, ""));
|
|
464
|
+
return listEncryptedStorageRecordIds("workflows");
|
|
440
465
|
}
|
|
441
466
|
async function deleteWorkflowCheckpoint(requestId) {
|
|
442
|
-
|
|
443
|
-
if (!fs.existsSync(filePath)) return false;
|
|
444
|
-
fs.unlinkSync(filePath);
|
|
445
|
-
return true;
|
|
467
|
+
return deleteEncryptedStorageRecord("workflows", requestId);
|
|
446
468
|
}
|
|
447
469
|
async function renameWalletSession(walletName, nextWalletName) {
|
|
448
470
|
const storageDirectory = ensureStorageDir();
|
|
@@ -461,7 +483,7 @@ async function renameWalletSession(walletName, nextWalletName) {
|
|
|
461
483
|
if (fs.existsSync(targetFilePath)) {
|
|
462
484
|
throw new Error(`Wallet already exists: ${targetName}`);
|
|
463
485
|
}
|
|
464
|
-
const wallet = readEncryptedJson(currentFilePath);
|
|
486
|
+
const wallet = migrateWalletSessionRecord(readEncryptedJson(currentFilePath));
|
|
465
487
|
wallet.walletName = targetName;
|
|
466
488
|
writeEncryptedJson(targetFilePath, wallet);
|
|
467
489
|
fs.unlinkSync(currentFilePath);
|
|
@@ -8000,6 +8022,37 @@ function buildWorkflowPayRecommendedCommand(walletName, paymasterMode) {
|
|
|
8000
8022
|
const command = `zk-agent workflow pay --wallet ${walletName} --to <address> --amount <amount>`;
|
|
8001
8023
|
return appendPaymasterMode(command, paymasterMode);
|
|
8002
8024
|
}
|
|
8025
|
+
function buildSendTokenRecommendedCommand(input) {
|
|
8026
|
+
let command = `zk-agent send-token --wallet ${input.walletName}`;
|
|
8027
|
+
command += ` --to ${input.to || "<address>"}`;
|
|
8028
|
+
command += ` --amount ${input.amount || "<amount>"}`;
|
|
8029
|
+
if (input.symbol) {
|
|
8030
|
+
command += ` --symbol ${input.symbol}`;
|
|
8031
|
+
}
|
|
8032
|
+
if (input.tokenAddress) {
|
|
8033
|
+
command += ` --token ${input.tokenAddress}`;
|
|
8034
|
+
}
|
|
8035
|
+
if (input.decimals !== void 0) {
|
|
8036
|
+
command += ` --decimals ${input.decimals}`;
|
|
8037
|
+
}
|
|
8038
|
+
return appendPaymasterMode(command, input.paymasterMode);
|
|
8039
|
+
}
|
|
8040
|
+
function buildPaymentListRecommendedCommand() {
|
|
8041
|
+
return "zk-agent payment list";
|
|
8042
|
+
}
|
|
8043
|
+
function buildPaymentShowRecommendedCommand(requestId) {
|
|
8044
|
+
return `zk-agent payment show --request-id ${requestId}`;
|
|
8045
|
+
}
|
|
8046
|
+
function buildPaymentSetStatusRecommendedCommand(requestId, status, txHash) {
|
|
8047
|
+
let command = `zk-agent payment set-status --request-id ${requestId} --status ${status}`;
|
|
8048
|
+
if (txHash) {
|
|
8049
|
+
command += ` --tx-hash ${txHash}`;
|
|
8050
|
+
}
|
|
8051
|
+
return command;
|
|
8052
|
+
}
|
|
8053
|
+
function buildPaymentRemoveRecommendedCommand(requestId) {
|
|
8054
|
+
return `zk-agent payment remove --request-id ${requestId}`;
|
|
8055
|
+
}
|
|
8003
8056
|
function buildWorkflowFundRecommendedCommand(walletName) {
|
|
8004
8057
|
return `zk-agent workflow fund --wallet ${walletName}`;
|
|
8005
8058
|
}
|
|
@@ -12838,8 +12891,615 @@ function createDefaultsCommand() {
|
|
|
12838
12891
|
});
|
|
12839
12892
|
}
|
|
12840
12893
|
|
|
12841
|
-
// src/commands/
|
|
12894
|
+
// src/commands/payment.ts
|
|
12895
|
+
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
12842
12896
|
import { Command as Command7 } from "commander";
|
|
12897
|
+
|
|
12898
|
+
// ../agent-pay/src/execution-plan.ts
|
|
12899
|
+
function buildPaymentExecutionPlan(record) {
|
|
12900
|
+
return {
|
|
12901
|
+
action: record.asset.kind === "native" ? "native-transfer" : "erc20-transfer",
|
|
12902
|
+
surface: record.executionPreference.surface,
|
|
12903
|
+
walletId: record.walletId,
|
|
12904
|
+
walletName: record.walletName,
|
|
12905
|
+
chain: record.chain,
|
|
12906
|
+
chainId: record.chainId,
|
|
12907
|
+
paymasterMode: record.executionPreference.paymasterMode,
|
|
12908
|
+
payeeAddress: record.payee.address,
|
|
12909
|
+
asset: record.asset
|
|
12910
|
+
};
|
|
12911
|
+
}
|
|
12912
|
+
|
|
12913
|
+
// ../agent-pay/src/payment-request.ts
|
|
12914
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
12915
|
+
var PAYMENT_REQUEST_STATUS_TRANSITIONS = {
|
|
12916
|
+
draft: ["draft", "ready", "cancelled"],
|
|
12917
|
+
ready: ["draft", "ready", "paid", "cancelled"],
|
|
12918
|
+
paid: ["paid"],
|
|
12919
|
+
cancelled: ["cancelled"]
|
|
12920
|
+
};
|
|
12921
|
+
function nowIso2() {
|
|
12922
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
12923
|
+
}
|
|
12924
|
+
function createPaymentHistoryEventId() {
|
|
12925
|
+
return `payevt-${randomBytes4(4).toString("hex")}`;
|
|
12926
|
+
}
|
|
12927
|
+
function normalizeOptionalString4(value) {
|
|
12928
|
+
const trimmed = value?.trim();
|
|
12929
|
+
return trimmed ? trimmed : void 0;
|
|
12930
|
+
}
|
|
12931
|
+
function normalizeMetadata2(metadata) {
|
|
12932
|
+
if (!metadata) return {};
|
|
12933
|
+
const normalized = {};
|
|
12934
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
12935
|
+
const normalizedKey = key.trim();
|
|
12936
|
+
const normalizedValue = value.trim();
|
|
12937
|
+
if (!normalizedKey || !normalizedValue) continue;
|
|
12938
|
+
normalized[normalizedKey] = normalizedValue;
|
|
12939
|
+
}
|
|
12940
|
+
return normalized;
|
|
12941
|
+
}
|
|
12942
|
+
function normalizePaymentAsset(asset) {
|
|
12943
|
+
const amount = asset.amount.trim();
|
|
12944
|
+
if (!amount) {
|
|
12945
|
+
throw new AgentError("PAYMENT_AMOUNT_REQUIRED", "Payment amount is required.");
|
|
12946
|
+
}
|
|
12947
|
+
if (asset.kind === "native") {
|
|
12948
|
+
return {
|
|
12949
|
+
kind: "native",
|
|
12950
|
+
amount,
|
|
12951
|
+
symbol: normalizeOptionalString4(asset.symbol)
|
|
12952
|
+
};
|
|
12953
|
+
}
|
|
12954
|
+
const tokenAddress = asset.tokenAddress?.trim();
|
|
12955
|
+
if (!tokenAddress) {
|
|
12956
|
+
throw new AgentError(
|
|
12957
|
+
"PAYMENT_TOKEN_REQUIRED",
|
|
12958
|
+
"ERC-20 payment requests require a token address."
|
|
12959
|
+
);
|
|
12960
|
+
}
|
|
12961
|
+
if (!Number.isInteger(asset.decimals) || Number(asset.decimals) < 0) {
|
|
12962
|
+
throw new AgentError(
|
|
12963
|
+
"PAYMENT_TOKEN_DECIMALS_REQUIRED",
|
|
12964
|
+
"ERC-20 payment requests require non-negative token decimals."
|
|
12965
|
+
);
|
|
12966
|
+
}
|
|
12967
|
+
return {
|
|
12968
|
+
kind: "erc20",
|
|
12969
|
+
amount,
|
|
12970
|
+
tokenAddress,
|
|
12971
|
+
decimals: Number(asset.decimals),
|
|
12972
|
+
symbol: normalizeOptionalString4(asset.symbol)
|
|
12973
|
+
};
|
|
12974
|
+
}
|
|
12975
|
+
function inferExecutionSurface(asset) {
|
|
12976
|
+
return asset.kind === "native" ? "workflow-pay" : "send-token";
|
|
12977
|
+
}
|
|
12978
|
+
function createPaymentHistoryEvent(input) {
|
|
12979
|
+
return {
|
|
12980
|
+
eventId: createPaymentHistoryEventId(),
|
|
12981
|
+
type: input.type,
|
|
12982
|
+
at: input.at,
|
|
12983
|
+
status: input.status,
|
|
12984
|
+
previousStatus: input.previousStatus,
|
|
12985
|
+
txHash: normalizeOptionalString4(input.txHash),
|
|
12986
|
+
note: normalizeOptionalString4(input.note)
|
|
12987
|
+
};
|
|
12988
|
+
}
|
|
12989
|
+
function buildLegacyPaymentHistory(record) {
|
|
12990
|
+
return [
|
|
12991
|
+
{
|
|
12992
|
+
eventId: `payevt-${record.requestId}-legacy-created`,
|
|
12993
|
+
type: "created",
|
|
12994
|
+
at: record.createdAt,
|
|
12995
|
+
status: record.settlement.status,
|
|
12996
|
+
txHash: record.settlement.txHash,
|
|
12997
|
+
note: record.settlement.note
|
|
12998
|
+
}
|
|
12999
|
+
];
|
|
13000
|
+
}
|
|
13001
|
+
function migratePaymentRequestRecord(record) {
|
|
13002
|
+
return {
|
|
13003
|
+
...record,
|
|
13004
|
+
history: Array.isArray(record.history) && record.history.length > 0 ? record.history.map((event) => ({
|
|
13005
|
+
...event,
|
|
13006
|
+
txHash: normalizeOptionalString4(event.txHash),
|
|
13007
|
+
note: normalizeOptionalString4(event.note)
|
|
13008
|
+
})) : buildLegacyPaymentHistory(record)
|
|
13009
|
+
};
|
|
13010
|
+
}
|
|
13011
|
+
function createPaymentRequestRecord(input) {
|
|
13012
|
+
const timestamp = nowIso2();
|
|
13013
|
+
const payeeAddress = input.payeeAddress.trim();
|
|
13014
|
+
if (!payeeAddress) {
|
|
13015
|
+
throw new AgentError("PAYMENT_PAYEE_REQUIRED", "Payment payee address is required.");
|
|
13016
|
+
}
|
|
13017
|
+
const asset = normalizePaymentAsset(input.asset);
|
|
13018
|
+
const status = input.status ?? "ready";
|
|
13019
|
+
return {
|
|
13020
|
+
format: "zk-agent-payment-request",
|
|
13021
|
+
version: 1,
|
|
13022
|
+
requestId: input.requestId.trim(),
|
|
13023
|
+
walletId: input.walletId.trim(),
|
|
13024
|
+
walletName: input.walletName.trim(),
|
|
13025
|
+
walletAddress: input.walletAddress.trim(),
|
|
13026
|
+
chain: input.chain.trim(),
|
|
13027
|
+
chainId: input.chainId,
|
|
13028
|
+
payer: {
|
|
13029
|
+
walletId: input.walletId.trim(),
|
|
13030
|
+
walletName: input.walletName.trim(),
|
|
13031
|
+
walletAddress: input.walletAddress.trim(),
|
|
13032
|
+
name: normalizeOptionalString4(input.payerName)
|
|
13033
|
+
},
|
|
13034
|
+
payee: {
|
|
13035
|
+
address: payeeAddress,
|
|
13036
|
+
name: normalizeOptionalString4(input.payeeName)
|
|
13037
|
+
},
|
|
13038
|
+
asset,
|
|
13039
|
+
description: normalizeOptionalString4(input.description),
|
|
13040
|
+
memo: normalizeOptionalString4(input.memo),
|
|
13041
|
+
metadata: normalizeMetadata2(input.metadata),
|
|
13042
|
+
executionPreference: {
|
|
13043
|
+
surface: inferExecutionSurface(asset),
|
|
13044
|
+
paymasterMode: input.paymasterMode ?? "none"
|
|
13045
|
+
},
|
|
13046
|
+
settlement: {
|
|
13047
|
+
status
|
|
13048
|
+
},
|
|
13049
|
+
history: [
|
|
13050
|
+
createPaymentHistoryEvent({
|
|
13051
|
+
type: "created",
|
|
13052
|
+
at: timestamp,
|
|
13053
|
+
status
|
|
13054
|
+
})
|
|
13055
|
+
],
|
|
13056
|
+
createdAt: timestamp,
|
|
13057
|
+
updatedAt: timestamp
|
|
13058
|
+
};
|
|
13059
|
+
}
|
|
13060
|
+
function applyPaymentRequestStatusUpdate(record, input) {
|
|
13061
|
+
const nextStatus = input.status;
|
|
13062
|
+
const allowedTransitions = PAYMENT_REQUEST_STATUS_TRANSITIONS[record.settlement.status];
|
|
13063
|
+
if (!allowedTransitions.includes(nextStatus)) {
|
|
13064
|
+
throw new AgentError(
|
|
13065
|
+
"PAYMENT_STATUS_TRANSITION_INVALID",
|
|
13066
|
+
`Cannot move payment request ${record.requestId} from ${record.settlement.status} to ${nextStatus}.`,
|
|
13067
|
+
{
|
|
13068
|
+
currentStatus: record.settlement.status,
|
|
13069
|
+
nextStatus,
|
|
13070
|
+
allowedTransitions
|
|
13071
|
+
}
|
|
13072
|
+
);
|
|
13073
|
+
}
|
|
13074
|
+
const timestamp = nowIso2();
|
|
13075
|
+
const nextTxHash = normalizeOptionalString4(input.txHash);
|
|
13076
|
+
const nextNote = normalizeOptionalString4(input.note);
|
|
13077
|
+
return {
|
|
13078
|
+
...record,
|
|
13079
|
+
updatedAt: timestamp,
|
|
13080
|
+
settlement: {
|
|
13081
|
+
status: nextStatus,
|
|
13082
|
+
paidAt: nextStatus === "paid" ? timestamp : record.settlement.paidAt,
|
|
13083
|
+
cancelledAt: nextStatus === "cancelled" ? timestamp : record.settlement.cancelledAt,
|
|
13084
|
+
txHash: nextTxHash ?? record.settlement.txHash,
|
|
13085
|
+
note: nextNote ?? record.settlement.note
|
|
13086
|
+
},
|
|
13087
|
+
history: [
|
|
13088
|
+
...record.history,
|
|
13089
|
+
createPaymentHistoryEvent({
|
|
13090
|
+
type: "status-updated",
|
|
13091
|
+
at: timestamp,
|
|
13092
|
+
status: nextStatus,
|
|
13093
|
+
previousStatus: record.settlement.status,
|
|
13094
|
+
txHash: nextTxHash,
|
|
13095
|
+
note: nextNote
|
|
13096
|
+
})
|
|
13097
|
+
]
|
|
13098
|
+
};
|
|
13099
|
+
}
|
|
13100
|
+
|
|
13101
|
+
// ../agent-pay/src/storage.ts
|
|
13102
|
+
var PAYMENT_REQUEST_COLLECTION = "payments";
|
|
13103
|
+
async function savePaymentRequest(record) {
|
|
13104
|
+
await saveEncryptedStorageRecord(
|
|
13105
|
+
PAYMENT_REQUEST_COLLECTION,
|
|
13106
|
+
record.requestId,
|
|
13107
|
+
migratePaymentRequestRecord(record)
|
|
13108
|
+
);
|
|
13109
|
+
}
|
|
13110
|
+
async function loadPaymentRequest(requestId) {
|
|
13111
|
+
const record = await loadEncryptedStorageRecord(
|
|
13112
|
+
PAYMENT_REQUEST_COLLECTION,
|
|
13113
|
+
requestId
|
|
13114
|
+
);
|
|
13115
|
+
return record ? migratePaymentRequestRecord(record) : null;
|
|
13116
|
+
}
|
|
13117
|
+
async function listPaymentRequestIds() {
|
|
13118
|
+
return listEncryptedStorageRecordIds(PAYMENT_REQUEST_COLLECTION);
|
|
13119
|
+
}
|
|
13120
|
+
async function deletePaymentRequest(requestId) {
|
|
13121
|
+
return deleteEncryptedStorageRecord(PAYMENT_REQUEST_COLLECTION, requestId);
|
|
13122
|
+
}
|
|
13123
|
+
async function renamePaymentRequestWalletReferences(options) {
|
|
13124
|
+
const currentName = options.previousWalletName.trim();
|
|
13125
|
+
const targetName = options.nextWalletName.trim();
|
|
13126
|
+
const walletId = options.walletId?.trim();
|
|
13127
|
+
if (!currentName) throw new Error("Current wallet name is required.");
|
|
13128
|
+
if (!targetName) throw new Error("New wallet name is required.");
|
|
13129
|
+
if (currentName === targetName) return [];
|
|
13130
|
+
const updatedRequestIds = [];
|
|
13131
|
+
for (const requestId of await listPaymentRequestIds()) {
|
|
13132
|
+
const paymentRequest = await loadPaymentRequest(requestId);
|
|
13133
|
+
if (!paymentRequest) continue;
|
|
13134
|
+
const matchesWallet = walletId && paymentRequest.walletId ? paymentRequest.walletId === walletId : paymentRequest.walletName === currentName;
|
|
13135
|
+
if (!matchesWallet) continue;
|
|
13136
|
+
if (walletId) {
|
|
13137
|
+
paymentRequest.walletId = walletId;
|
|
13138
|
+
paymentRequest.payer.walletId = walletId;
|
|
13139
|
+
}
|
|
13140
|
+
paymentRequest.walletName = targetName;
|
|
13141
|
+
paymentRequest.payer.walletName = targetName;
|
|
13142
|
+
await savePaymentRequest(paymentRequest);
|
|
13143
|
+
updatedRequestIds.push(requestId);
|
|
13144
|
+
}
|
|
13145
|
+
return updatedRequestIds;
|
|
13146
|
+
}
|
|
13147
|
+
|
|
13148
|
+
// ../agent-pay/src/service.ts
|
|
13149
|
+
async function requirePaymentRequest(requestId) {
|
|
13150
|
+
const record = await loadPaymentRequest(requestId);
|
|
13151
|
+
if (!record) {
|
|
13152
|
+
throw new AgentError(
|
|
13153
|
+
"PAYMENT_REQUEST_NOT_FOUND",
|
|
13154
|
+
`Payment request not found: ${requestId}`
|
|
13155
|
+
);
|
|
13156
|
+
}
|
|
13157
|
+
return record;
|
|
13158
|
+
}
|
|
13159
|
+
async function createStoredPaymentRequest(input) {
|
|
13160
|
+
const paymentRequest = createPaymentRequestRecord(input);
|
|
13161
|
+
await savePaymentRequest(paymentRequest);
|
|
13162
|
+
return {
|
|
13163
|
+
paymentRequest,
|
|
13164
|
+
executionPlan: buildPaymentExecutionPlan(paymentRequest)
|
|
13165
|
+
};
|
|
13166
|
+
}
|
|
13167
|
+
async function getStoredPaymentRequest(requestId) {
|
|
13168
|
+
const paymentRequest = await requirePaymentRequest(requestId);
|
|
13169
|
+
return {
|
|
13170
|
+
paymentRequest,
|
|
13171
|
+
executionPlan: buildPaymentExecutionPlan(paymentRequest)
|
|
13172
|
+
};
|
|
13173
|
+
}
|
|
13174
|
+
async function listStoredPaymentRequests(input = {}) {
|
|
13175
|
+
const requestIds = await listPaymentRequestIds();
|
|
13176
|
+
const requests = [];
|
|
13177
|
+
for (const requestId of requestIds) {
|
|
13178
|
+
const record = await loadPaymentRequest(requestId);
|
|
13179
|
+
if (!record) continue;
|
|
13180
|
+
if (input.walletName && record.walletName !== input.walletName) continue;
|
|
13181
|
+
if (input.status && record.settlement.status !== input.status) continue;
|
|
13182
|
+
requests.push(record);
|
|
13183
|
+
}
|
|
13184
|
+
return requests.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
13185
|
+
}
|
|
13186
|
+
async function updateStoredPaymentRequestStatus(input) {
|
|
13187
|
+
const paymentRequest = await requirePaymentRequest(input.requestId);
|
|
13188
|
+
const updated = applyPaymentRequestStatusUpdate(paymentRequest, input);
|
|
13189
|
+
await savePaymentRequest(updated);
|
|
13190
|
+
return {
|
|
13191
|
+
paymentRequest: updated,
|
|
13192
|
+
executionPlan: buildPaymentExecutionPlan(updated)
|
|
13193
|
+
};
|
|
13194
|
+
}
|
|
13195
|
+
async function removeStoredPaymentRequest(requestId) {
|
|
13196
|
+
return deletePaymentRequest(requestId);
|
|
13197
|
+
}
|
|
13198
|
+
|
|
13199
|
+
// src/commands/payment.ts
|
|
13200
|
+
function parseMetadataEntries2(entries) {
|
|
13201
|
+
const metadata = {};
|
|
13202
|
+
for (const entry of entries) {
|
|
13203
|
+
const separatorIndex = entry.indexOf("=");
|
|
13204
|
+
if (separatorIndex <= 0 || separatorIndex === entry.length - 1) {
|
|
13205
|
+
throw new AgentError(
|
|
13206
|
+
"PAYMENT_METADATA_INVALID",
|
|
13207
|
+
`Invalid metadata entry: ${entry}. Use key=value.`
|
|
13208
|
+
);
|
|
13209
|
+
}
|
|
13210
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
13211
|
+
const value = entry.slice(separatorIndex + 1).trim();
|
|
13212
|
+
if (!key || !value) {
|
|
13213
|
+
throw new AgentError(
|
|
13214
|
+
"PAYMENT_METADATA_INVALID",
|
|
13215
|
+
`Invalid metadata entry: ${entry}. Use key=value.`
|
|
13216
|
+
);
|
|
13217
|
+
}
|
|
13218
|
+
metadata[key] = value;
|
|
13219
|
+
}
|
|
13220
|
+
return metadata;
|
|
13221
|
+
}
|
|
13222
|
+
function resolvePaymentStatus(value) {
|
|
13223
|
+
const normalized = value?.trim().toLowerCase();
|
|
13224
|
+
if (!normalized) return "ready";
|
|
13225
|
+
if (normalized === "draft" || normalized === "ready" || normalized === "paid" || normalized === "cancelled") {
|
|
13226
|
+
return normalized;
|
|
13227
|
+
}
|
|
13228
|
+
throw new AgentError(
|
|
13229
|
+
"PAYMENT_STATUS_INVALID",
|
|
13230
|
+
`Unsupported payment status: ${value}. Use draft, ready, paid, or cancelled.`
|
|
13231
|
+
);
|
|
13232
|
+
}
|
|
13233
|
+
function resolvePaymasterMode2(value) {
|
|
13234
|
+
const normalized = value?.trim().toLowerCase();
|
|
13235
|
+
if (!normalized) return void 0;
|
|
13236
|
+
if (normalized === "none" || normalized === "sponsored" || normalized === "approval-based") {
|
|
13237
|
+
return normalized;
|
|
13238
|
+
}
|
|
13239
|
+
throw new AgentError(
|
|
13240
|
+
"PAYMENT_PAYMASTER_MODE_INVALID",
|
|
13241
|
+
`Unsupported paymaster mode: ${value}. Use none, sponsored, or approval-based.`
|
|
13242
|
+
);
|
|
13243
|
+
}
|
|
13244
|
+
function buildPaymentRequestId(value) {
|
|
13245
|
+
const trimmed = value?.trim();
|
|
13246
|
+
if (trimmed) return trimmed;
|
|
13247
|
+
return `payreq-${randomBytes5(4).toString("hex")}`;
|
|
13248
|
+
}
|
|
13249
|
+
function formatPaymentAsset(record) {
|
|
13250
|
+
const symbol = record.asset.kind === "native" ? record.asset.symbol || "native" : record.asset.symbol || record.asset.tokenAddress || "erc20";
|
|
13251
|
+
return `${record.asset.amount} ${symbol}`;
|
|
13252
|
+
}
|
|
13253
|
+
function buildPaymentExecuteCommand(plan) {
|
|
13254
|
+
if (plan.asset.kind === "native") {
|
|
13255
|
+
return buildWorkflowPayRecommendedCommand(
|
|
13256
|
+
plan.walletName,
|
|
13257
|
+
plan.paymasterMode
|
|
13258
|
+
).replace("--to <address>", `--to ${plan.payeeAddress}`).replace("--amount <amount>", `--amount ${plan.asset.amount}`);
|
|
13259
|
+
}
|
|
13260
|
+
return buildSendTokenRecommendedCommand({
|
|
13261
|
+
walletName: plan.walletName,
|
|
13262
|
+
to: plan.payeeAddress,
|
|
13263
|
+
amount: plan.asset.amount,
|
|
13264
|
+
tokenAddress: plan.asset.tokenAddress,
|
|
13265
|
+
symbol: plan.asset.symbol,
|
|
13266
|
+
decimals: plan.asset.decimals,
|
|
13267
|
+
paymasterMode: plan.paymasterMode
|
|
13268
|
+
});
|
|
13269
|
+
}
|
|
13270
|
+
function buildPaymentRecommendedCommands(record, executionPlan) {
|
|
13271
|
+
return {
|
|
13272
|
+
list: buildPaymentListRecommendedCommand(),
|
|
13273
|
+
show: buildPaymentShowRecommendedCommand(record.requestId),
|
|
13274
|
+
execute: buildPaymentExecuteCommand(executionPlan),
|
|
13275
|
+
...record.settlement.status === "draft" ? {
|
|
13276
|
+
markReady: buildPaymentSetStatusRecommendedCommand(record.requestId, "ready"),
|
|
13277
|
+
cancel: buildPaymentSetStatusRecommendedCommand(record.requestId, "cancelled")
|
|
13278
|
+
} : {},
|
|
13279
|
+
...record.settlement.status === "ready" ? {
|
|
13280
|
+
markDraft: buildPaymentSetStatusRecommendedCommand(record.requestId, "draft"),
|
|
13281
|
+
markPaid: buildPaymentSetStatusRecommendedCommand(
|
|
13282
|
+
record.requestId,
|
|
13283
|
+
"paid",
|
|
13284
|
+
"<tx-hash>"
|
|
13285
|
+
),
|
|
13286
|
+
cancel: buildPaymentSetStatusRecommendedCommand(record.requestId, "cancelled")
|
|
13287
|
+
} : {},
|
|
13288
|
+
remove: buildPaymentRemoveRecommendedCommand(record.requestId)
|
|
13289
|
+
};
|
|
13290
|
+
}
|
|
13291
|
+
function paymentRequestLines(record, executionPlan) {
|
|
13292
|
+
const lines = [
|
|
13293
|
+
["request", record.requestId],
|
|
13294
|
+
["status", record.settlement.status],
|
|
13295
|
+
["wallet", record.walletName],
|
|
13296
|
+
["chain", `${record.chain} (${record.chainId})`],
|
|
13297
|
+
["payer", `${record.payer.name || record.payer.walletName} ${record.payer.walletAddress}`],
|
|
13298
|
+
["payee", `${record.payee.name || "payee"} ${record.payee.address}`],
|
|
13299
|
+
["asset", formatPaymentAsset(record)],
|
|
13300
|
+
["execution surface", record.executionPreference.surface],
|
|
13301
|
+
["paymaster mode", record.executionPreference.paymasterMode],
|
|
13302
|
+
["execute", buildPaymentExecuteCommand(executionPlan)],
|
|
13303
|
+
["show", buildPaymentShowRecommendedCommand(record.requestId)],
|
|
13304
|
+
["remove", buildPaymentRemoveRecommendedCommand(record.requestId)]
|
|
13305
|
+
];
|
|
13306
|
+
if (record.description) lines.splice(7, 0, ["description", record.description]);
|
|
13307
|
+
if (record.memo) lines.splice(record.description ? 8 : 7, 0, ["memo", record.memo]);
|
|
13308
|
+
if (record.settlement.txHash) lines.push(["txHash", record.settlement.txHash]);
|
|
13309
|
+
if (record.settlement.note) lines.push(["note", record.settlement.note]);
|
|
13310
|
+
if (record.settlement.paidAt) lines.push(["paid at", record.settlement.paidAt]);
|
|
13311
|
+
if (record.settlement.cancelledAt) lines.push(["cancelled at", record.settlement.cancelledAt]);
|
|
13312
|
+
lines.push(["history events", String(record.history.length)]);
|
|
13313
|
+
lines.push(["metadata keys", String(Object.keys(record.metadata).length)]);
|
|
13314
|
+
return lines;
|
|
13315
|
+
}
|
|
13316
|
+
function buildPaymentExecutionPlanJson(plan) {
|
|
13317
|
+
return {
|
|
13318
|
+
...plan,
|
|
13319
|
+
command: buildPaymentExecuteCommand(plan)
|
|
13320
|
+
};
|
|
13321
|
+
}
|
|
13322
|
+
function buildPaymentListSummary(record) {
|
|
13323
|
+
return `${record.requestId} ${record.settlement.status} ${formatPaymentAsset(record)} -> ${record.payee.address} (${record.walletName})`;
|
|
13324
|
+
}
|
|
13325
|
+
function createPaymentCommand() {
|
|
13326
|
+
const payment = new Command7("payment").description(
|
|
13327
|
+
"Manage local-first Agent Pay request records separately from the execution-layer workflow and send commands"
|
|
13328
|
+
);
|
|
13329
|
+
payment.addHelpText(
|
|
13330
|
+
"after",
|
|
13331
|
+
[
|
|
13332
|
+
"",
|
|
13333
|
+
" Payment request surface:",
|
|
13334
|
+
" Use this layer to capture payer/payee intent and local settlement state before or after execution.",
|
|
13335
|
+
" `workflow pay` and `send-token` still execute the transfer; `payment` stores the request record and status lifecycle.",
|
|
13336
|
+
"",
|
|
13337
|
+
" First platform path:",
|
|
13338
|
+
" zk-agent payment create --wallet main --to <address> --amount <amount>",
|
|
13339
|
+
" zk-agent payment show --request-id <id>",
|
|
13340
|
+
" zk-agent payment set-status --request-id <id> --status paid --tx-hash <tx-hash>",
|
|
13341
|
+
"",
|
|
13342
|
+
" ERC-20 request path:",
|
|
13343
|
+
" zk-agent payment create --wallet main --to <address> --amount <amount> --symbol USDC",
|
|
13344
|
+
"",
|
|
13345
|
+
" Stored request management:",
|
|
13346
|
+
" zk-agent payment list",
|
|
13347
|
+
" zk-agent payment remove --request-id <id>"
|
|
13348
|
+
].join("\n")
|
|
13349
|
+
);
|
|
13350
|
+
payment.command("create").description("Create a local payment request record for native value or an ERC-20 transfer").option("--wallet <name>", "Stored payer wallet name", "main").requiredOption("--to <address>", "Payee address").requiredOption("--amount <value>", "Amount in human-readable units").option("--token <address>", "ERC-20 token contract address").option("--symbol <symbol>", "ERC-20 token symbol for registry-backed resolution").option("--decimals <value>", "ERC-20 token decimals when registry metadata is unavailable").option("--payee-name <name>", "Optional payee display name").option("--payer-name <name>", "Optional payer display name").option("--description <text>", "Short payment description").option("--memo <text>", "Optional memo or invoice reference").option("--metadata <key=value>", "Additional payment metadata", collectRepeatedString2, []).option("--paymaster-mode <mode>", "Optional execution preference: none, sponsored, or approval-based").option("--status <status>", "Initial local payment status: draft, ready, paid, or cancelled").option("--request-id <id>", "Optional explicit payment request id").action(async (options) => {
|
|
13351
|
+
const wallet = await loadWalletSession(options.wallet);
|
|
13352
|
+
if (!wallet) {
|
|
13353
|
+
throw new AgentError("PAYMENT_WALLET_NOT_FOUND", `Wallet not found: ${options.wallet}`);
|
|
13354
|
+
}
|
|
13355
|
+
if (!wallet.walletId) {
|
|
13356
|
+
throw new AgentError(
|
|
13357
|
+
"WALLET_ID_MISSING",
|
|
13358
|
+
`Wallet ${wallet.walletName} is missing a stable walletId. Re-save or reapprove the wallet session before creating a payment request.`
|
|
13359
|
+
);
|
|
13360
|
+
}
|
|
13361
|
+
const paymasterMode = resolvePaymasterMode2(options.paymasterMode) ?? wallet.paymasterMode ?? "none";
|
|
13362
|
+
const status = resolvePaymentStatus(options.status);
|
|
13363
|
+
const metadata = parseMetadataEntries2(options.metadata);
|
|
13364
|
+
const requestId = buildPaymentRequestId(options.requestId);
|
|
13365
|
+
const hasTokenInput = Boolean(options.token?.trim() || options.symbol?.trim());
|
|
13366
|
+
const asset = hasTokenInput ? await resolveRequiredTokenInput({
|
|
13367
|
+
tokenAddress: options.token,
|
|
13368
|
+
symbol: options.symbol,
|
|
13369
|
+
decimals: options.decimals,
|
|
13370
|
+
chain: wallet.chain,
|
|
13371
|
+
tokenOptionLabel: "--token",
|
|
13372
|
+
symbolOptionLabel: "--symbol",
|
|
13373
|
+
decimalsOptionLabel: "--decimals"
|
|
13374
|
+
}).then((token) => ({
|
|
13375
|
+
kind: "erc20",
|
|
13376
|
+
amount: options.amount,
|
|
13377
|
+
tokenAddress: token.address,
|
|
13378
|
+
decimals: token.decimals,
|
|
13379
|
+
symbol: token.symbol
|
|
13380
|
+
})) : {
|
|
13381
|
+
kind: "native",
|
|
13382
|
+
amount: options.amount
|
|
13383
|
+
};
|
|
13384
|
+
const result = await createStoredPaymentRequest({
|
|
13385
|
+
requestId,
|
|
13386
|
+
walletId: wallet.walletId,
|
|
13387
|
+
walletName: wallet.walletName,
|
|
13388
|
+
walletAddress: wallet.walletAddress,
|
|
13389
|
+
chain: wallet.chain,
|
|
13390
|
+
chainId: wallet.chainId,
|
|
13391
|
+
payerName: options.payerName,
|
|
13392
|
+
payeeAddress: options.to,
|
|
13393
|
+
payeeName: options.payeeName,
|
|
13394
|
+
asset,
|
|
13395
|
+
description: options.description,
|
|
13396
|
+
memo: options.memo,
|
|
13397
|
+
metadata,
|
|
13398
|
+
paymasterMode,
|
|
13399
|
+
status
|
|
13400
|
+
});
|
|
13401
|
+
printResult(paymentRequestLines(result.paymentRequest, result.executionPlan), {
|
|
13402
|
+
ok: true,
|
|
13403
|
+
paymentRequest: result.paymentRequest,
|
|
13404
|
+
executionPlan: buildPaymentExecutionPlanJson(result.executionPlan),
|
|
13405
|
+
recommendedCommands: buildPaymentRecommendedCommands(
|
|
13406
|
+
result.paymentRequest,
|
|
13407
|
+
result.executionPlan
|
|
13408
|
+
)
|
|
13409
|
+
});
|
|
13410
|
+
});
|
|
13411
|
+
payment.command("list").description("List stored local payment request records").option("--wallet <name>", "Optional payer wallet filter").option("--status <status>", "Optional status filter: draft, ready, paid, or cancelled").action(async (options) => {
|
|
13412
|
+
const statusFilter = options.status ? resolvePaymentStatus(options.status) : void 0;
|
|
13413
|
+
const requests = await listStoredPaymentRequests({
|
|
13414
|
+
walletName: options.wallet,
|
|
13415
|
+
status: statusFilter
|
|
13416
|
+
});
|
|
13417
|
+
printResult(
|
|
13418
|
+
requests.length > 0 ? requests.flatMap((record) => [
|
|
13419
|
+
["payment", buildPaymentListSummary(record)],
|
|
13420
|
+
["show", buildPaymentShowRecommendedCommand(record.requestId)]
|
|
13421
|
+
]) : [
|
|
13422
|
+
["status", "No stored payment requests"],
|
|
13423
|
+
["next", "zk-agent payment create --wallet main --to <address> --amount <amount>"]
|
|
13424
|
+
],
|
|
13425
|
+
{
|
|
13426
|
+
ok: true,
|
|
13427
|
+
count: requests.length,
|
|
13428
|
+
filters: {
|
|
13429
|
+
walletName: options.wallet || null,
|
|
13430
|
+
status: statusFilter || null
|
|
13431
|
+
},
|
|
13432
|
+
requests,
|
|
13433
|
+
recommendedCommands: requests.length === 0 ? {
|
|
13434
|
+
create: "zk-agent payment create --wallet main --to <address> --amount <amount>"
|
|
13435
|
+
} : {
|
|
13436
|
+
list: buildPaymentListRecommendedCommand()
|
|
13437
|
+
}
|
|
13438
|
+
}
|
|
13439
|
+
);
|
|
13440
|
+
});
|
|
13441
|
+
payment.command("show").description("Show one stored payment request record").requiredOption("--request-id <id>", "Stored payment request id").action(async (options) => {
|
|
13442
|
+
const result = await getStoredPaymentRequest(options.requestId);
|
|
13443
|
+
printResult(paymentRequestLines(result.paymentRequest, result.executionPlan), {
|
|
13444
|
+
ok: true,
|
|
13445
|
+
paymentRequest: result.paymentRequest,
|
|
13446
|
+
executionPlan: buildPaymentExecutionPlanJson(result.executionPlan),
|
|
13447
|
+
recommendedCommands: buildPaymentRecommendedCommands(
|
|
13448
|
+
result.paymentRequest,
|
|
13449
|
+
result.executionPlan
|
|
13450
|
+
)
|
|
13451
|
+
});
|
|
13452
|
+
});
|
|
13453
|
+
payment.command("set-status").description("Update the local settlement status of one stored payment request").requiredOption("--request-id <id>", "Stored payment request id").requiredOption("--status <status>", "Next status: draft, ready, paid, or cancelled").option("--tx-hash <hash>", "Optional settlement transaction hash").option("--note <text>", "Optional operator note for the status update").action(async (options) => {
|
|
13454
|
+
const result = await updateStoredPaymentRequestStatus({
|
|
13455
|
+
requestId: options.requestId,
|
|
13456
|
+
status: resolvePaymentStatus(options.status),
|
|
13457
|
+
txHash: options.txHash,
|
|
13458
|
+
note: options.note
|
|
13459
|
+
});
|
|
13460
|
+
printResult(paymentRequestLines(result.paymentRequest, result.executionPlan), {
|
|
13461
|
+
ok: true,
|
|
13462
|
+
paymentRequest: result.paymentRequest,
|
|
13463
|
+
executionPlan: buildPaymentExecutionPlanJson(result.executionPlan),
|
|
13464
|
+
recommendedCommands: buildPaymentRecommendedCommands(
|
|
13465
|
+
result.paymentRequest,
|
|
13466
|
+
result.executionPlan
|
|
13467
|
+
)
|
|
13468
|
+
});
|
|
13469
|
+
});
|
|
13470
|
+
payment.command("remove").description("Delete one stored payment request record").requiredOption("--request-id <id>", "Stored payment request id").action(async (options) => {
|
|
13471
|
+
const removed = await removeStoredPaymentRequest(options.requestId);
|
|
13472
|
+
if (!removed) {
|
|
13473
|
+
throw new AgentError(
|
|
13474
|
+
"PAYMENT_REQUEST_NOT_FOUND",
|
|
13475
|
+
`Payment request not found: ${options.requestId}`
|
|
13476
|
+
);
|
|
13477
|
+
}
|
|
13478
|
+
printResult(
|
|
13479
|
+
[
|
|
13480
|
+
["status", "Payment request removed"],
|
|
13481
|
+
["request", options.requestId],
|
|
13482
|
+
["next", buildPaymentListRecommendedCommand()]
|
|
13483
|
+
],
|
|
13484
|
+
{
|
|
13485
|
+
ok: true,
|
|
13486
|
+
requestId: options.requestId,
|
|
13487
|
+
removed: true,
|
|
13488
|
+
recommendedCommands: {
|
|
13489
|
+
list: buildPaymentListRecommendedCommand(),
|
|
13490
|
+
create: "zk-agent payment create --wallet main --to <address> --amount <amount>"
|
|
13491
|
+
}
|
|
13492
|
+
}
|
|
13493
|
+
);
|
|
13494
|
+
});
|
|
13495
|
+
return payment;
|
|
13496
|
+
}
|
|
13497
|
+
function collectRepeatedString2(value, previous) {
|
|
13498
|
+
return [...previous, value];
|
|
13499
|
+
}
|
|
13500
|
+
|
|
13501
|
+
// src/commands/resolve-token.ts
|
|
13502
|
+
import { Command as Command8 } from "commander";
|
|
12843
13503
|
function resolveResolveTokenCommandDeps(deps) {
|
|
12844
13504
|
return {
|
|
12845
13505
|
loadWallet: deps?.loadWallet ?? (async (walletName) => {
|
|
@@ -12897,7 +13557,7 @@ function buildResolveTokenDiscoverySummary(result) {
|
|
|
12897
13557
|
}
|
|
12898
13558
|
function createResolveTokenCommand(deps) {
|
|
12899
13559
|
const resolvedDeps = resolveResolveTokenCommandDeps(deps);
|
|
12900
|
-
return new
|
|
13560
|
+
return new Command8("resolve-token").description("Resolve a token symbol or address against the configured local-first token registry").addHelpText(
|
|
12901
13561
|
"after",
|
|
12902
13562
|
[
|
|
12903
13563
|
"",
|
|
@@ -13031,7 +13691,7 @@ function normalizeSource(value) {
|
|
|
13031
13691
|
}
|
|
13032
13692
|
|
|
13033
13693
|
// src/commands/suite.ts
|
|
13034
|
-
import { Command as
|
|
13694
|
+
import { Command as Command9 } from "commander";
|
|
13035
13695
|
|
|
13036
13696
|
// src/lib/operator-suite.ts
|
|
13037
13697
|
function buildOperatorSuitePayload(options = {}) {
|
|
@@ -13219,6 +13879,13 @@ function buildOperatorSuitePayload(options = {}) {
|
|
|
13219
13879
|
entryIds: ["hosted-approval-recovery"]
|
|
13220
13880
|
}
|
|
13221
13881
|
];
|
|
13882
|
+
const recommendedJourney = {
|
|
13883
|
+
id: journeys[0].id,
|
|
13884
|
+
title: journeys[0].title,
|
|
13885
|
+
startCommand: journeys[0].startCommand,
|
|
13886
|
+
surface: journeys[0].surface,
|
|
13887
|
+
useWhen: journeys[0].useWhen
|
|
13888
|
+
};
|
|
13222
13889
|
return {
|
|
13223
13890
|
ok: true,
|
|
13224
13891
|
summary: {
|
|
@@ -13229,6 +13896,7 @@ function buildOperatorSuitePayload(options = {}) {
|
|
|
13229
13896
|
stage: "wallet-ready-post-flagship",
|
|
13230
13897
|
useWhen: "Use suite after wallet readiness when you want one packaged surface for flagship pay plus the current post-flagship discovery, paymaster, funding, and hosted recovery slices.",
|
|
13231
13898
|
entryModes: ["local-first", "hosted-recovery"],
|
|
13899
|
+
startHereJourneyId: recommendedJourney.id,
|
|
13232
13900
|
journeyOrder: journeys.map((entry) => entry.id),
|
|
13233
13901
|
surfaceOrder: ["workflow", "discovery", "relay"],
|
|
13234
13902
|
categoryOrder: [flagship.category, ...slices.map((entry) => entry.category)],
|
|
@@ -13238,6 +13906,7 @@ function buildOperatorSuitePayload(options = {}) {
|
|
|
13238
13906
|
nextAction: flagship.primaryCommand
|
|
13239
13907
|
},
|
|
13240
13908
|
...preflight ? { preflight } : {},
|
|
13909
|
+
recommendedJourney,
|
|
13241
13910
|
journeys,
|
|
13242
13911
|
surfaces,
|
|
13243
13912
|
flagship,
|
|
@@ -13294,6 +13963,10 @@ function operatorSuiteLines(payload) {
|
|
|
13294
13963
|
["stage", payload.summary.stage],
|
|
13295
13964
|
["use when", payload.summary.useWhen],
|
|
13296
13965
|
["entry modes", payload.summary.entryModes.join(" -> ")],
|
|
13966
|
+
["start here journey", payload.summary.startHereJourneyId],
|
|
13967
|
+
["start here", payload.recommendedJourney.startCommand],
|
|
13968
|
+
["start here surface", payload.recommendedJourney.surface],
|
|
13969
|
+
["start here when", payload.recommendedJourney.useWhen],
|
|
13297
13970
|
["journey order", payload.summary.journeyOrder.join(" -> ")],
|
|
13298
13971
|
["surface order", payload.summary.surfaceOrder.join(" -> ")],
|
|
13299
13972
|
["category order", payload.summary.categoryOrder.join(" -> ")],
|
|
@@ -13320,7 +13993,7 @@ function operatorSuiteLines(payload) {
|
|
|
13320
13993
|
|
|
13321
13994
|
// src/commands/suite.ts
|
|
13322
13995
|
function createSuiteCommand() {
|
|
13323
|
-
return new
|
|
13996
|
+
return new Command9("suite").description("Show the flagship and post-flagship zkSync-native operator suite").option("--wallet <name>", "Wallet name used in example commands", "main").option("--chain <chain>", "Chain key used in example commands", "zksync-sepolia").option("--include-onboarding", "Include the first-run preflight and wallet-bootstrap map", false).addHelpText(
|
|
13324
13997
|
"after",
|
|
13325
13998
|
[
|
|
13326
13999
|
"",
|
|
@@ -13340,6 +14013,9 @@ function createSuiteCommand() {
|
|
|
13340
14013
|
" unstick a write: recover paymaster/funding readiness on the workflow path",
|
|
13341
14014
|
" recover remote approval: move approval to the hosted relay path",
|
|
13342
14015
|
"",
|
|
14016
|
+
" If you only need one default starting point inside suite:",
|
|
14017
|
+
" send value now",
|
|
14018
|
+
"",
|
|
13343
14019
|
" Where `suite` hands you off next:",
|
|
13344
14020
|
" workflow: flagship pay, approval-based pay, and funding recovery",
|
|
13345
14021
|
" discovery: assets, defaults, and token inspection",
|
|
@@ -13360,11 +14036,12 @@ function createSuiteCommand() {
|
|
|
13360
14036
|
" guidance in the same packaged readout.",
|
|
13361
14037
|
"",
|
|
13362
14038
|
" In JSON mode, `summary.catalogView`, `summary.entryModes`,",
|
|
13363
|
-
" `summary.
|
|
13364
|
-
" top-level `
|
|
13365
|
-
"
|
|
13366
|
-
" `
|
|
13367
|
-
"
|
|
14039
|
+
" `summary.startHereJourneyId`, `summary.journeyOrder`,",
|
|
14040
|
+
" `summary.surfaceOrder`, top-level `recommendedJourney`, top-level",
|
|
14041
|
+
" `journeys[]`, top-level `surfaces[]`, `summary.categoryOrder`,",
|
|
14042
|
+
" `summary.recommendedOrder`, optional `preflight`, and each entry",
|
|
14043
|
+
" `category` + `surface` + `surfaceCommand` + `useWhen` field explain",
|
|
14044
|
+
" which slice to choose and which deeper surface owns it next.",
|
|
13368
14045
|
" `recommendedCommands.workflowSurface|discoverySurface|relaySurface`",
|
|
13369
14046
|
" expose the direct deeper-surface entry commands."
|
|
13370
14047
|
].join("\n")
|
|
@@ -13379,7 +14056,7 @@ function createSuiteCommand() {
|
|
|
13379
14056
|
}
|
|
13380
14057
|
|
|
13381
14058
|
// src/commands/tokens.ts
|
|
13382
|
-
import { Command as
|
|
14059
|
+
import { Command as Command10 } from "commander";
|
|
13383
14060
|
var provider2 = new ZkSyncWalletProvider();
|
|
13384
14061
|
function resolveTokensCommandDeps(deps) {
|
|
13385
14062
|
return {
|
|
@@ -13509,7 +14186,7 @@ function buildTokenDiscoverySummary(result) {
|
|
|
13509
14186
|
}
|
|
13510
14187
|
function createTokensCommand(deps) {
|
|
13511
14188
|
const resolvedDeps = resolveTokensCommandDeps(deps);
|
|
13512
|
-
return new
|
|
14189
|
+
return new Command10("tokens").description("List discoverable tokens from the configured local-first token registry, or inspect the owned ERC-20 registry subset for one wallet").addHelpText(
|
|
13513
14190
|
"after",
|
|
13514
14191
|
[
|
|
13515
14192
|
"",
|
|
@@ -13714,7 +14391,7 @@ function normalizeRole2(value) {
|
|
|
13714
14391
|
}
|
|
13715
14392
|
|
|
13716
14393
|
// src/commands/relay.ts
|
|
13717
|
-
import { Command as
|
|
14394
|
+
import { Command as Command11 } from "commander";
|
|
13718
14395
|
|
|
13719
14396
|
// src/lib/relay.ts
|
|
13720
14397
|
import { createServer } from "node:http";
|
|
@@ -14579,7 +15256,7 @@ function buildRelayInspectPayload(relayUrl, rawHealth) {
|
|
|
14579
15256
|
};
|
|
14580
15257
|
}
|
|
14581
15258
|
function createRelayCommand() {
|
|
14582
|
-
const relay = new
|
|
15259
|
+
const relay = new Command11("relay").description(
|
|
14583
15260
|
"Serve and inspect the single-host connector relay baseline for hosted approval"
|
|
14584
15261
|
);
|
|
14585
15262
|
relay.addHelpText(
|
|
@@ -14841,7 +15518,7 @@ function createRelayCommand() {
|
|
|
14841
15518
|
// src/commands/wallet.ts
|
|
14842
15519
|
import { createServer as createServer2 } from "node:http";
|
|
14843
15520
|
import { createInterface } from "node:readline/promises";
|
|
14844
|
-
import { Command as
|
|
15521
|
+
import { Command as Command12 } from "commander";
|
|
14845
15522
|
|
|
14846
15523
|
// ../account-profiles/src/profiles.ts
|
|
14847
15524
|
import fs8 from "node:fs";
|
|
@@ -15426,8 +16103,9 @@ function stripSensitiveWalletRecord(wallet) {
|
|
|
15426
16103
|
};
|
|
15427
16104
|
}
|
|
15428
16105
|
function sanitizeWalletRecord(wallet) {
|
|
16106
|
+
const { walletId: _walletId, ...rest } = stripSensitiveWalletRecord(wallet);
|
|
15429
16107
|
return {
|
|
15430
|
-
...
|
|
16108
|
+
...rest,
|
|
15431
16109
|
sessionPayload: sanitizeSessionPayload(wallet.sessionPayload)
|
|
15432
16110
|
};
|
|
15433
16111
|
}
|
|
@@ -17508,32 +18186,32 @@ async function printBuiltinSmartAccountProfiles() {
|
|
|
17508
18186
|
}
|
|
17509
18187
|
function createWalletCommand(deps) {
|
|
17510
18188
|
const resolvedDeps = resolveWalletCommandDeps(deps);
|
|
17511
|
-
const wallet = new
|
|
18189
|
+
const wallet = new Command12("wallet").description(
|
|
17512
18190
|
"Create, inspect, and recover local-first wallet sessions"
|
|
17513
18191
|
);
|
|
17514
|
-
const request = new
|
|
17515
|
-
const signer = new
|
|
18192
|
+
const request = new Command12("request").description("Inspect and finalize pending wallet requests");
|
|
18193
|
+
const signer = new Command12("signer").description(
|
|
17516
18194
|
"Inspect and manage the stored local execution signer for a wallet"
|
|
17517
18195
|
);
|
|
17518
|
-
const smartAccount = new
|
|
18196
|
+
const smartAccount = new Command12("smart-account").description(
|
|
17519
18197
|
"Predict and deploy zkSync smart-account contracts from a supplied artifact or built-in profile"
|
|
17520
18198
|
);
|
|
17521
|
-
const sedLite = new
|
|
18199
|
+
const sedLite = new Command12("sed-lite").description(
|
|
17522
18200
|
"Inspect and manage the SED modular smart-account profile"
|
|
17523
18201
|
);
|
|
17524
|
-
const nativeCapHook = new
|
|
18202
|
+
const nativeCapHook = new Command12("native-cap-hook").description(
|
|
17525
18203
|
"Inspect and manage the first SED Lite validation-hook policy: native per-transaction spend caps"
|
|
17526
18204
|
);
|
|
17527
|
-
const targetAllowlistHook = new
|
|
18205
|
+
const targetAllowlistHook = new Command12("target-allowlist-hook").description(
|
|
17528
18206
|
"Inspect and manage the SED Lite validation-hook policy that restricts transactions to an allowlisted target set"
|
|
17529
18207
|
);
|
|
17530
|
-
const selectorAllowlistHook = new
|
|
18208
|
+
const selectorAllowlistHook = new Command12("selector-allowlist-hook").description(
|
|
17531
18209
|
"Inspect and manage the SED Lite validation-hook policy that restricts contract calls to allowlisted target and selector pairs"
|
|
17532
18210
|
);
|
|
17533
|
-
const dailySpendLimit = new
|
|
18211
|
+
const dailySpendLimit = new Command12("daily-spend-limit").description(
|
|
17534
18212
|
"Read and update the native-token daily spend limit used by the built-in daily-spend-limit smart-account profile"
|
|
17535
18213
|
);
|
|
17536
|
-
const paymaster = new
|
|
18214
|
+
const paymaster = new Command12("paymaster").description(
|
|
17537
18215
|
"Manage saved paymaster defaults for stored wallets"
|
|
17538
18216
|
);
|
|
17539
18217
|
wallet.addHelpText(
|
|
@@ -18041,6 +18719,13 @@ function createWalletCommand(deps) {
|
|
|
18041
18719
|
wallet.command("list").description("List stored wallets").action(async () => printWalletList());
|
|
18042
18720
|
wallet.command("rename").description("Rename a stored wallet and update any local pending requests that reference it").option("--name <name>", "Current wallet name", "main").requiredOption("--new-name <name>", "New wallet name").action(async (options) => {
|
|
18043
18721
|
const result = await renameWalletSession(options.name, options.newName);
|
|
18722
|
+
const updatedPaymentRequestIds = await renamePaymentRequestWalletReferences(
|
|
18723
|
+
{
|
|
18724
|
+
walletId: result.wallet.walletId,
|
|
18725
|
+
previousWalletName: options.name,
|
|
18726
|
+
nextWalletName: options.newName
|
|
18727
|
+
}
|
|
18728
|
+
);
|
|
18044
18729
|
printResult(
|
|
18045
18730
|
[
|
|
18046
18731
|
["status", "Wallet renamed"],
|
|
@@ -18048,6 +18733,7 @@ function createWalletCommand(deps) {
|
|
|
18048
18733
|
["to", result.wallet.walletName],
|
|
18049
18734
|
["address", result.wallet.walletAddress],
|
|
18050
18735
|
["requests updated", String(result.updatedRequestIds.length)],
|
|
18736
|
+
["payment requests updated", String(updatedPaymentRequestIds.length)],
|
|
18051
18737
|
["workflow checkpoints updated", String(result.updatedWorkflowRequestIds.length)],
|
|
18052
18738
|
...walletFollowUpLines(result.wallet)
|
|
18053
18739
|
],
|
|
@@ -18057,6 +18743,7 @@ function createWalletCommand(deps) {
|
|
|
18057
18743
|
previousWalletName: options.name,
|
|
18058
18744
|
wallet: sanitizeWalletRecord(result.wallet),
|
|
18059
18745
|
updatedRequestIds: result.updatedRequestIds,
|
|
18746
|
+
updatedPaymentRequestIds,
|
|
18060
18747
|
updatedWorkflowRequestIds: result.updatedWorkflowRequestIds,
|
|
18061
18748
|
recommendedCommands: buildWalletFollowUpRecommendedCommands(result.wallet)
|
|
18062
18749
|
}
|
|
@@ -20182,8 +20869,8 @@ function createWalletCommand(deps) {
|
|
|
20182
20869
|
}
|
|
20183
20870
|
|
|
20184
20871
|
// src/commands/workflow.ts
|
|
20185
|
-
import { randomBytes as
|
|
20186
|
-
import { Command as
|
|
20872
|
+
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
20873
|
+
import { Command as Command13 } from "commander";
|
|
20187
20874
|
var defaultProvider2 = new ZkSyncWalletProvider();
|
|
20188
20875
|
var defaultDefiProvider2 = new ZkSyncDefiProvider({
|
|
20189
20876
|
walletWriter: defaultProvider2
|
|
@@ -20250,7 +20937,7 @@ function parseBooleanString(value, label) {
|
|
|
20250
20937
|
throw new Error(`${label} must be true or false`);
|
|
20251
20938
|
}
|
|
20252
20939
|
function generateWorkflowRequestId() {
|
|
20253
|
-
return
|
|
20940
|
+
return randomBytes6(4).toString("hex");
|
|
20254
20941
|
}
|
|
20255
20942
|
async function reserveWorkflowRequestId(requestId) {
|
|
20256
20943
|
const explicit = requestId?.trim();
|
|
@@ -21956,7 +22643,7 @@ function applyWorkflowHelpCommandOrder(workflow) {
|
|
|
21956
22643
|
}
|
|
21957
22644
|
function createWorkflowCommand(deps) {
|
|
21958
22645
|
const resolvedDeps = resolveWorkflowCommandDeps(deps);
|
|
21959
|
-
const workflow = new
|
|
22646
|
+
const workflow = new Command13("workflow").description(
|
|
21960
22647
|
"Plan, persist, and execute higher-level wallet workflows"
|
|
21961
22648
|
);
|
|
21962
22649
|
workflow.addHelpText("after", buildWorkflowHelpText());
|
|
@@ -22644,10 +23331,18 @@ function buildDefaultOperatorPathHelpText() {
|
|
|
22644
23331
|
" zk-agent suite",
|
|
22645
23332
|
" zk-agent suite --include-onboarding",
|
|
22646
23333
|
"",
|
|
23334
|
+
"First local Agent Pay primitive:",
|
|
23335
|
+
" zk-agent payment create --wallet main --to <address> --amount <amount>",
|
|
23336
|
+
" zk-agent payment list",
|
|
23337
|
+
"",
|
|
22647
23338
|
"Product routing by operator question:",
|
|
22648
23339
|
" next -> bootstrap | recover | operate | workflow",
|
|
22649
23340
|
" suite -> operate | discover | pay | fund | recover",
|
|
22650
23341
|
"",
|
|
23342
|
+
"Payment-first default path after wallet readiness:",
|
|
23343
|
+
" send native value now -> stay on approval-based pay when fee-token/default state matters -> recover funding only when blocked",
|
|
23344
|
+
" Default start inside suite: send value now",
|
|
23345
|
+
"",
|
|
22651
23346
|
"Use `next` while the CLI still needs to choose across setup, wallet readiness, or stored workflow continuation.",
|
|
22652
23347
|
"Use `suite` once wallet readiness is no longer the blocker and you want the packaged post-flagship surface.",
|
|
22653
23348
|
"Use `zk-agent suite --include-onboarding` when you want one readout from first-run bootstrap through the packaged operator catalog.",
|
|
@@ -22675,6 +23370,7 @@ var ROOT_HELP_COMMAND_ORDER = [
|
|
|
22675
23370
|
"wallet",
|
|
22676
23371
|
"workflow",
|
|
22677
23372
|
"suite",
|
|
23373
|
+
"payment",
|
|
22678
23374
|
"assets",
|
|
22679
23375
|
"balances",
|
|
22680
23376
|
"fund",
|
|
@@ -22708,7 +23404,7 @@ function applyRootHelpCommandOrder(program) {
|
|
|
22708
23404
|
program.commands = sortedCommands;
|
|
22709
23405
|
}
|
|
22710
23406
|
function createProgram() {
|
|
22711
|
-
const program = new
|
|
23407
|
+
const program = new Command14().name("zk-agent").description(
|
|
22712
23408
|
"Local-first zkSync-native CLI for wallet approval, workflow execution, and single-host hosted relay recovery"
|
|
22713
23409
|
).showHelpAfterError().option("--json", "Force JSON output for agent harnesses", false).hook("preAction", (thisCommand) => {
|
|
22714
23410
|
if (thisCommand.optsWithGlobals().json) process.env.ZK_AGENT_OUTPUT = "json";
|
|
@@ -22719,6 +23415,7 @@ function createProgram() {
|
|
|
22719
23415
|
program.addCommand(createAgentCommand());
|
|
22720
23416
|
program.addCommand(createDefaultsCommand());
|
|
22721
23417
|
program.addCommand(createSuiteCommand());
|
|
23418
|
+
program.addCommand(createPaymentCommand());
|
|
22722
23419
|
program.addCommand(createTokensCommand());
|
|
22723
23420
|
program.addCommand(createResolveTokenCommand());
|
|
22724
23421
|
program.addCommand(createRelayCommand());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zk-agent-cli",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.4",
|
|
4
4
|
"description": "Local-first zkSync Era and ZK Stack agent CLI with wallet session recovery, workflow orchestration, relay-backed approval, and SED smart-account support.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@zk-agent/account-profiles": "workspace:*",
|
|
69
69
|
"@zk-agent/agent-core": "workspace:*",
|
|
70
|
+
"@zk-agent/agent-pay": "workspace:*",
|
|
70
71
|
"@zk-agent/agent-session-protocol": "workspace:*",
|
|
71
72
|
"@zk-agent/plugin-identity": "workspace:*",
|
|
72
73
|
"@zk-agent/provider-zksync-defi": "workspace:*",
|