@heyanon-arp/cli 0.0.17 → 0.0.19
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/dist/cli.js +999 -1078
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -345,6 +345,10 @@ var init_api = __esm({
|
|
|
345
345
|
async discoverProfile(did) {
|
|
346
346
|
return this.get(`/v1/discovery/agents/${encodeURIComponent(did)}/profile`);
|
|
347
347
|
}
|
|
348
|
+
/** Public `GET /v1/discovery/agents/by-name/:name`. Resolves a unique name → composed profile (incl. DID). 404 if unknown. */
|
|
349
|
+
async discoverByName(name) {
|
|
350
|
+
return this.get(`/v1/discovery/agents/by-name/${encodeURIComponent(name)}`);
|
|
351
|
+
}
|
|
348
352
|
/**
|
|
349
353
|
* Public `GET /v1/escrow/config`. Returns the live on-chain V2
|
|
350
354
|
* Config PDA (fees / pause / stakes / windows). No auth.
|
|
@@ -613,6 +617,14 @@ var init_api = __esm({
|
|
|
613
617
|
query
|
|
614
618
|
);
|
|
615
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* Signed `GET /v1/escrow/disputes/:delegationId`. The autonomous arbiter's
|
|
622
|
+
* verdict for a disputed delegation — winner + DID, evaluator source,
|
|
623
|
+
* reasoning, status, and the on-chain resolve signature. Parties only.
|
|
624
|
+
*/
|
|
625
|
+
async getDisputeResolution(delegationId, signer) {
|
|
626
|
+
return this.signedRequest("GET", `/v1/escrow/disputes/${encodeURIComponent(delegationId)}`, null, signer);
|
|
627
|
+
}
|
|
616
628
|
/**
|
|
617
629
|
* Build the same canonical-JSON signing input the arp-server's
|
|
618
630
|
* `SignedRequestGuard` recomputes (`{ method, path, query, body }`),
|
|
@@ -722,7 +734,7 @@ var import_simple_update_notifier = __toESM(require("simple-update-notifier"));
|
|
|
722
734
|
// package.json
|
|
723
735
|
var package_default = {
|
|
724
736
|
name: "@heyanon-arp/cli",
|
|
725
|
-
version: "0.0.
|
|
737
|
+
version: "0.0.19",
|
|
726
738
|
description: "Command-line client for the Agent Relationship Protocol \u2014 register agents, sign envelopes, run escrowed work cycles on Solana.",
|
|
727
739
|
license: "MIT",
|
|
728
740
|
keywords: ["arp", "agent-relationship-protocol", "did", "solana", "escrow", "ed25519", "agents", "a2a", "cli"],
|
|
@@ -767,7 +779,7 @@ var package_default = {
|
|
|
767
779
|
};
|
|
768
780
|
|
|
769
781
|
// src/commands/agents.ts
|
|
770
|
-
var
|
|
782
|
+
var import_sdk3 = require("@heyanon-arp/sdk");
|
|
771
783
|
var import_chalk3 = __toESM(require("chalk"));
|
|
772
784
|
init_api();
|
|
773
785
|
|
|
@@ -912,6 +924,7 @@ function formatAgentsTable(rows) {
|
|
|
912
924
|
// src/state.ts
|
|
913
925
|
var import_node_fs3 = require("fs");
|
|
914
926
|
var import_node_path4 = require("path");
|
|
927
|
+
var import_sdk2 = require("@heyanon-arp/sdk");
|
|
915
928
|
init_api();
|
|
916
929
|
|
|
917
930
|
// src/credentials.ts
|
|
@@ -1137,13 +1150,35 @@ function warnIfForeignOwner(agent, serverUrl) {
|
|
|
1137
1150
|
`
|
|
1138
1151
|
);
|
|
1139
1152
|
}
|
|
1140
|
-
function resolveSenderAgent(cmdName, serverOverride, explicitFromDid) {
|
|
1153
|
+
function resolveSenderAgent(cmdName, serverOverride, explicitFromDid, explicitFromName) {
|
|
1141
1154
|
const resolvedServerUrl = resolveServerUrl(serverOverride);
|
|
1155
|
+
if (explicitFromDid && explicitFromName) {
|
|
1156
|
+
throw new Error(`${cmdName}: pass either --from <name> OR --from-did <did>, not both.`);
|
|
1157
|
+
}
|
|
1142
1158
|
if (explicitFromDid) {
|
|
1159
|
+
if (!explicitFromDid.startsWith("did:arp:")) {
|
|
1160
|
+
throw new Error(`${cmdName}: --from-did expects a did:arp:<...> DID \u2014 for an agent name use '--from ${explicitFromDid}'.`);
|
|
1161
|
+
}
|
|
1143
1162
|
const agent = loadAgentOrThrow(serverOverride, explicitFromDid);
|
|
1144
1163
|
warnIfForeignOwner(agent, resolvedServerUrl);
|
|
1145
1164
|
return agent;
|
|
1146
1165
|
}
|
|
1166
|
+
if (explicitFromName) {
|
|
1167
|
+
const wanted = (0, import_sdk2.normalizeName)(explicitFromName);
|
|
1168
|
+
const named = listAgents().filter((row) => row.serverUrl === resolvedServerUrl && row.agent.name === wanted);
|
|
1169
|
+
if (named.length === 1) {
|
|
1170
|
+
warnIfForeignOwner(named[0].agent, resolvedServerUrl);
|
|
1171
|
+
return named[0].agent;
|
|
1172
|
+
}
|
|
1173
|
+
if (named.length === 0) {
|
|
1174
|
+
throw new Error(`${cmdName}: no local agent named '${wanted}' for ${resolvedServerUrl}. Pass its --from-did <did>, or register/recover that agent locally first.`);
|
|
1175
|
+
}
|
|
1176
|
+
const dups = named.map((row) => ` ${row.agent.did}`).join("\n");
|
|
1177
|
+
throw new Error(
|
|
1178
|
+
`${cmdName}: ${named.length} local agents share the name '${wanted}' for ${resolvedServerUrl} \u2014 ambiguous. Pass --from-did <did> instead. Candidates:
|
|
1179
|
+
${dups}`
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1147
1182
|
const onServer = listAgents().filter((row) => row.serverUrl === resolvedServerUrl);
|
|
1148
1183
|
if (onServer.length === 1) {
|
|
1149
1184
|
warnIfForeignOwner(onServer[0].agent, resolvedServerUrl);
|
|
@@ -1154,7 +1189,7 @@ function resolveSenderAgent(cmdName, serverOverride, explicitFromDid) {
|
|
|
1154
1189
|
}
|
|
1155
1190
|
const list = onServer.map((row) => ` ${row.agent.did}${row.agent.name ? ` (${row.agent.name})` : ""}`).join("\n");
|
|
1156
1191
|
throw new Error(
|
|
1157
|
-
`${cmdName}: ${onServer.length} agents registered for ${resolvedServerUrl} \u2014 refusing to silently sign as one of them. Pass --from-did <did> to disambiguate. Candidates:
|
|
1192
|
+
`${cmdName}: ${onServer.length} agents registered for ${resolvedServerUrl} \u2014 refusing to silently sign as one of them. Pass --from <name> or --from-did <did> to disambiguate. Candidates:
|
|
1158
1193
|
${list}`
|
|
1159
1194
|
);
|
|
1160
1195
|
}
|
|
@@ -1173,16 +1208,16 @@ function listAgents() {
|
|
|
1173
1208
|
var import_chalk2 = __toESM(require("chalk"));
|
|
1174
1209
|
init_api();
|
|
1175
1210
|
function registerLifecycleCommands(root) {
|
|
1176
|
-
root.command("update").description("Update an agent profile (
|
|
1211
|
+
root.command("update").description("Update an agent profile (description / tags). At least one flag is required. The agent name is immutable and cannot be changed.").argument("[did]", "Agent DID (did:arp:...) \u2014 optional when --from-did is given OR exactly one agent is registered for the resolved server.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Alias for the positional <did> \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--description <s>", "New description").option("--tag <s>", "Capability tag \u2014 REPLACES the existing list. Repeatable: --tag translation --tag fr", accumulate, []).option("--clear-tags", "Drop all tags (cannot be combined with --tag)", false).option("--json", "Machine-readable mode \u2014 emit the updated profile as a single JSON object on stdout (AgentPublic). Prelude moves to stderr. ", false).action(
|
|
1177
1212
|
async (did, opts) => {
|
|
1178
1213
|
if (did !== void 0 && opts.fromDid !== void 0 && did !== opts.fromDid) {
|
|
1179
1214
|
throw new Error(`update: positional <did> (${did}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
|
|
1180
1215
|
}
|
|
1181
1216
|
const explicitDid = did ?? opts.fromDid;
|
|
1182
|
-
const targetDid = (explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("update", opts.server, void 0)).did;
|
|
1217
|
+
const targetDid = (explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("update", opts.server, void 0, opts.from)).did;
|
|
1183
1218
|
const body = buildUpdateBody(opts);
|
|
1184
1219
|
if (Object.keys(body).length === 0) {
|
|
1185
|
-
throw new Error("update: pass at least one of --
|
|
1220
|
+
throw new Error("update: pass at least one of --description / --tag / --clear-tags");
|
|
1186
1221
|
}
|
|
1187
1222
|
const agent = await actSigned(targetDid, opts.server, opts.json, (api, signer) => api.updateAgent(targetDid, body, signer));
|
|
1188
1223
|
updateAgentLocal(opts.server, targetDid, {
|
|
@@ -1206,7 +1241,6 @@ function buildUpdateBody(opts) {
|
|
|
1206
1241
|
throw new Error("update: --clear-tags cannot be combined with --tag");
|
|
1207
1242
|
}
|
|
1208
1243
|
const body = {};
|
|
1209
|
-
if (opts.name !== void 0) body.name = opts.name;
|
|
1210
1244
|
if (opts.description !== void 0) body.description = opts.description;
|
|
1211
1245
|
if (opts.clearTags) {
|
|
1212
1246
|
body.tags = [];
|
|
@@ -1265,10 +1299,10 @@ function registerAgentsCommand(root) {
|
|
|
1265
1299
|
}
|
|
1266
1300
|
async function runAgents(opts) {
|
|
1267
1301
|
const limit = parseLimit(opts.limit);
|
|
1268
|
-
if (opts.sort && opts.sort !==
|
|
1302
|
+
if (opts.sort && opts.sort !== import_sdk3.DiscoverySorts.REPUTATION && opts.sort !== import_sdk3.DiscoverySorts.RECENT && opts.sort !== import_sdk3.DiscoverySorts.CREATED) {
|
|
1269
1303
|
throw new Error(`agents: --sort must be 'reputation', 'recent', or 'created' (got '${opts.sort}')`);
|
|
1270
1304
|
}
|
|
1271
|
-
const sort = opts.sort ===
|
|
1305
|
+
const sort = opts.sort === import_sdk3.DiscoverySorts.RECENT ? import_sdk3.DiscoverySorts.RECENT : opts.sort === import_sdk3.DiscoverySorts.CREATED ? import_sdk3.DiscoverySorts.CREATED : import_sdk3.DiscoverySorts.REPUTATION;
|
|
1272
1306
|
const api = new ArpApiClient(opts.server);
|
|
1273
1307
|
progress(opts.json, import_chalk3.default.dim(`Server: ${api.serverUrl}`));
|
|
1274
1308
|
const query = { limit, sort };
|
|
@@ -1277,7 +1311,7 @@ async function runAgents(opts) {
|
|
|
1277
1311
|
if (opts.accountId) query.accountId = opts.accountId;
|
|
1278
1312
|
if (opts.accepts) query.accepts = resolveAcceptsAsset(opts.accepts);
|
|
1279
1313
|
if (opts.online) query.online = true;
|
|
1280
|
-
if (sort ===
|
|
1314
|
+
if (sort === import_sdk3.DiscoverySorts.CREATED) {
|
|
1281
1315
|
if (opts.after) query.after = opts.after;
|
|
1282
1316
|
} else {
|
|
1283
1317
|
query.page = parsePage(opts.page);
|
|
@@ -1316,10 +1350,10 @@ ${rule}`);
|
|
|
1316
1350
|
`);
|
|
1317
1351
|
}
|
|
1318
1352
|
if (pagination.hasMore) {
|
|
1319
|
-
if (sort ===
|
|
1353
|
+
if (sort === import_sdk3.DiscoverySorts.CREATED && pagination.nextCursor) {
|
|
1320
1354
|
console.log(import_chalk3.default.dim(`
|
|
1321
1355
|
Next page: re-run with --after ${pagination.nextCursor}`));
|
|
1322
|
-
} else if (sort !==
|
|
1356
|
+
} else if (sort !== import_sdk3.DiscoverySorts.CREATED) {
|
|
1323
1357
|
console.log(import_chalk3.default.dim(`
|
|
1324
1358
|
Next page: re-run with --page ${parsePage(opts.page) + 1}`));
|
|
1325
1359
|
}
|
|
@@ -1358,7 +1392,7 @@ function parsePage(raw) {
|
|
|
1358
1392
|
return n;
|
|
1359
1393
|
}
|
|
1360
1394
|
function resolveAcceptsAsset(input) {
|
|
1361
|
-
const resolved = (0,
|
|
1395
|
+
const resolved = (0, import_sdk3.resolveAsset)(input);
|
|
1362
1396
|
if (!resolved) {
|
|
1363
1397
|
throw new Error(`agents: --accepts '${input}' is not a known asset shorthand or a valid CAIP-19 id.`);
|
|
1364
1398
|
}
|
|
@@ -1394,9 +1428,9 @@ function registerAcceptPrefsCommands(agents) {
|
|
|
1394
1428
|
});
|
|
1395
1429
|
prefs.command("show").description(
|
|
1396
1430
|
"Read an agent's published accept-prefs (any DID \u2014 the read is signed with YOUR local agent key; any registered agent may read). Buyers: run this BEFORE `delegation offer` so the offer matches"
|
|
1397
|
-
).argument("<did>", "Agent DID to inspect (any agent, not just your own)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Emit only the AcceptPrefs JSON (or null) on stdout \u2014 jq-pipeable", false).action(async (did, _opts, cmd) => {
|
|
1431
|
+
).argument("<did>", "Agent DID to inspect (any agent, not just your own)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Emit only the AcceptPrefs JSON (or null) on stdout \u2014 jq-pipeable", false).action(async (did, _opts, cmd) => {
|
|
1398
1432
|
const opts = cmd.optsWithGlobals();
|
|
1399
|
-
const sender = resolveSenderAgent("agents accept-prefs show", opts.server, opts.fromDid);
|
|
1433
|
+
const sender = resolveSenderAgent("agents accept-prefs show", opts.server, opts.fromDid, opts.from);
|
|
1400
1434
|
const api = new ArpApiClient(opts.server);
|
|
1401
1435
|
progress(opts.json, import_chalk3.default.dim(`Server: ${api.serverUrl}`));
|
|
1402
1436
|
progress(opts.json, import_chalk3.default.dim(`Signer: ${sender.did}`));
|
|
@@ -1487,11 +1521,11 @@ function printAcceptPrefs(prefs) {
|
|
|
1487
1521
|
}
|
|
1488
1522
|
|
|
1489
1523
|
// src/commands/assets.ts
|
|
1490
|
-
var
|
|
1524
|
+
var import_sdk4 = require("@heyanon-arp/sdk");
|
|
1491
1525
|
var import_chalk4 = __toESM(require("chalk"));
|
|
1492
1526
|
function renderAssetsText() {
|
|
1493
1527
|
const lines = [];
|
|
1494
|
-
for (const [cluster, assets] of Object.entries(
|
|
1528
|
+
for (const [cluster, assets] of Object.entries(import_sdk4.ASSET_WHITELIST)) {
|
|
1495
1529
|
lines.push(import_chalk4.default.bold(cluster));
|
|
1496
1530
|
for (const a of assets) {
|
|
1497
1531
|
const key = `${a.symbol}:${cluster}`;
|
|
@@ -1507,7 +1541,7 @@ function renderAssetsText() {
|
|
|
1507
1541
|
function registerAssetsCommand(root) {
|
|
1508
1542
|
root.command("assets").description("List the payment-asset whitelist (per cluster) \u2014 currencies the server accepts for delegations").option("--json", "machine-readable output (the per-cluster whitelist table)").action((opts) => {
|
|
1509
1543
|
if (opts.json) {
|
|
1510
|
-
console.log(formatJson(
|
|
1544
|
+
console.log(formatJson(import_sdk4.ASSET_WHITELIST));
|
|
1511
1545
|
return;
|
|
1512
1546
|
}
|
|
1513
1547
|
console.log(renderAssetsText());
|
|
@@ -1515,26 +1549,26 @@ function registerAssetsCommand(root) {
|
|
|
1515
1549
|
}
|
|
1516
1550
|
|
|
1517
1551
|
// src/commands/block.ts
|
|
1518
|
-
var
|
|
1552
|
+
var import_sdk5 = require("@heyanon-arp/sdk");
|
|
1519
1553
|
var import_chalk5 = __toESM(require("chalk"));
|
|
1520
1554
|
init_api();
|
|
1521
1555
|
function resolveSigningAgent(opts) {
|
|
1522
|
-
return opts.fromDid !== void 0 ? loadAgentOrThrow(opts.server, opts.fromDid) : resolveSenderAgent("block", opts.server, void 0);
|
|
1556
|
+
return opts.fromDid !== void 0 ? loadAgentOrThrow(opts.server, opts.fromDid) : resolveSenderAgent("block", opts.server, void 0, opts.from);
|
|
1523
1557
|
}
|
|
1524
1558
|
function formatBlockRow(b) {
|
|
1525
|
-
const scope = b.scope ===
|
|
1559
|
+
const scope = b.scope === import_sdk5.InboxBlockScopes.ACCOUNT ? import_chalk5.default.yellow("account") : import_chalk5.default.cyan("did");
|
|
1526
1560
|
const reason = b.reason ? import_chalk5.default.dim(` \u2014 ${b.reason}`) : "";
|
|
1527
1561
|
return `${scope.padEnd(7)} ${b.did}${reason} ${import_chalk5.default.dim(b.blockedAt)}`;
|
|
1528
1562
|
}
|
|
1529
1563
|
function registerBlockCommand(root) {
|
|
1530
1564
|
const block = root.command("block").description("Manage your inbox blocklist \u2014 refuse inbound messages from an agent (and, by default, its whole owner account).");
|
|
1531
|
-
block.command("add <did>").description("Block an agent. Default blocks the target\u2019s ENTIRE owner account (every sibling agent); --did-only blocks just this DID. You cannot block your own account.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent). The block applies account-wide regardless of which signs.").option("--did-only", "Block only this exact DID, not the whole owner account", false).option("--reason <text>", "Private note (max 512 chars), visible only to you").option("--json", "Machine-readable output", false).action(async (did, opts) => {
|
|
1565
|
+
block.command("add <did>").description("Block an agent. Default blocks the target\u2019s ENTIRE owner account (every sibling agent); --did-only blocks just this DID. You cannot block your own account.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent). The block applies account-wide regardless of which signs.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--did-only", "Block only this exact DID, not the whole owner account", false).option("--reason <text>", "Private note (max 512 chars), visible only to you").option("--json", "Machine-readable output", false).action(async (did, opts) => {
|
|
1532
1566
|
await runAdd(did, opts);
|
|
1533
1567
|
});
|
|
1534
|
-
block.command("remove <did>").alias("rm").description("Remove a block. Pass the same DID (+ --did-only flag) you blocked with.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--did-only", "The original block was DID-level (didOnly)", false).option("--json", "Machine-readable output", false).action(async (did, opts) => {
|
|
1568
|
+
block.command("remove <did>").alias("rm").description("Remove a block. Pass the same DID (+ --did-only flag) you blocked with.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--did-only", "The original block was DID-level (didOnly)", false).option("--json", "Machine-readable output", false).action(async (did, opts) => {
|
|
1535
1569
|
await runRemove(did, opts);
|
|
1536
1570
|
});
|
|
1537
|
-
block.command("list").description("List your account\u2019s blocks. Each row shows the DID you named + scope \u2014 never the resolved owner account or its other agents.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--json", "Machine-readable output \u2014 a JSON array.", false).action(async (opts) => {
|
|
1571
|
+
block.command("list").description("List your account\u2019s blocks. Each row shows the DID you named + scope \u2014 never the resolved owner account or its other agents.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Which of your agents signs (defaults to your sole local agent).").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable output \u2014 a JSON array.", false).action(async (opts) => {
|
|
1538
1572
|
await runList(opts);
|
|
1539
1573
|
});
|
|
1540
1574
|
}
|
|
@@ -1547,7 +1581,7 @@ async function runAdd(did, opts) {
|
|
|
1547
1581
|
jsonOut(result);
|
|
1548
1582
|
return;
|
|
1549
1583
|
}
|
|
1550
|
-
const what = result.scope ===
|
|
1584
|
+
const what = result.scope === import_sdk5.InboxBlockScopes.ACCOUNT ? `the owner account of ${did} (all its agents)` : did;
|
|
1551
1585
|
console.log(import_chalk5.default.green(`\u2713 Blocked ${what}.`));
|
|
1552
1586
|
}
|
|
1553
1587
|
async function runRemove(did, opts) {
|
|
@@ -1663,15 +1697,15 @@ function unknownKey(key) {
|
|
|
1663
1697
|
|
|
1664
1698
|
// src/commands/delegation.ts
|
|
1665
1699
|
var import_node_fs4 = require("fs");
|
|
1666
|
-
var
|
|
1667
|
-
var
|
|
1700
|
+
var import_sdk12 = require("@heyanon-arp/sdk");
|
|
1701
|
+
var import_chalk9 = __toESM(require("chalk"));
|
|
1668
1702
|
init_api();
|
|
1669
1703
|
|
|
1670
1704
|
// src/id-format.ts
|
|
1671
|
-
var
|
|
1705
|
+
var import_sdk6 = require("@heyanon-arp/sdk");
|
|
1672
1706
|
var UUID_RE = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
|
|
1673
1707
|
var OBJECT_ID_24_HEX_RE = /^[0-9a-f]{24}$/;
|
|
1674
|
-
var SHA256_PREFIX_RE =
|
|
1708
|
+
var SHA256_PREFIX_RE = import_sdk6.SHA256_HEX_RE;
|
|
1675
1709
|
var UUID_NO_DASHES_RE = /^[a-fA-F0-9]{32}$/;
|
|
1676
1710
|
function describeNonUuidShape(raw) {
|
|
1677
1711
|
if (raw === "") return "empty string";
|
|
@@ -1702,10 +1736,31 @@ function requireUuid(cmdName, raw, label) {
|
|
|
1702
1736
|
throw new Error(hint ? `${base} \u2014 ${hint}` : base);
|
|
1703
1737
|
}
|
|
1704
1738
|
|
|
1705
|
-
// src/
|
|
1706
|
-
var
|
|
1739
|
+
// src/resolve-recipient.ts
|
|
1740
|
+
var import_sdk7 = require("@heyanon-arp/sdk");
|
|
1707
1741
|
var import_chalk7 = __toESM(require("chalk"));
|
|
1708
1742
|
init_api();
|
|
1743
|
+
async function resolveRecipient(serverOverride, cmdName, input, opts = {}) {
|
|
1744
|
+
if (input.startsWith("did:arp:")) {
|
|
1745
|
+
if (!(0, import_sdk7.isValidDid)(input)) {
|
|
1746
|
+
throw new Error(`${cmdName}: '${input}' starts with did:arp: but is not a valid DID (base58btc-encoded 32-byte Ed25519 pubkey).`);
|
|
1747
|
+
}
|
|
1748
|
+
return input;
|
|
1749
|
+
}
|
|
1750
|
+
const name = (0, import_sdk7.normalizeName)(input);
|
|
1751
|
+
if (!(0, import_sdk7.isValidAgentName)(name)) {
|
|
1752
|
+
throw new Error(`${cmdName}: '${input}' is neither a DID (did:arp:...) nor a valid agent name (lowercase a-z0-9_, 3-32 chars).`);
|
|
1753
|
+
}
|
|
1754
|
+
const api = new ArpApiClient(serverOverride);
|
|
1755
|
+
const profile = await api.discoverByName(name);
|
|
1756
|
+
warn(opts.json, import_chalk7.default.dim(`Resolved ${import_chalk7.default.cyan(name)} \u2192 ${profile.did}${profile.description ? ` (${profile.description})` : ""}`));
|
|
1757
|
+
return profile.did;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
// src/commands/status.ts
|
|
1761
|
+
var import_sdk8 = require("@heyanon-arp/sdk");
|
|
1762
|
+
var import_chalk8 = __toESM(require("chalk"));
|
|
1763
|
+
init_api();
|
|
1709
1764
|
var UNTIL_PHASES = [
|
|
1710
1765
|
"delegation.offered",
|
|
1711
1766
|
"delegation.accepted",
|
|
@@ -1726,7 +1781,7 @@ var UNTIL_PHASES = [
|
|
|
1726
1781
|
var WAIT_DEFAULT_INTERVAL_SEC = 3;
|
|
1727
1782
|
var WAIT_DEFAULT_TIMEOUT_SEC = 300;
|
|
1728
1783
|
function registerStatusCommand(root) {
|
|
1729
|
-
root.command("status").description("Where am I in the work cycle? FSM state + next-action hint for ONE relationship (signed reads)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable: single JSON object with the composed summary. Pipe-safe.", false).option(
|
|
1784
|
+
root.command("status").description("Where am I in the work cycle? FSM state + next-action hint for ONE relationship (signed reads)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable: single JSON object with the composed summary. Pipe-safe.", false).option(
|
|
1730
1785
|
"--wait",
|
|
1731
1786
|
`Block and poll until you can act (\`nextActionOwner === 'me'\` OR \`nextActionOwner === 'either' AND relationshipState === 'active'\`) OR the cycle terminates (COMPLETE / closed / not_found). Exits immediately if either condition is already true at first read. Default cadence ${WAIT_DEFAULT_INTERVAL_SEC}s, --wait-timeout ${WAIT_DEFAULT_TIMEOUT_SEC}s. Pairs with --json so a wrapping script can branch on the new state. Exit code 124 on timeout (unix \`timeout\` convention). Combine with --wait-verbose to see per-tick state snapshots during long waits \u2014 useful for "is it alive or stuck?" diagnosis without spawning a separate \`inbox --tail\` shell.`,
|
|
1732
1787
|
false
|
|
@@ -1751,11 +1806,11 @@ function registerStatusCommand(root) {
|
|
|
1751
1806
|
}
|
|
1752
1807
|
async function runStatus(relationshipId, opts) {
|
|
1753
1808
|
const api = new ArpApiClient(opts.server);
|
|
1754
|
-
const sender = resolveSenderAgent("status", opts.server, opts.fromDid);
|
|
1809
|
+
const sender = resolveSenderAgent("status", opts.server, opts.fromDid, opts.from);
|
|
1755
1810
|
if (!opts.json) {
|
|
1756
|
-
console.log(
|
|
1757
|
-
console.log(
|
|
1758
|
-
console.log(
|
|
1811
|
+
console.log(import_chalk8.default.dim(`Server: ${api.serverUrl}`));
|
|
1812
|
+
console.log(import_chalk8.default.dim(`Signer: ${sender.did}`));
|
|
1813
|
+
console.log(import_chalk8.default.dim(`Relationship: ${relationshipId}`));
|
|
1759
1814
|
}
|
|
1760
1815
|
const signer = makeSigner(sender);
|
|
1761
1816
|
if (!opts.wait) {
|
|
@@ -1787,7 +1842,7 @@ async function runStatus(relationshipId, opts) {
|
|
|
1787
1842
|
async function awaitFsmTransitionAfterAction(input) {
|
|
1788
1843
|
const { api, signerDid, signer, relationshipId, untilPhase, waitIntervalSec, waitTimeoutSec, waitVerbose, json } = input;
|
|
1789
1844
|
if (!json) {
|
|
1790
|
-
console.log(
|
|
1845
|
+
console.log(import_chalk8.default.dim(`
|
|
1791
1846
|
[--wait-until ${untilPhase}] polling relationship ${relationshipId} (interval=${waitIntervalSec}s timeout=${waitTimeoutSec}s)`));
|
|
1792
1847
|
}
|
|
1793
1848
|
const outcome = await runWaitLoop({
|
|
@@ -1804,13 +1859,13 @@ async function awaitFsmTransitionAfterAction(input) {
|
|
|
1804
1859
|
}
|
|
1805
1860
|
}
|
|
1806
1861
|
async function runWaitLoop(opts) {
|
|
1807
|
-
const isTerminal = (s) => s.cycleComplete || s.relationshipState ===
|
|
1862
|
+
const isTerminal = (s) => s.cycleComplete || s.relationshipState === import_sdk8.RelationshipStates.CLOSED || s.relationshipState === "not_found";
|
|
1808
1863
|
const isActionable = (s) => {
|
|
1809
1864
|
if (s.nextActionOwner === "me") {
|
|
1810
1865
|
if (s.relationshipState === "unknown") return false;
|
|
1811
1866
|
return true;
|
|
1812
1867
|
}
|
|
1813
|
-
if (s.nextActionOwner === "either" && s.relationshipState ===
|
|
1868
|
+
if (s.nextActionOwner === "either" && s.relationshipState === import_sdk8.RelationshipStates.ACTIVE) {
|
|
1814
1869
|
return true;
|
|
1815
1870
|
}
|
|
1816
1871
|
return false;
|
|
@@ -1826,7 +1881,7 @@ async function runWaitLoop(opts) {
|
|
|
1826
1881
|
}
|
|
1827
1882
|
if (isUntilReached !== null && isUntilReached(initial)) {
|
|
1828
1883
|
if (opts.json) opts.log(JSON.stringify(initial));
|
|
1829
|
-
else opts.log(
|
|
1884
|
+
else opts.log(import_chalk8.default.dim(`
|
|
1830
1885
|
[--wait] Phase '${opts.until}' already reached \u2014 exiting without polling.`));
|
|
1831
1886
|
return { timedOut: false, last: initial };
|
|
1832
1887
|
}
|
|
@@ -1837,13 +1892,13 @@ async function runWaitLoop(opts) {
|
|
|
1837
1892
|
else {
|
|
1838
1893
|
if (opts.until !== void 0) {
|
|
1839
1894
|
opts.log(
|
|
1840
|
-
|
|
1895
|
+
import_chalk8.default.yellow(
|
|
1841
1896
|
`
|
|
1842
1897
|
[--wait] Terminal state (${initial.relationshipState}, cycleComplete=${initial.cycleComplete}) reached before phase '${opts.until}' \u2014 exiting; phase unreachable.`
|
|
1843
1898
|
)
|
|
1844
1899
|
);
|
|
1845
1900
|
} else {
|
|
1846
|
-
opts.log(
|
|
1901
|
+
opts.log(import_chalk8.default.dim(`
|
|
1847
1902
|
[--wait] Already terminal \u2014 exiting.`));
|
|
1848
1903
|
}
|
|
1849
1904
|
}
|
|
@@ -1851,15 +1906,15 @@ async function runWaitLoop(opts) {
|
|
|
1851
1906
|
}
|
|
1852
1907
|
if (opts.until === void 0 && isActionable(initial)) {
|
|
1853
1908
|
if (opts.json) opts.log(JSON.stringify(initial));
|
|
1854
|
-
else opts.log(
|
|
1909
|
+
else opts.log(import_chalk8.default.dim(`
|
|
1855
1910
|
[--wait] Your turn already (nextActionOwner=${initial.nextActionOwner}) \u2014 exiting without polling.`));
|
|
1856
1911
|
return { timedOut: false, last: initial };
|
|
1857
1912
|
}
|
|
1858
1913
|
if (!opts.json) {
|
|
1859
1914
|
const blockerLabel = opts.until !== void 0 ? `Awaiting phase '${opts.until}'` : initial.nextActionOwner === "counterparty" ? "Counterparty owes the next move" : initial.nextActionOwner === "either" ? "Either side may act" : `Awaiting state change (currently ${initial.relationshipState}, nextActionOwner=${initial.nextActionOwner})`;
|
|
1860
|
-
opts.log(
|
|
1915
|
+
opts.log(import_chalk8.default.dim(`
|
|
1861
1916
|
[--wait] ${blockerLabel}. Polling every ${opts.waitIntervalSec}s, timeout ${opts.waitTimeoutSec}s.`));
|
|
1862
|
-
opts.log(
|
|
1917
|
+
opts.log(import_chalk8.default.dim(`[--wait] Initial hint: ${initial.nextActionHint}`));
|
|
1863
1918
|
}
|
|
1864
1919
|
const startedAt = localNow();
|
|
1865
1920
|
const deadline = startedAt + opts.waitTimeoutSec * 1e3;
|
|
@@ -1879,7 +1934,7 @@ async function runWaitLoop(opts) {
|
|
|
1879
1934
|
} else {
|
|
1880
1935
|
target = `nextActionOwner=${next.nextActionOwner}`;
|
|
1881
1936
|
}
|
|
1882
|
-
opts.log(
|
|
1937
|
+
opts.log(import_chalk8.default.dim(`[--wait tick ${tickIndex}/${maxTicks}] state=${next.relationshipState}, ${formatPhaseSnapshot(next)} (${target})`));
|
|
1883
1938
|
}
|
|
1884
1939
|
if (exitPredicate(next)) {
|
|
1885
1940
|
const phaseReached = isUntilReached !== null ? isUntilReached(next) : false;
|
|
@@ -1889,16 +1944,16 @@ async function runWaitLoop(opts) {
|
|
|
1889
1944
|
opts.log("");
|
|
1890
1945
|
if (opts.until !== void 0) {
|
|
1891
1946
|
if (phaseReached) {
|
|
1892
|
-
opts.log(
|
|
1947
|
+
opts.log(import_chalk8.default.green(`[--wait] Phase '${opts.until}' reached.`));
|
|
1893
1948
|
} else {
|
|
1894
1949
|
opts.log(
|
|
1895
|
-
|
|
1950
|
+
import_chalk8.default.yellow(
|
|
1896
1951
|
`[--wait] Terminal state (${next.relationshipState}, cycleComplete=${next.cycleComplete}) reached before phase '${opts.until}' \u2014 phase unreachable.`
|
|
1897
1952
|
)
|
|
1898
1953
|
);
|
|
1899
1954
|
}
|
|
1900
1955
|
} else {
|
|
1901
|
-
opts.log(
|
|
1956
|
+
opts.log(import_chalk8.default.green(`[--wait] ${isTerminal(next) ? "Cycle terminated" : `Your turn (owner=${next.nextActionOwner})`}.`));
|
|
1902
1957
|
}
|
|
1903
1958
|
opts.log(formatStatusReport(next));
|
|
1904
1959
|
}
|
|
@@ -1911,14 +1966,14 @@ async function runWaitLoop(opts) {
|
|
|
1911
1966
|
} else {
|
|
1912
1967
|
if (opts.until !== void 0) {
|
|
1913
1968
|
opts.log(
|
|
1914
|
-
|
|
1969
|
+
import_chalk8.default.yellow(
|
|
1915
1970
|
`
|
|
1916
1971
|
[--wait] Timed out after ${opts.waitTimeoutSec}s without reaching phase '${opts.until}' (latest state: ${last.relationshipState}, hint: ${last.nextActionHint}).`
|
|
1917
1972
|
)
|
|
1918
1973
|
);
|
|
1919
1974
|
} else {
|
|
1920
1975
|
opts.log(
|
|
1921
|
-
|
|
1976
|
+
import_chalk8.default.yellow(`
|
|
1922
1977
|
[--wait] Timed out after ${opts.waitTimeoutSec}s without an actionable or terminal transition (your turn never came, cycle still in flight).`)
|
|
1923
1978
|
);
|
|
1924
1979
|
}
|
|
@@ -1946,41 +2001,41 @@ function parseUntilPhase(raw) {
|
|
|
1946
2001
|
function isPhaseTerminallyUnreachable(phase, s) {
|
|
1947
2002
|
if (untilPhaseMatched(phase, s)) return false;
|
|
1948
2003
|
if (s.relationshipState === "not_found") return true;
|
|
1949
|
-
if (s.relationshipState ===
|
|
2004
|
+
if (s.relationshipState === import_sdk8.RelationshipStates.CLOSED && phase !== "relationship.closed") return true;
|
|
1950
2005
|
return false;
|
|
1951
2006
|
}
|
|
1952
2007
|
function untilPhaseMatched(phase, s) {
|
|
1953
2008
|
switch (phase) {
|
|
1954
2009
|
case "delegation.offered":
|
|
1955
|
-
return s.latestDelegation?.state ===
|
|
2010
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.OFFERED;
|
|
1956
2011
|
case "delegation.accepted":
|
|
1957
|
-
return s.latestDelegation?.state ===
|
|
2012
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.ACCEPTED;
|
|
1958
2013
|
case "delegation.locked":
|
|
1959
|
-
return s.latestDelegation?.state ===
|
|
2014
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.LOCKED;
|
|
1960
2015
|
case "delegation.disputing":
|
|
1961
|
-
return s.latestDelegation?.state ===
|
|
2016
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.DISPUTING;
|
|
1962
2017
|
case "delegation.canceled":
|
|
1963
|
-
return s.latestDelegation?.state ===
|
|
2018
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.CANCELED;
|
|
1964
2019
|
case "delegation.declined":
|
|
1965
|
-
return s.latestDelegation?.state ===
|
|
2020
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.DECLINED;
|
|
1966
2021
|
case "work.requested":
|
|
1967
|
-
return s.latestWorkLog?.state ===
|
|
2022
|
+
return s.latestWorkLog?.state === import_sdk8.WorkLogStates.REQUESTED;
|
|
1968
2023
|
case "work.responded":
|
|
1969
|
-
return s.latestWorkLog?.state ===
|
|
2024
|
+
return s.latestWorkLog?.state === import_sdk8.WorkLogStates.RESPONDED;
|
|
1970
2025
|
case "receipt.proposed":
|
|
1971
2026
|
return s.latestReceipt != null;
|
|
1972
2027
|
case "relationship.pending":
|
|
1973
|
-
return s.relationshipState ===
|
|
2028
|
+
return s.relationshipState === import_sdk8.RelationshipStates.PENDING;
|
|
1974
2029
|
case "relationship.active":
|
|
1975
|
-
return s.relationshipState ===
|
|
2030
|
+
return s.relationshipState === import_sdk8.RelationshipStates.ACTIVE;
|
|
1976
2031
|
case "relationship.paused":
|
|
1977
|
-
return s.relationshipState ===
|
|
2032
|
+
return s.relationshipState === import_sdk8.RelationshipStates.PAUSED;
|
|
1978
2033
|
case "relationship.closed":
|
|
1979
|
-
return s.relationshipState ===
|
|
2034
|
+
return s.relationshipState === import_sdk8.RelationshipStates.CLOSED;
|
|
1980
2035
|
case "cycle.complete":
|
|
1981
2036
|
return s.cycleComplete;
|
|
1982
2037
|
case "cycle.released":
|
|
1983
|
-
return s.latestDelegation?.state ===
|
|
2038
|
+
return s.latestDelegation?.state === import_sdk8.DelegationStates.COMPLETED;
|
|
1984
2039
|
}
|
|
1985
2040
|
}
|
|
1986
2041
|
function parseWaitInterval(raw) {
|
|
@@ -2031,7 +2086,7 @@ async function composeStatus(api, signerDid, relationshipId, signer) {
|
|
|
2031
2086
|
const relationship = relationships.find((r) => r.relationshipId === relationshipId);
|
|
2032
2087
|
const counterpartyDid = relationship ? relationship.pairDidA === signerDid ? relationship.pairDidB : relationship.pairDidA : inferCounterpartyFromEntities(signerDid, allDelegations);
|
|
2033
2088
|
const delegations = allDelegations;
|
|
2034
|
-
const latestDelegation = pickLatestLive(delegations, [...
|
|
2089
|
+
const latestDelegation = pickLatestLive(delegations, [...import_sdk8.DELEGATION_ACTIVE_STATES]);
|
|
2035
2090
|
const [workLogs, receipts] = await Promise.all([
|
|
2036
2091
|
latestDelegation ? fetchAllPages(
|
|
2037
2092
|
(after) => api.listWorkLogs(relationshipId, signer, { limit: 100, delegationId: latestDelegation.delegationId, ...after ? { after } : {} })
|
|
@@ -2095,8 +2150,8 @@ function findReceiptForWorkLog(receipts, workLog, allWorkLogs = [workLog]) {
|
|
|
2095
2150
|
};
|
|
2096
2151
|
const responseBody = workLog.responseOutput !== void 0 ? { type: "work_response", content: { delegation_id: workLog.delegationId, request_id: workLog.requestId, output: workLog.responseOutput } } : workLog.responseError !== void 0 ? { type: "work_response", content: { delegation_id: workLog.delegationId, request_id: workLog.requestId, error: workLog.responseError } } : null;
|
|
2097
2152
|
if (!responseBody) return null;
|
|
2098
|
-
const expectedRequestHash = (0,
|
|
2099
|
-
const expectedResponseHash = (0,
|
|
2153
|
+
const expectedRequestHash = (0, import_sdk8.canonicalSha256Hex)(requestBody);
|
|
2154
|
+
const expectedResponseHash = (0, import_sdk8.canonicalSha256Hex)(responseBody);
|
|
2100
2155
|
const matches = receipts.filter((r) => r.requestHash === expectedRequestHash && r.responseHash === expectedResponseHash);
|
|
2101
2156
|
if (matches.length > 0) return pickLatest(matches);
|
|
2102
2157
|
const respondedSiblings = allWorkLogs.filter((wl) => wl.delegationId === workLog.delegationId && (wl.responseOutput !== void 0 || wl.responseError !== void 0)).length;
|
|
@@ -2138,49 +2193,49 @@ function nextAction(input) {
|
|
|
2138
2193
|
complete: false
|
|
2139
2194
|
};
|
|
2140
2195
|
}
|
|
2141
|
-
if (relationship.state ===
|
|
2196
|
+
if (relationship.state === import_sdk8.RelationshipStates.PENDING) {
|
|
2142
2197
|
return {
|
|
2143
2198
|
hint: "Relationship is PENDING \u2014 one side owes `heyarp send-handshake-response <peer> --decision accept | decline`",
|
|
2144
2199
|
owner: "either",
|
|
2145
2200
|
complete: false
|
|
2146
2201
|
};
|
|
2147
2202
|
}
|
|
2148
|
-
if (relationship.state ===
|
|
2203
|
+
if (relationship.state === import_sdk8.RelationshipStates.PAUSED) {
|
|
2149
2204
|
return { hint: "Relationship is PAUSED \u2014 owner must `heyarp unpause` before any envelopes flow", owner: "either", complete: false };
|
|
2150
2205
|
}
|
|
2151
|
-
if (relationship.state ===
|
|
2206
|
+
if (relationship.state === import_sdk8.RelationshipStates.CLOSED) {
|
|
2152
2207
|
return { hint: "Relationship is CLOSED \u2014 terminal state, no further action possible. Start a fresh handshake to reopen.", owner: "none", complete: false };
|
|
2153
2208
|
}
|
|
2154
|
-
if (!latestDelegation || latestDelegation.state ===
|
|
2209
|
+
if (!latestDelegation || latestDelegation.state === import_sdk8.DelegationStates.DECLINED || latestDelegation.state === import_sdk8.DelegationStates.CANCELED) {
|
|
2155
2210
|
return {
|
|
2156
2211
|
hint: "No live delegation \u2014 buyer offers (terms only, no lock) `heyarp delegation offer <peer> --delegation-id <new-uuid> --title \u2026 --scope \u2026 --amount \u2026 --currency SOL:solana-devnet --deadline \u2026`, then funds the escrow lock AFTER the worker accepts via `heyarp delegation fund <del-id> --escrow-lock-from-file <path>`",
|
|
2157
2212
|
owner: "either",
|
|
2158
2213
|
complete: false
|
|
2159
2214
|
};
|
|
2160
2215
|
}
|
|
2161
|
-
if (latestDelegation.state ===
|
|
2216
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.DISPUTING) {
|
|
2162
2217
|
return {
|
|
2163
2218
|
hint: `Delegation ${latestDelegation.delegationId} is DISPUTING \u2014 the buyer opened an on-chain dispute (their stake is escrowed too). The operator may rule until the dispute window lapses; after that either party closes with \`heyarp escrow dispute close ${latestDelegation.delegationId}\` (escrow returns to the buyer, both stakes return). Deadline: \`heyarp escrow show ${latestDelegation.delegationId}\`. No envelopes to send meanwhile.`,
|
|
2164
2219
|
owner: "none",
|
|
2165
2220
|
complete: false
|
|
2166
2221
|
};
|
|
2167
2222
|
}
|
|
2168
|
-
if (latestDelegation.state ===
|
|
2223
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.COMPLETED) {
|
|
2169
2224
|
return {
|
|
2170
2225
|
hint: "Cycle COMPLETE \u2014 payment claimed on chain (lock paid; the receipt carries releaseStatus=paid)",
|
|
2171
2226
|
owner: "none",
|
|
2172
2227
|
complete: true
|
|
2173
2228
|
};
|
|
2174
2229
|
}
|
|
2175
|
-
if (latestDelegation.state ===
|
|
2230
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.FAILED || latestDelegation.state === import_sdk8.DelegationStates.REFUNDED || latestDelegation.state === import_sdk8.DelegationStates.DISPUTE_RESOLVED) {
|
|
2176
2231
|
const stateLabel = latestDelegation.state.toUpperCase();
|
|
2177
|
-
const reason = latestDelegation.state ===
|
|
2232
|
+
const reason = latestDelegation.state === import_sdk8.DelegationStates.FAILED ? "on-chain escrow lock failed to finalise (typical causes: insufficient payer funds, wrong program-id, ProgramState PDA uninitialised \u2014 check `heyarp delegations <rel-id> --json | jq .[].escrowError` for the worker-side reason)" : latestDelegation.state === import_sdk8.DelegationStates.REFUNDED ? (
|
|
2178
2233
|
// Keyed on the DELEGATION row's releaseStatus, not the
|
|
2179
2234
|
// receipt's: in the claim-expired path the worker never
|
|
2180
2235
|
// submitted anything, so no receipt row exists to carry
|
|
2181
2236
|
// the outcome — the delegation copy is always present
|
|
2182
2237
|
// on indexer-driven terminals.
|
|
2183
|
-
latestDelegation.releaseStatus ===
|
|
2238
|
+
latestDelegation.releaseStatus === import_sdk8.LockStates.DISPUTE_CLOSED ? "the dispute window lapsed without an operator ruling and the dispute was closed \u2014 escrow returned to the buyer, both stakes returned (work was delivered but not paid)" : latestDelegation.releaseStatus === import_sdk8.LockStates.REVOKED ? "the work window lapsed without an on-chain submit \u2014 the buyer reclaimed the escrow AND the worker stake (claim_expired_work)" : "lock was refunded after expiry \u2014 no work was delivered against this delegation"
|
|
2184
2239
|
) : "admin closed the delegation via the dispute-resolution path";
|
|
2185
2240
|
return {
|
|
2186
2241
|
hint: `Delegation ${latestDelegation.delegationId} is ${stateLabel} (terminal) \u2014 ${reason}. Issue a fresh \`heyarp delegation offer <peer> --delegation-id <new-uuid> \u2026\` to retry (FSM does not auto-retry).`,
|
|
@@ -2188,7 +2243,7 @@ function nextAction(input) {
|
|
|
2188
2243
|
complete: false
|
|
2189
2244
|
};
|
|
2190
2245
|
}
|
|
2191
|
-
if (latestDelegation.state ===
|
|
2246
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.OFFERED) {
|
|
2192
2247
|
const iAmOfferer = latestDelegation.offererDid === signerDid;
|
|
2193
2248
|
const stateLabel = "OFFERED";
|
|
2194
2249
|
return {
|
|
@@ -2197,7 +2252,7 @@ function nextAction(input) {
|
|
|
2197
2252
|
complete: false
|
|
2198
2253
|
};
|
|
2199
2254
|
}
|
|
2200
|
-
if (latestDelegation.state ===
|
|
2255
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.ACCEPTED && !latestWorkLog) {
|
|
2201
2256
|
const iAmOfferer = latestDelegation.offererDid === signerDid;
|
|
2202
2257
|
return {
|
|
2203
2258
|
hint: iAmOfferer ? `Delegation ${latestDelegation.delegationId} is ACCEPTED \u2014 you (buyer) owe \`heyarp wallet create-lock --delegation-id ${latestDelegation.delegationId} --condition-hash <hex> ... > lock.json\` then \`heyarp delegation fund ${latestDelegation.delegationId} --escrow-lock-from-file lock.json\` (fund the escrow lock; work begins once it is LOCKED on chain)` : `Delegation ${latestDelegation.delegationId} is ACCEPTED \u2014 counterparty (the buyer) owes \`heyarp delegation fund\` to lock the escrow; wait for the delegation to reach LOCKED before working`,
|
|
@@ -2205,7 +2260,7 @@ function nextAction(input) {
|
|
|
2205
2260
|
complete: false
|
|
2206
2261
|
};
|
|
2207
2262
|
}
|
|
2208
|
-
if (latestDelegation.state ===
|
|
2263
|
+
if (latestDelegation.state === import_sdk8.DelegationStates.PENDING_LOCK_FINALIZATION && !latestWorkLog) {
|
|
2209
2264
|
return {
|
|
2210
2265
|
hint: `Delegation ${latestDelegation.delegationId} is PENDING_LOCK_FINALIZATION \u2014 the escrow lock was funded and is awaiting on-chain confirmation; both sides wait (auto-advances to LOCKED). Poll with \`heyarp status ${relationship.relationshipId} --wait --until delegation.locked\`.`,
|
|
2211
2266
|
owner: "none",
|
|
@@ -2220,7 +2275,7 @@ function nextAction(input) {
|
|
|
2220
2275
|
complete: false
|
|
2221
2276
|
};
|
|
2222
2277
|
}
|
|
2223
|
-
if (latestWorkLog.state ===
|
|
2278
|
+
if (latestWorkLog.state === import_sdk8.WorkLogStates.REQUESTED) {
|
|
2224
2279
|
const iAmPayee = latestWorkLog.payeeDid === signerDid;
|
|
2225
2280
|
return {
|
|
2226
2281
|
hint: iAmPayee ? `work_request ${latestWorkLog.requestId} is REQUESTED \u2014 you owe \`heyarp work respond\` (output OR --error)` : `work_request ${latestWorkLog.requestId} is REQUESTED \u2014 counterparty (payee) owes \`heyarp work respond\``,
|
|
@@ -2272,349 +2327,84 @@ function formatStatusReport(s) {
|
|
|
2272
2327
|
const lines = [];
|
|
2273
2328
|
lines.push(cycleHeadline(s));
|
|
2274
2329
|
lines.push("");
|
|
2275
|
-
lines.push(
|
|
2330
|
+
lines.push(import_chalk8.default.bold("Relationship"));
|
|
2276
2331
|
lines.push(` state: ${stateColor(s.relationshipState)}`);
|
|
2277
|
-
if (s.counterpartyDid) lines.push(` counterparty: ${
|
|
2332
|
+
if (s.counterpartyDid) lines.push(` counterparty: ${import_chalk8.default.cyan(s.counterpartyDid)}`);
|
|
2278
2333
|
lines.push("");
|
|
2279
|
-
lines.push(
|
|
2334
|
+
lines.push(import_chalk8.default.bold("Latest delegation"));
|
|
2280
2335
|
if (s.latestDelegation) {
|
|
2281
2336
|
lines.push(` ${s.latestDelegation.delegationId} state=${stateColor(s.latestDelegation.state)}`);
|
|
2282
|
-
lines.push(` offerer: ${
|
|
2337
|
+
lines.push(` offerer: ${import_chalk8.default.cyan(s.latestDelegation.offererDid)}`);
|
|
2283
2338
|
if (s.latestDelegation.title) lines.push(` title: ${s.latestDelegation.title}`);
|
|
2284
2339
|
if (s.latestDelegation.scopeSummary) lines.push(` scope: ${s.latestDelegation.scopeSummary}`);
|
|
2285
2340
|
} else {
|
|
2286
|
-
lines.push(
|
|
2341
|
+
lines.push(import_chalk8.default.dim(" (none)"));
|
|
2287
2342
|
}
|
|
2288
2343
|
lines.push("");
|
|
2289
|
-
lines.push(
|
|
2344
|
+
lines.push(import_chalk8.default.bold("Latest work_log"));
|
|
2290
2345
|
if (s.latestWorkLog) {
|
|
2291
2346
|
lines.push(` request_id=${s.latestWorkLog.requestId} state=${stateColor(s.latestWorkLog.state)}`);
|
|
2292
2347
|
} else {
|
|
2293
|
-
lines.push(
|
|
2348
|
+
lines.push(import_chalk8.default.dim(" (none)"));
|
|
2294
2349
|
}
|
|
2295
2350
|
lines.push("");
|
|
2296
|
-
lines.push(
|
|
2351
|
+
lines.push(import_chalk8.default.bold("Latest receipt"));
|
|
2297
2352
|
if (s.latestReceipt) {
|
|
2298
2353
|
lines.push(` ${stateColor("proposed")} verdict=${s.latestReceipt.verdictProposed}`);
|
|
2299
2354
|
} else {
|
|
2300
|
-
lines.push(
|
|
2355
|
+
lines.push(import_chalk8.default.dim(" (none)"));
|
|
2301
2356
|
}
|
|
2302
2357
|
lines.push("");
|
|
2303
|
-
lines.push(
|
|
2304
|
-
const ownerLabel = s.nextActionOwner === "me" ?
|
|
2358
|
+
lines.push(import_chalk8.default.bold("Next action"));
|
|
2359
|
+
const ownerLabel = s.nextActionOwner === "me" ? import_chalk8.default.green("me") : s.nextActionOwner === "counterparty" ? import_chalk8.default.yellow("counterparty") : s.nextActionOwner === "either" ? import_chalk8.default.cyan("either side") : import_chalk8.default.dim("\u2014");
|
|
2305
2360
|
lines.push(` whose turn: ${ownerLabel}`);
|
|
2306
2361
|
lines.push(` hint: ${s.nextActionHint}`);
|
|
2307
|
-
if (s.cycleComplete) lines.push(` ${
|
|
2362
|
+
if (s.cycleComplete) lines.push(` ${import_chalk8.default.green("\u2713 Cycle complete.")}`);
|
|
2308
2363
|
return lines.join("\n");
|
|
2309
2364
|
}
|
|
2310
2365
|
function cycleHeadline(s) {
|
|
2311
2366
|
if (s.cycleComplete) {
|
|
2312
|
-
return `${
|
|
2367
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.green.bold("COMPLETE")} ${import_chalk8.default.dim("\u2014 payment proven on chain")}`;
|
|
2313
2368
|
}
|
|
2314
2369
|
switch (s.relationshipState) {
|
|
2315
2370
|
case "not_found":
|
|
2316
|
-
return `${
|
|
2371
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.red.bold("NOT FOUND")} ${import_chalk8.default.dim("\u2014 relationship missing or signer is not a member")}`;
|
|
2317
2372
|
case "unknown":
|
|
2318
|
-
return `${
|
|
2319
|
-
case
|
|
2320
|
-
return `${
|
|
2321
|
-
case
|
|
2322
|
-
return `${
|
|
2323
|
-
case
|
|
2324
|
-
return `${
|
|
2325
|
-
case
|
|
2373
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.yellow.bold("UNKNOWN")} ${import_chalk8.default.dim("\u2014 state probe inconclusive; hint below is advisory")}`;
|
|
2374
|
+
case import_sdk8.RelationshipStates.CLOSED:
|
|
2375
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.red.bold("CLOSED")} ${import_chalk8.default.dim("\u2014 relationship terminal, no further protocol action")}`;
|
|
2376
|
+
case import_sdk8.RelationshipStates.PAUSED:
|
|
2377
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.yellow.bold("PAUSED")} ${import_chalk8.default.dim("\u2014 relationship soft-disabled, resume to continue")}`;
|
|
2378
|
+
case import_sdk8.RelationshipStates.PENDING:
|
|
2379
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.yellow.bold("PENDING")} ${import_chalk8.default.dim("\u2014 awaiting handshake_response")}`;
|
|
2380
|
+
case import_sdk8.RelationshipStates.ACTIVE:
|
|
2326
2381
|
default:
|
|
2327
|
-
return `${
|
|
2382
|
+
return `${import_chalk8.default.bold("Cycle:")} ${import_chalk8.default.cyan.bold("ACTIVE")} ${import_chalk8.default.dim('\u2014 work in progress; see "Next action" below')}`;
|
|
2328
2383
|
}
|
|
2329
2384
|
}
|
|
2330
2385
|
function stateColor(state) {
|
|
2331
|
-
const c = state === "active" || state === "accepted" || state === "locked" || state === "responded" || state === "completed" ?
|
|
2386
|
+
const c = state === "active" || state === "accepted" || state === "locked" || state === "responded" || state === "completed" ? import_chalk8.default.green : state === "pending" || state === "requested" || state === "offered" || state === "pending_lock_finalization" ? import_chalk8.default.yellow : state === "closed" || state === "declined" || state === "canceled" || state === "replaced" || state === "not_found" || // Terminal failure states deserve the same red
|
|
2332
2387
|
// treatment as declined/canceled so an operator
|
|
2333
2388
|
// scanning `heyarp status` immediately sees
|
|
2334
2389
|
// "this is dead, don't follow the hint blindly".
|
|
2335
|
-
state === "failed" || state === "refunded" || state === "dispute_resolved" ?
|
|
2390
|
+
state === "failed" || state === "refunded" || state === "dispute_resolved" ? import_chalk8.default.red : import_chalk8.default.cyan;
|
|
2336
2391
|
return c(state);
|
|
2337
2392
|
}
|
|
2338
2393
|
|
|
2339
2394
|
// src/commands/wallet.ts
|
|
2340
|
-
var
|
|
2395
|
+
var import_sdk11 = require("@heyanon-arp/sdk");
|
|
2341
2396
|
var import_utils = require("@noble/hashes/utils");
|
|
2342
|
-
var
|
|
2397
|
+
var import_web3 = require("@solana/web3.js");
|
|
2343
2398
|
init_api();
|
|
2344
2399
|
init_config();
|
|
2345
2400
|
|
|
2346
2401
|
// src/solana/escrow-ix.ts
|
|
2347
|
-
var
|
|
2348
|
-
var import_web3 = require("@solana/web3.js");
|
|
2349
|
-
var SPL_TOKEN_PROGRAM_ID = new import_web3.PublicKey(import_sdk7.SPL_TOKEN_PROGRAM_ID_BASE58);
|
|
2350
|
-
var ASSOCIATED_TOKEN_PROGRAM_ID = new import_web3.PublicKey(import_sdk7.ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
|
|
2351
|
-
var NATIVE_SOL_MINT = new import_web3.PublicKey(import_sdk7.NATIVE_SOL_MINT_BASE58);
|
|
2352
|
-
function deriveLockPda(programId, lockId) {
|
|
2353
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.LOCK), Buffer.from(lockId)], programId)[0];
|
|
2354
|
-
}
|
|
2355
|
-
function deriveEscrowPda(programId, lockId) {
|
|
2356
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.ESCROW), Buffer.from(lockId)], programId)[0];
|
|
2357
|
-
}
|
|
2358
|
-
function deriveConfigPda(programId) {
|
|
2359
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.CONFIG)], programId)[0];
|
|
2360
|
-
}
|
|
2361
|
-
function deriveStakeVaultPda(programId) {
|
|
2362
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.STAKE_VAULT)], programId)[0];
|
|
2363
|
-
}
|
|
2364
|
-
function deriveCollateralConfigPda(programId, mint) {
|
|
2365
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.COLLATERAL), mint.toBuffer()], programId)[0];
|
|
2366
|
-
}
|
|
2367
|
-
function deriveDisputeResolutionPda(programId, lockId) {
|
|
2368
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.DISPUTE_RESOLUTION), Buffer.from(lockId)], programId)[0];
|
|
2369
|
-
}
|
|
2370
|
-
function deriveOperatorAuthPda(programId, operator) {
|
|
2371
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.OPERATOR_AUTH), operator.toBuffer()], programId)[0];
|
|
2372
|
-
}
|
|
2373
|
-
function deriveEventAuthorityPda(programId) {
|
|
2374
|
-
return import_web3.PublicKey.findProgramAddressSync([Buffer.from(import_sdk7.ESCROW_PDA_SEEDS.EVENT_AUTHORITY)], programId)[0];
|
|
2375
|
-
}
|
|
2376
|
-
function deriveAta(owner, mint) {
|
|
2377
|
-
return import_web3.PublicKey.findProgramAddressSync([owner.toBuffer(), SPL_TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID)[0];
|
|
2378
|
-
}
|
|
2379
|
-
function eventCpiTail(programId) {
|
|
2380
|
-
return [
|
|
2381
|
-
{ pubkey: deriveEventAuthorityPda(programId), isSigner: false, isWritable: false },
|
|
2382
|
-
{ pubkey: programId, isSigner: false, isWritable: false }
|
|
2383
|
-
];
|
|
2384
|
-
}
|
|
2385
|
-
function meta(pubkey, opts = {}) {
|
|
2386
|
-
return { pubkey, isSigner: opts.signer === true, isWritable: opts.writable === true };
|
|
2387
|
-
}
|
|
2388
|
-
function noArgIx(programId, name, keys) {
|
|
2389
|
-
return new import_web3.TransactionInstruction({ programId, keys, data: Buffer.from((0, import_sdk7.buildLifecycleIxData)(name)) });
|
|
2390
|
-
}
|
|
2391
|
-
function buildCreateLockIx(input) {
|
|
2392
|
-
const { programId, lockId } = input;
|
|
2393
|
-
const native = input.mint === null;
|
|
2394
|
-
const data = Buffer.from((0, import_sdk7.buildCreateLockIxData)({ lockId, amount: input.amount, conditionHash: input.conditionHash }, { native }));
|
|
2395
|
-
const head = [
|
|
2396
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2397
|
-
meta(input.payee),
|
|
2398
|
-
meta(deriveConfigPda(programId)),
|
|
2399
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2400
|
-
meta(deriveCollateralConfigPda(programId, input.mint ?? NATIVE_SOL_MINT))
|
|
2401
|
-
];
|
|
2402
|
-
const keys = native ? [...head, meta(deriveEscrowPda(programId, lockId), { writable: true }), meta(import_web3.SystemProgram.programId), ...eventCpiTail(programId)] : [
|
|
2403
|
-
...head,
|
|
2404
|
-
meta(input.mint),
|
|
2405
|
-
meta(deriveAta(input.payer, input.mint), { writable: true }),
|
|
2406
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2407
|
-
meta(import_web3.SystemProgram.programId),
|
|
2408
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2409
|
-
...eventCpiTail(programId)
|
|
2410
|
-
];
|
|
2411
|
-
return new import_web3.TransactionInstruction({ programId, keys, data });
|
|
2412
|
-
}
|
|
2413
|
-
function buildAcceptLockIx(input) {
|
|
2414
|
-
const { programId, lockId } = input;
|
|
2415
|
-
return noArgIx(programId, "accept_lock", [
|
|
2416
|
-
meta(input.payee, { signer: true, writable: true }),
|
|
2417
|
-
meta(deriveConfigPda(programId)),
|
|
2418
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2419
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2420
|
-
meta(import_web3.SystemProgram.programId),
|
|
2421
|
-
...eventCpiTail(programId)
|
|
2422
|
-
]);
|
|
2423
|
-
}
|
|
2424
|
-
function buildSubmitWorkIx(input) {
|
|
2425
|
-
const { programId, lockId } = input;
|
|
2426
|
-
return noArgIx(programId, "submit_work", [
|
|
2427
|
-
meta(input.payee, { signer: true }),
|
|
2428
|
-
meta(deriveConfigPda(programId)),
|
|
2429
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2430
|
-
...eventCpiTail(programId)
|
|
2431
|
-
]);
|
|
2432
|
-
}
|
|
2433
|
-
function buildClaimWorkPaymentIx(input) {
|
|
2434
|
-
const { programId, lockId } = input;
|
|
2435
|
-
if (input.mint === null) {
|
|
2436
|
-
return noArgIx(programId, "claim_work_payment_native", [
|
|
2437
|
-
meta(input.authority, { signer: true, writable: true }),
|
|
2438
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2439
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2440
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2441
|
-
meta(input.payer, { writable: true }),
|
|
2442
|
-
meta(input.payee, { writable: true }),
|
|
2443
|
-
meta(input.feeRecipient, { writable: true }),
|
|
2444
|
-
meta(import_web3.SystemProgram.programId),
|
|
2445
|
-
...eventCpiTail(programId)
|
|
2446
|
-
]);
|
|
2447
|
-
}
|
|
2448
|
-
return noArgIx(programId, "claim_work_payment", [
|
|
2449
|
-
meta(input.authority, { signer: true, writable: true }),
|
|
2450
|
-
meta(deriveConfigPda(programId)),
|
|
2451
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2452
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2453
|
-
meta(input.mint),
|
|
2454
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2455
|
-
meta(input.payer, { writable: true }),
|
|
2456
|
-
meta(input.payee, { writable: true }),
|
|
2457
|
-
meta(deriveAta(input.payee, input.mint), { writable: true }),
|
|
2458
|
-
meta(input.feeRecipient),
|
|
2459
|
-
meta(deriveAta(input.feeRecipient, input.mint), { writable: true }),
|
|
2460
|
-
meta(import_web3.SystemProgram.programId),
|
|
2461
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2462
|
-
meta(ASSOCIATED_TOKEN_PROGRAM_ID),
|
|
2463
|
-
...eventCpiTail(programId)
|
|
2464
|
-
]);
|
|
2465
|
-
}
|
|
2466
|
-
function buildCancelLockIx(input) {
|
|
2467
|
-
const { programId, lockId } = input;
|
|
2468
|
-
if (input.mint === null) {
|
|
2469
|
-
return noArgIx(programId, "cancel_lock_native", [
|
|
2470
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2471
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2472
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2473
|
-
meta(import_web3.SystemProgram.programId),
|
|
2474
|
-
...eventCpiTail(programId)
|
|
2475
|
-
]);
|
|
2476
|
-
}
|
|
2477
|
-
return noArgIx(programId, "cancel_lock", [
|
|
2478
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2479
|
-
meta(deriveConfigPda(programId)),
|
|
2480
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2481
|
-
meta(input.mint),
|
|
2482
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2483
|
-
meta(deriveAta(input.payer, input.mint), { writable: true }),
|
|
2484
|
-
meta(import_web3.SystemProgram.programId),
|
|
2485
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2486
|
-
meta(ASSOCIATED_TOKEN_PROGRAM_ID),
|
|
2487
|
-
...eventCpiTail(programId)
|
|
2488
|
-
]);
|
|
2489
|
-
}
|
|
2490
|
-
function buildClaimExpiredWorkIx(input) {
|
|
2491
|
-
const { programId, lockId } = input;
|
|
2492
|
-
if (input.mint === null) {
|
|
2493
|
-
return noArgIx(programId, "claim_expired_work_native", [
|
|
2494
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2495
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2496
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2497
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2498
|
-
meta(import_web3.SystemProgram.programId),
|
|
2499
|
-
...eventCpiTail(programId)
|
|
2500
|
-
]);
|
|
2501
|
-
}
|
|
2502
|
-
return noArgIx(programId, "claim_expired_work", [
|
|
2503
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2504
|
-
meta(deriveConfigPda(programId)),
|
|
2505
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2506
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2507
|
-
meta(input.mint),
|
|
2508
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2509
|
-
meta(deriveAta(input.payer, input.mint), { writable: true }),
|
|
2510
|
-
meta(import_web3.SystemProgram.programId),
|
|
2511
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2512
|
-
meta(ASSOCIATED_TOKEN_PROGRAM_ID),
|
|
2513
|
-
...eventCpiTail(programId)
|
|
2514
|
-
]);
|
|
2515
|
-
}
|
|
2516
|
-
function buildOpenDisputeIx(input) {
|
|
2517
|
-
const { programId, lockId } = input;
|
|
2518
|
-
return noArgIx(programId, "open_dispute", [
|
|
2519
|
-
meta(input.payer, { signer: true, writable: true }),
|
|
2520
|
-
meta(deriveConfigPda(programId)),
|
|
2521
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2522
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2523
|
-
meta(import_web3.SystemProgram.programId),
|
|
2524
|
-
...eventCpiTail(programId)
|
|
2525
|
-
]);
|
|
2526
|
-
}
|
|
2527
|
-
function buildResolveDisputeIx(input) {
|
|
2528
|
-
const { programId, lockId } = input;
|
|
2529
|
-
const native = input.mint === null;
|
|
2530
|
-
const data = Buffer.from((0, import_sdk7.buildResolveDisputeIxData)(input.args, { native }));
|
|
2531
|
-
if (native) {
|
|
2532
|
-
return new import_web3.TransactionInstruction({
|
|
2533
|
-
programId,
|
|
2534
|
-
data,
|
|
2535
|
-
keys: [
|
|
2536
|
-
meta(input.operator, { signer: true, writable: true }),
|
|
2537
|
-
meta(deriveOperatorAuthPda(programId, input.operator)),
|
|
2538
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2539
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2540
|
-
meta(deriveDisputeResolutionPda(programId, lockId), { writable: true }),
|
|
2541
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2542
|
-
meta(input.payer, { writable: true }),
|
|
2543
|
-
meta(input.winner, { writable: true }),
|
|
2544
|
-
meta(input.feeRecipient, { writable: true }),
|
|
2545
|
-
meta(input.treasury, { writable: true }),
|
|
2546
|
-
meta(import_web3.SystemProgram.programId),
|
|
2547
|
-
...eventCpiTail(programId)
|
|
2548
|
-
]
|
|
2549
|
-
});
|
|
2550
|
-
}
|
|
2551
|
-
return new import_web3.TransactionInstruction({
|
|
2552
|
-
programId,
|
|
2553
|
-
data,
|
|
2554
|
-
keys: [
|
|
2555
|
-
meta(input.operator, { signer: true, writable: true }),
|
|
2556
|
-
meta(deriveOperatorAuthPda(programId, input.operator)),
|
|
2557
|
-
meta(deriveConfigPda(programId)),
|
|
2558
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2559
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2560
|
-
meta(deriveDisputeResolutionPda(programId, lockId), { writable: true }),
|
|
2561
|
-
meta(input.mint),
|
|
2562
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2563
|
-
meta(input.payer, { writable: true }),
|
|
2564
|
-
meta(input.winner, { writable: true }),
|
|
2565
|
-
meta(deriveAta(input.winner, input.mint), { writable: true }),
|
|
2566
|
-
meta(input.feeRecipient),
|
|
2567
|
-
meta(deriveAta(input.feeRecipient, input.mint), { writable: true }),
|
|
2568
|
-
meta(input.treasury, { writable: true }),
|
|
2569
|
-
meta(import_web3.SystemProgram.programId),
|
|
2570
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2571
|
-
meta(ASSOCIATED_TOKEN_PROGRAM_ID),
|
|
2572
|
-
...eventCpiTail(programId)
|
|
2573
|
-
]
|
|
2574
|
-
});
|
|
2575
|
-
}
|
|
2576
|
-
function buildCloseDisputeIx(input) {
|
|
2577
|
-
const { programId, lockId } = input;
|
|
2578
|
-
if (input.mint === null) {
|
|
2579
|
-
return noArgIx(programId, "close_dispute_native", [
|
|
2580
|
-
meta(input.authority, { signer: true, writable: true }),
|
|
2581
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2582
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2583
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2584
|
-
meta(input.payer, { writable: true }),
|
|
2585
|
-
meta(input.payee, { writable: true }),
|
|
2586
|
-
meta(import_web3.SystemProgram.programId),
|
|
2587
|
-
...eventCpiTail(programId)
|
|
2588
|
-
]);
|
|
2589
|
-
}
|
|
2590
|
-
return noArgIx(programId, "close_dispute", [
|
|
2591
|
-
meta(input.authority, { signer: true, writable: true }),
|
|
2592
|
-
meta(deriveConfigPda(programId)),
|
|
2593
|
-
meta(deriveStakeVaultPda(programId), { writable: true }),
|
|
2594
|
-
meta(deriveLockPda(programId, lockId), { writable: true }),
|
|
2595
|
-
meta(input.mint),
|
|
2596
|
-
meta(deriveEscrowPda(programId, lockId), { writable: true }),
|
|
2597
|
-
meta(input.payer, { writable: true }),
|
|
2598
|
-
meta(deriveAta(input.payer, input.mint), { writable: true }),
|
|
2599
|
-
meta(input.payee, { writable: true }),
|
|
2600
|
-
meta(import_web3.SystemProgram.programId),
|
|
2601
|
-
meta(SPL_TOKEN_PROGRAM_ID),
|
|
2602
|
-
meta(ASSOCIATED_TOKEN_PROGRAM_ID),
|
|
2603
|
-
...eventCpiTail(programId)
|
|
2604
|
-
]);
|
|
2605
|
-
}
|
|
2606
|
-
async function fetchLockAccount(conn, programId, delegationId) {
|
|
2607
|
-
const lockId = (0, import_sdk7.deriveLockId)(delegationId);
|
|
2608
|
-
const lockPda = deriveLockPda(programId, lockId);
|
|
2609
|
-
const info = await conn.getAccountInfo(lockPda);
|
|
2610
|
-
if (!info) return null;
|
|
2611
|
-
return { lockId, lockPda, lock: (0, import_sdk7.decodeLockAccount)(Uint8Array.from(info.data)) };
|
|
2612
|
-
}
|
|
2402
|
+
var import_sdk9 = require("@heyanon-arp/sdk");
|
|
2613
2403
|
|
|
2614
2404
|
// src/commands/token-amount.ts
|
|
2615
|
-
var
|
|
2405
|
+
var import_sdk10 = require("@heyanon-arp/sdk");
|
|
2616
2406
|
function toBaseUnits(amountDecimal, decimals) {
|
|
2617
|
-
if (!(0,
|
|
2407
|
+
if (!(0, import_sdk10.isDecimalAmountString)(amountDecimal)) {
|
|
2618
2408
|
throw new Error(`amount '${amountDecimal}' is not a non-negative decimal number`);
|
|
2619
2409
|
}
|
|
2620
2410
|
if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) {
|
|
@@ -2643,8 +2433,8 @@ function normaliseDelegationId(raw) {
|
|
|
2643
2433
|
}
|
|
2644
2434
|
throw new Error(`wallet: --delegation-id must be either 'del_<uuid>' or a bare canonical-lowercase UUID (got '${raw}')`);
|
|
2645
2435
|
}
|
|
2646
|
-
var SPL_TOKEN_PROGRAM_ID2 = new
|
|
2647
|
-
var ASSOCIATED_TOKEN_PROGRAM_ID2 = new
|
|
2436
|
+
var SPL_TOKEN_PROGRAM_ID2 = new import_web3.PublicKey(import_sdk11.SPL_TOKEN_PROGRAM_ID_BASE58);
|
|
2437
|
+
var ASSOCIATED_TOKEN_PROGRAM_ID2 = new import_web3.PublicKey(import_sdk11.ASSOCIATED_TOKEN_PROGRAM_ID_BASE58);
|
|
2648
2438
|
var FALLBACK_RPC_URL = "https://api.mainnet-beta.solana.com";
|
|
2649
2439
|
function resolveRpcUrl(opts) {
|
|
2650
2440
|
if (opts.rpcUrl !== void 0 && opts.rpcUrl !== "") return opts.rpcUrl;
|
|
@@ -2664,7 +2454,7 @@ function redactRpcUrl(url) {
|
|
|
2664
2454
|
return "<redacted>";
|
|
2665
2455
|
}
|
|
2666
2456
|
}
|
|
2667
|
-
var FALLBACK_PROGRAM_ID =
|
|
2457
|
+
var FALLBACK_PROGRAM_ID = import_sdk11.ESCROW_PROGRAM_ID_BASE58;
|
|
2668
2458
|
async function resolveProgramIdWithSource(api, opts) {
|
|
2669
2459
|
if (opts.programId !== void 0 && opts.programId !== "") {
|
|
2670
2460
|
return { programId: opts.programId, source: "flag" };
|
|
@@ -2747,14 +2537,14 @@ function registerDerivePdas(cmd) {
|
|
|
2747
2537
|
async function derivePdasHandler(opts) {
|
|
2748
2538
|
const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
|
|
2749
2539
|
const api = new ArpApiClient(opts.server);
|
|
2750
|
-
const programId = new
|
|
2751
|
-
const lockIdBytes = (0,
|
|
2540
|
+
const programId = new import_web3.PublicKey(await resolveProgramIdStrict(api, opts, "wallet derive-pdas"));
|
|
2541
|
+
const lockIdBytes = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
|
|
2752
2542
|
const lockIdSeed = Buffer.from(lockIdBytes);
|
|
2753
2543
|
const lockIdHex = Buffer.from(lockIdBytes).toString("hex");
|
|
2754
|
-
const [lockPda] =
|
|
2755
|
-
const [escrowPda] =
|
|
2756
|
-
const [configPda] =
|
|
2757
|
-
const [eventAuthorityPda] =
|
|
2544
|
+
const [lockPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("lock"), lockIdSeed], programId);
|
|
2545
|
+
const [escrowPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("escrow"), lockIdSeed], programId);
|
|
2546
|
+
const [configPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("config")], programId);
|
|
2547
|
+
const [eventAuthorityPda] = import_web3.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], programId);
|
|
2758
2548
|
return {
|
|
2759
2549
|
delegation_id: normalisedDelegationId,
|
|
2760
2550
|
lock_id_hex: lockIdHex,
|
|
@@ -2767,11 +2557,11 @@ async function derivePdasHandler(opts) {
|
|
|
2767
2557
|
};
|
|
2768
2558
|
}
|
|
2769
2559
|
var TERMINAL_METHOD = {
|
|
2770
|
-
[
|
|
2771
|
-
[
|
|
2772
|
-
[
|
|
2773
|
-
[
|
|
2774
|
-
[
|
|
2560
|
+
[import_sdk11.LockStates.PAID]: "claim_work_payment",
|
|
2561
|
+
[import_sdk11.LockStates.CANCELED]: "cancel_lock",
|
|
2562
|
+
[import_sdk11.LockStates.REVOKED]: "claim_expired_work",
|
|
2563
|
+
[import_sdk11.LockStates.DISPUTE_RESOLVED]: "resolve_dispute",
|
|
2564
|
+
[import_sdk11.LockStates.DISPUTE_CLOSED]: "close_dispute"
|
|
2775
2565
|
};
|
|
2776
2566
|
function registerVerifyRelease(cmd) {
|
|
2777
2567
|
cmd.command("verify-release").description(
|
|
@@ -2782,7 +2572,7 @@ function registerVerifyRelease(cmd) {
|
|
|
2782
2572
|
).option(
|
|
2783
2573
|
"--program-id <pubkey>",
|
|
2784
2574
|
"Deployed ARP escrow program id. STRICT: flag > ARP_ESCROW_PROGRAM_ID env > GET /v1/escrow/config > FAIL \u2014 a wrong-program read would silently report lock_never_created."
|
|
2785
|
-
).option("--from-did <did>", "Accepted for scripting symmetry with the signing commands; verify-release reads on-chain state only and needs no signer, so this is ignored.").option("--json", "Emit JSON instead of human text. jq-pipeable.", false).action(async (opts) => {
|
|
2575
|
+
).option("--from-did <did>", "Accepted for scripting symmetry with the signing commands; verify-release reads on-chain state only and needs no signer, so this is ignored.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Emit JSON instead of human text. jq-pipeable.", false).action(async (opts) => {
|
|
2786
2576
|
try {
|
|
2787
2577
|
const out = await verifyReleaseHandler(opts);
|
|
2788
2578
|
if (opts.json) {
|
|
@@ -2813,13 +2603,13 @@ function registerVerifyRelease(cmd) {
|
|
|
2813
2603
|
async function verifyReleaseHandler(opts) {
|
|
2814
2604
|
const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
|
|
2815
2605
|
const api = new ArpApiClient(opts.server);
|
|
2816
|
-
const programId = new
|
|
2606
|
+
const programId = new import_web3.PublicKey(await resolveProgramIdStrict(api, opts));
|
|
2817
2607
|
const rpcUrl = resolveRpcUrlStrict(opts);
|
|
2818
|
-
const conn = new
|
|
2819
|
-
const fetched = await fetchLockAccount(conn, programId, normalisedDelegationId);
|
|
2820
|
-
const lockId = (0,
|
|
2821
|
-
const lockPda = deriveLockPda(programId, lockId);
|
|
2822
|
-
const escrowPda = deriveEscrowPda(programId, lockId);
|
|
2608
|
+
const conn = new import_web3.Connection(rpcUrl, "confirmed");
|
|
2609
|
+
const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, normalisedDelegationId);
|
|
2610
|
+
const lockId = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
|
|
2611
|
+
const lockPda = (0, import_sdk9.deriveLockPda)(programId, lockId);
|
|
2612
|
+
const escrowPda = (0, import_sdk9.deriveEscrowPda)(programId, lockId);
|
|
2823
2613
|
if (!fetched) {
|
|
2824
2614
|
return {
|
|
2825
2615
|
delegation_id: normalisedDelegationId,
|
|
@@ -2838,7 +2628,7 @@ async function verifyReleaseHandler(opts) {
|
|
|
2838
2628
|
lock_pda: lockPda.toBase58(),
|
|
2839
2629
|
escrow_pda: escrowPda.toBase58(),
|
|
2840
2630
|
lock_account_exists: true,
|
|
2841
|
-
released: status ===
|
|
2631
|
+
released: status === import_sdk11.LockStates.PAID,
|
|
2842
2632
|
status,
|
|
2843
2633
|
...TERMINAL_METHOD[status] !== void 0 ? { release_method: TERMINAL_METHOD[status] } : {},
|
|
2844
2634
|
lock_state: lock.stateByte,
|
|
@@ -2848,23 +2638,23 @@ async function verifyReleaseHandler(opts) {
|
|
|
2848
2638
|
}
|
|
2849
2639
|
function renderStatusLine(status) {
|
|
2850
2640
|
switch (status) {
|
|
2851
|
-
case
|
|
2641
|
+
case import_sdk11.LockStates.PAID:
|
|
2852
2642
|
return "\u2713 paid \u2014 claim_work_payment landed (buyer approval or post-review self-claim); the payee was paid net of any protocol fee";
|
|
2853
|
-
case
|
|
2643
|
+
case import_sdk11.LockStates.CREATED:
|
|
2854
2644
|
return "\u2717 created \u2014 funded, awaiting the worker accept_lock (stake) \u2014 or a buyer cancel";
|
|
2855
|
-
case
|
|
2645
|
+
case import_sdk11.LockStates.IN_PROGRESS:
|
|
2856
2646
|
return "\u2717 in_progress \u2014 worker accepted + staked; work window running";
|
|
2857
|
-
case
|
|
2647
|
+
case import_sdk11.LockStates.SUBMITTED:
|
|
2858
2648
|
return "\u2717 submitted \u2014 work delivered on-chain; review window running (buyer claims to approve, disputes to refuse; worker self-claims after expiry)";
|
|
2859
|
-
case
|
|
2649
|
+
case import_sdk11.LockStates.DISPUTING:
|
|
2860
2650
|
return "\u2717 disputing \u2014 buyer disputed; operator has the dispute window to rule, after that either party can close";
|
|
2861
|
-
case
|
|
2651
|
+
case import_sdk11.LockStates.CANCELED:
|
|
2862
2652
|
return "\u2717 canceled \u2014 buyer canceled pre-accept; escrow returned";
|
|
2863
|
-
case
|
|
2653
|
+
case import_sdk11.LockStates.REVOKED:
|
|
2864
2654
|
return "\u2717 revoked \u2014 work window lapsed unsubmitted; buyer reclaimed the escrow + the worker stake";
|
|
2865
|
-
case
|
|
2655
|
+
case import_sdk11.LockStates.DISPUTE_RESOLVED:
|
|
2866
2656
|
return "\u2717 dispute_resolved \u2014 operator ruled; winner took the escrow per the on-chain split";
|
|
2867
|
-
case
|
|
2657
|
+
case import_sdk11.LockStates.DISPUTE_CLOSED:
|
|
2868
2658
|
return "\u2717 dispute_closed \u2014 dispute window lapsed unresolved; escrow returned to the buyer, stakes returned";
|
|
2869
2659
|
case "lock_never_created":
|
|
2870
2660
|
return "\u2717 lock_never_created \u2014 no Lock PDA on this cluster/program; create_lock never fired (or wrong --rpc-url/--program-id)";
|
|
@@ -2873,7 +2663,7 @@ function renderStatusLine(status) {
|
|
|
2873
2663
|
function registerCreateLock(cmd) {
|
|
2874
2664
|
cmd.command("create-lock").description(
|
|
2875
2665
|
"Build + sign a create_lock Solana tx (native SOL or an SPL token); output JSON ready for attachments.escrow_lock. This command does NOT submit the tx to chain \u2014 it only signs the blob locally. Run this AFTER the worker accepts your offer; the actual on-chain submission happens inside `heyarp delegation fund <delegation-id> --escrow-lock-from-file <path>` (the server's escrow worker picks up the signed blob from the fund envelope's attachments and posts it). Watch for the `lock_id` appearing on-chain only AFTER `delegation fund` runs, not after this command."
|
|
2876
|
-
).option("--server <url>", "Override server URL for sender-key resolution").option("--from-did <did>", "Sender DID (= payer of the lock). Required when more than one agent on the host.").requiredOption("--delegation-id <id>", "Delegation UUID (drives the lock_id derivation)").requiredOption("--recipient-pubkey <base58>", "Payee Solana pubkey (recipient agent's settlement_pubkey)").option("--amount-lamports <int>", "NATIVE SOL: lock amount in lamports (1 SOL = 1_000_000_000). Required when --mint-pubkey is omitted; not allowed with it.").option("--mint-pubkey <base58>", "SPL token mint to lock. Omit for native SOL. Must be a legacy SPL Token mint (Token-2022 is not supported).").option("--amount-base-units <int>", "SPL: lock amount in the mint's base units (e.g. 1000000 = 1 USDC at 6 decimals). Canonical SPL amount input.").option(
|
|
2666
|
+
).option("--server <url>", "Override server URL for sender-key resolution").option("--from-did <did>", "Sender DID (= payer of the lock). Required when more than one agent on the host.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").requiredOption("--delegation-id <id>", "Delegation UUID (drives the lock_id derivation)").requiredOption("--recipient-pubkey <base58>", "Payee Solana pubkey (recipient agent's settlement_pubkey)").option("--amount-lamports <int>", "NATIVE SOL: lock amount in lamports (1 SOL = 1_000_000_000). Required when --mint-pubkey is omitted; not allowed with it.").option("--mint-pubkey <base58>", "SPL token mint to lock. Omit for native SOL. Must be a legacy SPL Token mint (Token-2022 is not supported).").option("--amount-base-units <int>", "SPL: lock amount in the mint's base units (e.g. 1000000 = 1 USDC at 6 decimals). Canonical SPL amount input.").option(
|
|
2877
2667
|
"--amount <decimal>",
|
|
2878
2668
|
"SPL: lock amount as a human decimal (e.g. 1.5); converted using the mint's on-chain decimals. Convenience alternative to --amount-base-units."
|
|
2879
2669
|
).requiredOption("--condition-hash <hex>", "32-byte hex condition_hash from `heyarp escrow derive-condition-hash` (binds the delegation terms)").option(
|
|
@@ -3007,7 +2797,7 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
|
|
|
3007
2797
|
if (amount === 0n) {
|
|
3008
2798
|
throw new Error("wallet create-lock: lock amount must be greater than zero.");
|
|
3009
2799
|
}
|
|
3010
|
-
const [payerAta] =
|
|
2800
|
+
const [payerAta] = import_web3.PublicKey.findProgramAddressSync([payer.toBuffer(), SPL_TOKEN_PROGRAM_ID2.toBuffer(), mint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID2);
|
|
3011
2801
|
const ataInfo = await conn.getAccountInfo(payerAta);
|
|
3012
2802
|
if (!ataInfo) {
|
|
3013
2803
|
throw new Error(
|
|
@@ -3017,8 +2807,8 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
|
|
|
3017
2807
|
if (ataInfo.data.length < 72) {
|
|
3018
2808
|
throw new Error(`wallet create-lock: payer token account ${payerAta.toBase58()} is malformed (data length ${ataInfo.data.length} < 72).`);
|
|
3019
2809
|
}
|
|
3020
|
-
const ataMint = new
|
|
3021
|
-
const ataOwner = new
|
|
2810
|
+
const ataMint = new import_web3.PublicKey(ataInfo.data.subarray(0, 32));
|
|
2811
|
+
const ataOwner = new import_web3.PublicKey(ataInfo.data.subarray(32, 64));
|
|
3022
2812
|
if (!ataMint.equals(mint)) {
|
|
3023
2813
|
throw new Error(`wallet create-lock: payer token account ${payerAta.toBase58()} is for mint ${ataMint.toBase58()}, not ${mint.toBase58()}.`);
|
|
3024
2814
|
}
|
|
@@ -3039,7 +2829,7 @@ async function resolveCreateLockAsset(conn, opts, payer, clusterCaip2) {
|
|
|
3039
2829
|
};
|
|
3040
2830
|
}
|
|
3041
2831
|
async function createLockHandler(opts) {
|
|
3042
|
-
const agent = resolveSenderAgent("wallet create-lock", opts.server, opts.fromDid);
|
|
2832
|
+
const agent = resolveSenderAgent("wallet create-lock", opts.server, opts.fromDid, opts.from);
|
|
3043
2833
|
const payerKp = keypairFromAgent(agent);
|
|
3044
2834
|
const normalisedDelegationId = normaliseDelegationId(opts.delegationId);
|
|
3045
2835
|
const payee = parsePubkey(opts.recipientPubkey, "--recipient-pubkey");
|
|
@@ -3050,18 +2840,18 @@ async function createLockHandler(opts) {
|
|
|
3050
2840
|
if (clusterTag !== 0 && clusterTag !== 1) {
|
|
3051
2841
|
throw new Error(`--cluster-tag must be 0 (devnet) or 1 (mainnet) (got ${clusterTag})`);
|
|
3052
2842
|
}
|
|
3053
|
-
const clusterCaip2 = clusterTag === 1 ?
|
|
2843
|
+
const clusterCaip2 = clusterTag === 1 ? import_sdk11.SOLANA_CLUSTER_IDS["solana-mainnet"] : import_sdk11.SOLANA_CLUSTER_IDS["solana-devnet"];
|
|
3054
2844
|
const expectedLockAsset = typeof opts.mintPubkey === "string" && opts.mintPubkey !== "" ? { kind: "spl", mint: parsePubkey(opts.mintPubkey, "--mint-pubkey").toBase58(), cluster: clusterCaip2 } : { kind: "native" };
|
|
3055
2845
|
if (!offlineMode) {
|
|
3056
2846
|
await preflightLockCurrency(api, agent, normalisedDelegationId, expectedLockAsset);
|
|
3057
2847
|
}
|
|
3058
|
-
const programId = new
|
|
2848
|
+
const programId = new import_web3.PublicKey(await resolveProgramId(api, opts));
|
|
3059
2849
|
const rpcUrl = resolveRpcUrl(opts);
|
|
3060
|
-
const conn = new
|
|
2850
|
+
const conn = new import_web3.Connection(rpcUrl, "confirmed");
|
|
3061
2851
|
const asset = await resolveCreateLockAsset(conn, opts, payerKp.publicKey, clusterCaip2);
|
|
3062
2852
|
const amount = asset.amount;
|
|
3063
|
-
const lockIdBytes = (0,
|
|
3064
|
-
const ix = buildCreateLockIx({
|
|
2853
|
+
const lockIdBytes = (0, import_sdk11.deriveLockId)(normalisedDelegationId);
|
|
2854
|
+
const ix = (0, import_sdk9.buildCreateLockIx)({
|
|
3065
2855
|
programId,
|
|
3066
2856
|
lockId: lockIdBytes,
|
|
3067
2857
|
payer: payerKp.publicKey,
|
|
@@ -3070,11 +2860,14 @@ async function createLockHandler(opts) {
|
|
|
3070
2860
|
conditionHash,
|
|
3071
2861
|
mint: asset.kind === "spl" ? asset.mint : null
|
|
3072
2862
|
});
|
|
3073
|
-
const tx = new
|
|
2863
|
+
const tx = new import_web3.Transaction().add(ix);
|
|
3074
2864
|
tx.feePayer = payerKp.publicKey;
|
|
3075
|
-
const { blockhash } = await conn.getLatestBlockhash("confirmed");
|
|
2865
|
+
const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash("confirmed");
|
|
3076
2866
|
tx.recentBlockhash = blockhash;
|
|
3077
2867
|
tx.sign(payerKp);
|
|
2868
|
+
process.stderr.write(
|
|
2869
|
+
"\u26A0 create-lock: this signed blob is valid for only ~60-90s \u2014 run `heyarp delegation fund` NOW. If you wait, the create_lock tx is silently dropped on-chain and the delegation fails; re-run create-lock to retry.\n"
|
|
2870
|
+
);
|
|
3078
2871
|
const blob = tx.serialize({ requireAllSignatures: true, verifySignatures: true });
|
|
3079
2872
|
return {
|
|
3080
2873
|
signed_tx_blob: blob.toString("base64"),
|
|
@@ -3097,22 +2890,26 @@ async function createLockHandler(opts) {
|
|
|
3097
2890
|
// Record the program id the create_lock ix was built against.
|
|
3098
2891
|
// `delegation offer` cross-checks this pre-flight so a stale
|
|
3099
2892
|
// ESCRoW... fallback lock doesn't ship silently.
|
|
3100
|
-
program_id: programId.toBase58()
|
|
2893
|
+
program_id: programId.toBase58(),
|
|
2894
|
+
// Blockhash + its expiry slot — the ~60-90s submission window for
|
|
2895
|
+
// this blob (see CreateLockOutput docs).
|
|
2896
|
+
blockhash,
|
|
2897
|
+
last_valid_block_height: lastValidBlockHeight
|
|
3101
2898
|
};
|
|
3102
2899
|
}
|
|
3103
2900
|
function keypairFromAgent(agent) {
|
|
3104
2901
|
const stored = base64ToBytes(agent.settlementSecretKeyB64);
|
|
3105
2902
|
if (stored.length === 32) {
|
|
3106
|
-
return
|
|
2903
|
+
return import_web3.Keypair.fromSeed(stored);
|
|
3107
2904
|
}
|
|
3108
2905
|
if (stored.length === 64) {
|
|
3109
|
-
return
|
|
2906
|
+
return import_web3.Keypair.fromSecretKey(stored);
|
|
3110
2907
|
}
|
|
3111
2908
|
throw new Error(`agent ${agent.did}: settlementSecretKeyB64 must decode to 32 bytes (Ed25519 seed) or 64 bytes (Solana expanded form); got ${stored.length}`);
|
|
3112
2909
|
}
|
|
3113
2910
|
function parsePubkey(value, flag) {
|
|
3114
2911
|
try {
|
|
3115
|
-
return new
|
|
2912
|
+
return new import_web3.PublicKey(value);
|
|
3116
2913
|
} catch (err) {
|
|
3117
2914
|
throw new Error(`${flag}: invalid base58 pubkey '${value}': ${err.message}`);
|
|
3118
2915
|
}
|
|
@@ -3145,7 +2942,7 @@ function registerDelegationCommands(root) {
|
|
|
3145
2942
|
registerCancel(cmd);
|
|
3146
2943
|
}
|
|
3147
2944
|
function registerOffer(parent) {
|
|
3148
|
-
parent.command("offer").description("Open a new delegation addressed to <recipient-did> with the agreed terms INLINE (no escrow lock \u2014 fund AFTER acceptance via `delegation fund`).").argument("<recipient
|
|
2945
|
+
parent.command("offer").description("Open a new delegation addressed to <recipient-did> with the agreed terms INLINE (no escrow lock \u2014 fund AFTER acceptance via `delegation fund`).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--delegation-id <uuid>", "Override the auto-generated delegation id (UUID). Reuse the SAME id at `heyarp delegation fund` time. Useful for replay / scripting.").option("--title <s>", "Required: human-readable title for the offer").option("--brief <json>", "Optional structured brief (JSON object)").option("--criterion <s>", "acceptance_criteria \u2014 repeatable; pass --criterion once per bullet", collectRepeated, []).option("--deadline <rfc3339>", 'Optional RFC 3339 deadline (e.g. "2026-12-31T23:59:59Z")').option("--scope <text>", "scope_summary \u2014 short prose describing the agreed work. Required.").option("--amount <s>", 'Optional decimal-as-string amount (e.g. "10.00"). REQUIRES --currency if set.').option("--currency <s>", `Asset identifier: shorthand (${import_sdk12.WELL_KNOWN_ASSET_KEYS.join("|")}) OR raw CAIP-19 string.`).option("--currency-decimals <n>", "Decimal places for base-unit conversion (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3149
2946
|
"--json",
|
|
3150
2947
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"offer", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + the "reference this delegation" hints move to stderr; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
3151
2948
|
false
|
|
@@ -3260,16 +3057,16 @@ async function runOffer(recipientDid, opts) {
|
|
|
3260
3057
|
"delegation offer: --verbose and --json are mutually exclusive. --json emits the structured server response; --verbose adds dumps that would break `--json | jq`."
|
|
3261
3058
|
);
|
|
3262
3059
|
}
|
|
3263
|
-
|
|
3060
|
+
recipientDid = await resolveRecipient(opts.server, "delegation offer", recipientDid, { json: opts.json });
|
|
3264
3061
|
const ttlSeconds = parseTtl("delegation offer", opts.ttl);
|
|
3265
3062
|
if (!opts.title || opts.title.length === 0) {
|
|
3266
3063
|
throw new Error("delegation offer: --title is required (server-side validator rejects empty offers)");
|
|
3267
3064
|
}
|
|
3268
3065
|
const terms = parseOfferTerms("delegation offer", opts);
|
|
3269
3066
|
const offeredAssetId = terms.currency?.asset_id;
|
|
3270
|
-
if (offeredAssetId && !(0,
|
|
3067
|
+
if (offeredAssetId && !(0, import_sdk12.isWhitelistedAssetId)(offeredAssetId)) {
|
|
3271
3068
|
console.error(
|
|
3272
|
-
|
|
3069
|
+
import_chalk9.default.yellow(
|
|
3273
3070
|
`warning: currency '${offeredAssetId}' is not in the static payment whitelist \u2014 the server will reject the offer (DELEGATION_ASSET_NOT_ALLOWED) unless its deploy registers this asset. See 'heyarp assets'.`
|
|
3274
3071
|
)
|
|
3275
3072
|
);
|
|
@@ -3286,45 +3083,45 @@ async function runOffer(recipientDid, opts) {
|
|
|
3286
3083
|
);
|
|
3287
3084
|
}
|
|
3288
3085
|
const api = new ArpApiClient(opts.server);
|
|
3289
|
-
const sender = resolveSenderAgent("delegation offer", opts.server, opts.fromDid);
|
|
3086
|
+
const sender = resolveSenderAgent("delegation offer", opts.server, opts.fromDid, opts.from);
|
|
3290
3087
|
const content = {
|
|
3291
|
-
action:
|
|
3088
|
+
action: import_sdk12.DelegationActions.OFFER,
|
|
3292
3089
|
delegation_id: delegationId,
|
|
3293
3090
|
title: opts.title,
|
|
3294
3091
|
...terms
|
|
3295
3092
|
};
|
|
3296
3093
|
const body = { type: "delegation", content };
|
|
3297
|
-
progress(opts.json,
|
|
3298
|
-
progress(opts.json,
|
|
3299
|
-
progress(opts.json,
|
|
3300
|
-
progress(opts.json,
|
|
3094
|
+
progress(opts.json, import_chalk9.default.dim(`Server: ${api.serverUrl}`));
|
|
3095
|
+
progress(opts.json, import_chalk9.default.dim(`Sender: ${sender.did}`));
|
|
3096
|
+
progress(opts.json, import_chalk9.default.dim(`Recipient: ${recipientDid}`));
|
|
3097
|
+
progress(opts.json, import_chalk9.default.dim(`Delegation: ${delegationId}`));
|
|
3301
3098
|
let result;
|
|
3302
3099
|
try {
|
|
3303
3100
|
result = await sendDelegationEnvelope({ api, sender, recipientDid, body, ttlSeconds, verbose: opts.verbose, server: opts.server });
|
|
3304
3101
|
} catch (err) {
|
|
3305
|
-
if (err instanceof ApiError && err.payload.code ===
|
|
3102
|
+
if (err instanceof ApiError && err.payload.code === import_sdk12.DelegationOfferRejectionCodes.ASSET_NOT_ALLOWED) {
|
|
3306
3103
|
const d = err.payload.details;
|
|
3307
|
-
console.error(
|
|
3104
|
+
console.error(import_chalk9.default.yellow(`
|
|
3308
3105
|
The server's payment-asset whitelist rejected this currency.`));
|
|
3309
3106
|
if (d !== void 0) {
|
|
3310
|
-
console.error(
|
|
3311
|
-
console.error(
|
|
3107
|
+
console.error(import_chalk9.default.dim(` offered: ${JSON.stringify(d.offered)}`));
|
|
3108
|
+
console.error(import_chalk9.default.dim(` accepted: ${JSON.stringify(d.accepted)}`));
|
|
3312
3109
|
}
|
|
3313
|
-
console.error(
|
|
3110
|
+
console.error(import_chalk9.default.dim(`
|
|
3314
3111
|
See the whitelist (shorthand keys + canonical decimals):
|
|
3315
3112
|
heyarp assets
|
|
3316
3113
|
then re-offer with a whitelisted --currency.`));
|
|
3317
3114
|
}
|
|
3318
|
-
if (err instanceof ApiError && err.payload.code ===
|
|
3115
|
+
if (err instanceof ApiError && err.payload.code === import_sdk12.DelegationOfferRejectionCodes.PRICING_MISMATCH) {
|
|
3319
3116
|
const d = err.payload.details;
|
|
3320
|
-
console.error(
|
|
3117
|
+
console.error(import_chalk9.default.yellow(`
|
|
3321
3118
|
The recipient's published accept-prefs rejected this offer${d?.reason ? ` (mismatch: ${d.reason})` : ""}.`));
|
|
3322
3119
|
if (d !== void 0) {
|
|
3323
|
-
console.error(
|
|
3324
|
-
console.error(
|
|
3120
|
+
console.error(import_chalk9.default.dim(` accepted: ${JSON.stringify(d.accepted)}`));
|
|
3121
|
+
console.error(import_chalk9.default.dim(` offered: ${JSON.stringify(d.offered)}`));
|
|
3325
3122
|
}
|
|
3326
3123
|
console.error(
|
|
3327
|
-
|
|
3124
|
+
import_chalk9.default.dim(
|
|
3328
3125
|
`
|
|
3329
3126
|
Check what the recipient accepts BEFORE offering:
|
|
3330
3127
|
heyarp agents accept-prefs show ${recipientDid}
|
|
@@ -3332,12 +3129,12 @@ then re-run with matching --currency / --amount.`
|
|
|
3332
3129
|
)
|
|
3333
3130
|
);
|
|
3334
3131
|
}
|
|
3335
|
-
if (err instanceof ApiError && err.payload.code ===
|
|
3132
|
+
if (err instanceof ApiError && err.payload.code === import_sdk12.DelegationOfferRejectionCodes.CAPACITY_EXCEEDED) {
|
|
3336
3133
|
const d = err.payload.details;
|
|
3337
3134
|
const cap = d?.maxActive === 0 ? "closed for new offers (busy)" : `at capacity (${d?.currentActive}/${d?.maxActive} active delegations)`;
|
|
3338
|
-
console.error(
|
|
3135
|
+
console.error(import_chalk9.default.yellow(`
|
|
3339
3136
|
The recipient is ${cap}.`));
|
|
3340
|
-
console.error(
|
|
3137
|
+
console.error(import_chalk9.default.dim("\nThis is TRANSIENT \u2014 your terms are fine. Retry the same offer later, or pick another worker (`heyarp agents --tag \u2026`)."));
|
|
3341
3138
|
}
|
|
3342
3139
|
throw err;
|
|
3343
3140
|
}
|
|
@@ -3355,15 +3152,15 @@ The recipient is ${cap}.`));
|
|
|
3355
3152
|
});
|
|
3356
3153
|
} else {
|
|
3357
3154
|
printIngestResult(result);
|
|
3358
|
-
console.log(
|
|
3155
|
+
console.log(import_chalk9.default.dim(`
|
|
3359
3156
|
Reference this delegation on subsequent calls with:`));
|
|
3360
|
-
console.log(
|
|
3361
|
-
console.log(
|
|
3362
|
-
console.log(
|
|
3363
|
-
console.log(
|
|
3157
|
+
console.log(import_chalk9.default.dim(` heyarp delegation accept ${result.relationshipId} ${delegationId}`));
|
|
3158
|
+
console.log(import_chalk9.default.dim(` heyarp delegation decline ${result.relationshipId} ${delegationId}`));
|
|
3159
|
+
console.log(import_chalk9.default.dim(` heyarp delegation cancel ${result.relationshipId} ${delegationId}`));
|
|
3160
|
+
console.log(import_chalk9.default.dim(`
|
|
3364
3161
|
After the worker accepts, fund the escrow lock:`));
|
|
3365
|
-
console.log(
|
|
3366
|
-
console.log(
|
|
3162
|
+
console.log(import_chalk9.default.dim(` heyarp wallet create-lock --delegation-id ${delegationId} --condition-hash <hex> ... > lock.json`));
|
|
3163
|
+
console.log(import_chalk9.default.dim(` heyarp delegation fund ${delegationId} --escrow-lock-from-file lock.json`));
|
|
3367
3164
|
}
|
|
3368
3165
|
if (opts.waitUntil && !opts.json) {
|
|
3369
3166
|
const untilPhase = parseUntilPhase(opts.waitUntil);
|
|
@@ -3385,7 +3182,7 @@ After the worker accepts, fund the escrow lock:`));
|
|
|
3385
3182
|
}
|
|
3386
3183
|
}
|
|
3387
3184
|
function registerFund(parent) {
|
|
3388
|
-
parent.command("fund").description("Fund an ACCEPTED delegation with the escrow lock (buyer-only). Run AFTER the worker accepts the offer.").argument("<delegation-id>", "Delegation UUID (the one you offered + the worker accepted)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", `Envelope TTL in seconds (max ${
|
|
3185
|
+
parent.command("fund").description("Fund an ACCEPTED delegation with the escrow lock (buyer-only). Run AFTER the worker accepts the offer.").argument("<delegation-id>", "Delegation UUID (the one you offered + the worker accepted)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk12.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3389
3186
|
"--json",
|
|
3390
3187
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"fund", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude moves off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
3391
3188
|
false
|
|
@@ -3426,7 +3223,7 @@ async function runFund(delegationId, opts) {
|
|
|
3426
3223
|
);
|
|
3427
3224
|
}
|
|
3428
3225
|
const api = new ArpApiClient(opts.server);
|
|
3429
|
-
const sender = resolveSenderAgent("delegation fund", opts.server, opts.fromDid);
|
|
3226
|
+
const sender = resolveSenderAgent("delegation fund", opts.server, opts.fromDid, opts.from);
|
|
3430
3227
|
const signer = makeSigner(sender);
|
|
3431
3228
|
const resolved = await resolveFundRefs("delegation fund", api, signer, { delegationId, selfDid: sender.did });
|
|
3432
3229
|
if (escrowResult.lockProgramId !== void 0) {
|
|
@@ -3443,23 +3240,23 @@ async function runFund(delegationId, opts) {
|
|
|
3443
3240
|
}
|
|
3444
3241
|
if (result2.kind === "skipped_no_expected_program_id") {
|
|
3445
3242
|
console.error(
|
|
3446
|
-
|
|
3243
|
+
import_chalk9.default.yellow(
|
|
3447
3244
|
"\u26A0 delegation fund: no authoritative expected program-id available (--program-id missing, ARP_ESCROW_PROGRAM_ID env unset, server protocol-fee unreachable). Pre-flight skipped; server-side ESC_LOCK_TX_PROGRAM_ID_MISMATCH check is the only backstop. Set ARP_ESCROW_PROGRAM_ID or pass --program-id to enable pre-flight."
|
|
3448
3245
|
)
|
|
3449
3246
|
);
|
|
3450
3247
|
}
|
|
3451
3248
|
}
|
|
3452
|
-
const content = { action:
|
|
3249
|
+
const content = { action: import_sdk12.DelegationActions.FUND, delegation_id: delegationId };
|
|
3453
3250
|
const body = { type: "delegation", content };
|
|
3454
3251
|
const attachments = { escrow_lock: escrowResult.attachment };
|
|
3455
|
-
progress(opts.json,
|
|
3456
|
-
progress(opts.json,
|
|
3457
|
-
progress(opts.json,
|
|
3458
|
-
progress(opts.json,
|
|
3459
|
-
progress(opts.json,
|
|
3252
|
+
progress(opts.json, import_chalk9.default.dim(`Server: ${api.serverUrl}`));
|
|
3253
|
+
progress(opts.json, import_chalk9.default.dim(`Sender: ${sender.did}`));
|
|
3254
|
+
progress(opts.json, import_chalk9.default.dim(`Recipient: ${resolved.recipientDid}`));
|
|
3255
|
+
progress(opts.json, import_chalk9.default.dim(`Relationship: ${resolved.relationshipId}`));
|
|
3256
|
+
progress(opts.json, import_chalk9.default.dim(`Delegation: ${delegationId} (action=fund)`));
|
|
3460
3257
|
{
|
|
3461
3258
|
const a = escrowResult.attachment;
|
|
3462
|
-
progress(opts.json,
|
|
3259
|
+
progress(opts.json, import_chalk9.default.dim(`Escrow lock attached: lock_id=${a.lock_id} amount=${a.amount} asset_id=${a.asset_id}`));
|
|
3463
3260
|
}
|
|
3464
3261
|
const result = await sendDelegationEnvelope({
|
|
3465
3262
|
api,
|
|
@@ -3485,7 +3282,7 @@ async function runFund(delegationId, opts) {
|
|
|
3485
3282
|
});
|
|
3486
3283
|
} else {
|
|
3487
3284
|
printIngestResult(result);
|
|
3488
|
-
console.log(
|
|
3285
|
+
console.log(import_chalk9.default.dim("\nThe worker waits for the on-chain lock to confirm (LOCKED), then begins work."));
|
|
3489
3286
|
}
|
|
3490
3287
|
if (opts.waitUntil && !opts.json) {
|
|
3491
3288
|
const untilPhase = parseUntilPhase(opts.waitUntil);
|
|
@@ -3534,7 +3331,7 @@ async function resolveFundRefs(cmdName, api, signer, args) {
|
|
|
3534
3331
|
);
|
|
3535
3332
|
}
|
|
3536
3333
|
function registerAccept(parent) {
|
|
3537
|
-
parent.command("accept").description("Accept a PROPOSED delegation \u2014 promotes to ACCEPTED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3334
|
+
parent.command("accept").description("Accept a PROPOSED delegation \u2014 promotes to ACCEPTED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3538
3335
|
"--json",
|
|
3539
3336
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"accept", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + pending-lock poll chatter move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
3540
3337
|
false
|
|
@@ -3546,11 +3343,11 @@ function registerAccept(parent) {
|
|
|
3546
3343
|
});
|
|
3547
3344
|
}
|
|
3548
3345
|
function registerDecline(parent) {
|
|
3549
|
-
parent.command("decline").description("Decline a PROPOSED delegation \u2014 moves to DECLINED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").requiredOption(
|
|
3346
|
+
parent.command("decline").description("Decline a PROPOSED delegation \u2014 moves to DECLINED. Counterparty-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").requiredOption(
|
|
3550
3347
|
"--reason <code>",
|
|
3551
3348
|
// surface the closed enum at help time so operators
|
|
3552
3349
|
// don't have to read source to find acceptable values.
|
|
3553
|
-
`Required: decline reason code (one of: ${
|
|
3350
|
+
`Required: decline reason code (one of: ${import_sdk12.DECLINE_REASONS.join(", ")}). Carried in body.content.reason so the counterparty's reactor can branch on it.`
|
|
3554
3351
|
).option("--reason-detail <s>", 'Optional free-text elaboration alongside --reason (e.g. "rate floor 0.20 USDC"). Max 512 chars.').option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3555
3352
|
"--json",
|
|
3556
3353
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"decline", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + pending-lock poll chatter move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
@@ -3563,7 +3360,7 @@ function registerDecline(parent) {
|
|
|
3563
3360
|
});
|
|
3564
3361
|
}
|
|
3565
3362
|
function registerCancel(parent) {
|
|
3566
|
-
parent.command("cancel").description("Cancel an OFFERED delegation \u2014 moves to CANCELED. Offerer-only (the OTHER side uses decline).").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3363
|
+
parent.command("cancel").description("Cancel an OFFERED delegation \u2014 moves to CANCELED. Offerer-only (the OTHER side uses decline).").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Delegation UUID").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
3567
3364
|
"--json",
|
|
3568
3365
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"cancel", delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + pending-lock poll chatter move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
3569
3366
|
false
|
|
@@ -3587,16 +3384,16 @@ async function runFollowupAction(relationshipId, delegationId, action, opts) {
|
|
|
3587
3384
|
const lockWaitTimeoutSec = parseLockWaitTimeout(cmdName, opts.lockWaitTimeout);
|
|
3588
3385
|
const lockWaitIntervalSec = parseLockWaitInterval(cmdName, opts.lockWaitInterval);
|
|
3589
3386
|
let declinePayload = null;
|
|
3590
|
-
if (action ===
|
|
3387
|
+
if (action === import_sdk12.DelegationActions.DECLINE) {
|
|
3591
3388
|
const reason = parseDeclineReason(cmdName, opts.reason);
|
|
3592
3389
|
const validatedDetail = parseReasonDetail(cmdName, opts.reasonDetail);
|
|
3593
3390
|
declinePayload = validatedDetail ? { reason, reasonDetail: validatedDetail } : { reason };
|
|
3594
3391
|
}
|
|
3595
3392
|
const api = new ArpApiClient(opts.server);
|
|
3596
|
-
const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid);
|
|
3393
|
+
const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid, opts.from);
|
|
3597
3394
|
const signer = makeSigner(sender);
|
|
3598
3395
|
const resolved = await resolveDelegationRefs(cmdName, api, signer, { relationshipId, delegationId, action, selfDid: sender.did });
|
|
3599
|
-
if (resolved.state ===
|
|
3396
|
+
if (resolved.state === import_sdk12.DelegationStates.PENDING_LOCK_FINALIZATION && opts.waitForLock !== false) {
|
|
3600
3397
|
await awaitDelegationLockFinalized(cmdName, api, signer, {
|
|
3601
3398
|
relationshipId,
|
|
3602
3399
|
delegationId,
|
|
@@ -3618,10 +3415,10 @@ async function runFollowupAction(relationshipId, delegationId, action, opts) {
|
|
|
3618
3415
|
if (declinePayload.reasonDetail) content.reason_detail = declinePayload.reasonDetail;
|
|
3619
3416
|
}
|
|
3620
3417
|
const body = { type: "delegation", content };
|
|
3621
|
-
progress(opts.json,
|
|
3622
|
-
progress(opts.json,
|
|
3623
|
-
progress(opts.json,
|
|
3624
|
-
progress(opts.json,
|
|
3418
|
+
progress(opts.json, import_chalk9.default.dim(`Server: ${api.serverUrl}`));
|
|
3419
|
+
progress(opts.json, import_chalk9.default.dim(`Sender: ${sender.did}`));
|
|
3420
|
+
progress(opts.json, import_chalk9.default.dim(`Relationship: ${relationshipId}`));
|
|
3421
|
+
progress(opts.json, import_chalk9.default.dim(`Delegation: ${delegationId} (action=${action}${action === import_sdk12.DelegationActions.DECLINE ? `, reason=${content.reason}` : ""})`));
|
|
3625
3422
|
const result = await sendDelegationEnvelope({
|
|
3626
3423
|
api,
|
|
3627
3424
|
sender,
|
|
@@ -3650,9 +3447,9 @@ async function runFollowupAction(relationshipId, delegationId, action, opts) {
|
|
|
3650
3447
|
async function sendDelegationEnvelope(args) {
|
|
3651
3448
|
const nextSequence = (args.sender.lastSenderSequence ?? 0) + 1;
|
|
3652
3449
|
const protectedBlock = {
|
|
3653
|
-
protocol_version:
|
|
3654
|
-
purpose:
|
|
3655
|
-
message_id: (0,
|
|
3450
|
+
protocol_version: import_sdk12.CURRENT_PROTOCOL_VERSION,
|
|
3451
|
+
purpose: import_sdk12.Purpose.ENVELOPE,
|
|
3452
|
+
message_id: (0, import_sdk12.uuidV4)(),
|
|
3656
3453
|
sender_did: args.sender.did,
|
|
3657
3454
|
recipient_did: args.recipientDid,
|
|
3658
3455
|
// `relationship_id: null` matches the handshake
|
|
@@ -3661,20 +3458,20 @@ async function sendDelegationEnvelope(args) {
|
|
|
3661
3458
|
// existing relationship row.
|
|
3662
3459
|
relationship_id: null,
|
|
3663
3460
|
sender_sequence: nextSequence,
|
|
3664
|
-
sender_nonce: (0,
|
|
3665
|
-
timestamp: (0,
|
|
3666
|
-
expires_at: (0,
|
|
3461
|
+
sender_nonce: (0, import_sdk12.senderNonce)(),
|
|
3462
|
+
timestamp: (0, import_sdk12.rfc3339)(),
|
|
3463
|
+
expires_at: (0, import_sdk12.expiresAt)(args.ttlSeconds),
|
|
3667
3464
|
delivery_id: null
|
|
3668
3465
|
};
|
|
3669
3466
|
const signer = makeSigner(args.sender);
|
|
3670
|
-
const envelope = (0,
|
|
3467
|
+
const envelope = (0, import_sdk12.signEnvelope)({
|
|
3671
3468
|
protected: protectedBlock,
|
|
3672
3469
|
body: args.body,
|
|
3673
3470
|
identitySecretKey: signer.identitySecretKey,
|
|
3674
3471
|
attachments: args.attachments
|
|
3675
3472
|
});
|
|
3676
3473
|
if (args.verbose) {
|
|
3677
|
-
console.log(
|
|
3474
|
+
console.log(import_chalk9.default.bold("\nEnvelope (pre-send):"));
|
|
3678
3475
|
console.log(formatJson(envelope));
|
|
3679
3476
|
}
|
|
3680
3477
|
try {
|
|
@@ -3682,7 +3479,7 @@ async function sendDelegationEnvelope(args) {
|
|
|
3682
3479
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
3683
3480
|
return result;
|
|
3684
3481
|
} catch (err) {
|
|
3685
|
-
if (err instanceof ApiError && (0,
|
|
3482
|
+
if (err instanceof ApiError && (0, import_sdk12.isPostCommitErrorCode)(err.payload.code)) {
|
|
3686
3483
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
3687
3484
|
}
|
|
3688
3485
|
throw err;
|
|
@@ -3704,7 +3501,7 @@ async function resolveDelegationRefs(cmdName, api, signer, args) {
|
|
|
3704
3501
|
);
|
|
3705
3502
|
}
|
|
3706
3503
|
let recipientDid;
|
|
3707
|
-
if (args.action ===
|
|
3504
|
+
if (args.action === import_sdk12.DelegationActions.CANCEL) {
|
|
3708
3505
|
const firstEvents = await api.listEvents(args.relationshipId, signer, { since: 0, limit: 1 });
|
|
3709
3506
|
const handshake = firstEvents[0];
|
|
3710
3507
|
if (!handshake) {
|
|
@@ -3729,7 +3526,7 @@ async function resolveDelegationRefs(cmdName, api, signer, args) {
|
|
|
3729
3526
|
async function awaitDelegationLockFinalized(cmdName, api, signer, args) {
|
|
3730
3527
|
const log = args.log ?? ((line) => console.log(line));
|
|
3731
3528
|
log(
|
|
3732
|
-
|
|
3529
|
+
import_chalk9.default.dim(
|
|
3733
3530
|
`
|
|
3734
3531
|
[--wait-for-lock] delegation ${args.delegationId} is awaiting on-chain lock confirmation; polling until ready (interval=${args.intervalSec}s timeout=${args.timeoutSec}s)`
|
|
3735
3532
|
)
|
|
@@ -3744,7 +3541,7 @@ async function awaitDelegationLockFinalized(cmdName, api, signer, args) {
|
|
|
3744
3541
|
after = page[page.length - 1].id;
|
|
3745
3542
|
}
|
|
3746
3543
|
};
|
|
3747
|
-
const outcome = await (0,
|
|
3544
|
+
const outcome = await (0, import_sdk12.pollUntil)({
|
|
3748
3545
|
fetch: fetchRow,
|
|
3749
3546
|
// Match on either "row not found at all" OR "state moved
|
|
3750
3547
|
// past pending_lock_finalization". The post-poll branch
|
|
@@ -3754,7 +3551,7 @@ async function awaitDelegationLockFinalized(cmdName, api, signer, args) {
|
|
|
3754
3551
|
// rows return cleanly. Polling on null would loop pointlessly
|
|
3755
3552
|
// until the deadline fires and surface a misleading "timed
|
|
3756
3553
|
// out" message for what's actually a wrong-id problem.
|
|
3757
|
-
predicate: (row2) => row2 === null || row2.state !==
|
|
3554
|
+
predicate: (row2) => row2 === null || row2.state !== import_sdk12.DelegationStates.PENDING_LOCK_FINALIZATION,
|
|
3758
3555
|
intervalMs: args.intervalSec * 1e3,
|
|
3759
3556
|
timeoutMs: args.timeoutSec * 1e3,
|
|
3760
3557
|
// Swallow ONLY transient errors. A 4xx during the poll is a
|
|
@@ -3768,7 +3565,7 @@ async function awaitDelegationLockFinalized(cmdName, api, signer, args) {
|
|
|
3768
3565
|
if (err instanceof ApiError && err.status >= 400 && err.status < 500) {
|
|
3769
3566
|
throw err;
|
|
3770
3567
|
}
|
|
3771
|
-
log(
|
|
3568
|
+
log(import_chalk9.default.dim(` poll: transient fetch error (${err instanceof Error ? err.message : String(err)})`));
|
|
3772
3569
|
}
|
|
3773
3570
|
});
|
|
3774
3571
|
if (outcome.kind === "timeout") {
|
|
@@ -3785,12 +3582,12 @@ async function awaitDelegationLockFinalized(cmdName, api, signer, args) {
|
|
|
3785
3582
|
`${cmdName}: delegation ${args.delegationId} disappeared from relationship ${args.relationshipId} during --wait-for-lock pre-flight. Re-check the delegation id with \`heyarp delegations ${args.relationshipId}\`.`
|
|
3786
3583
|
);
|
|
3787
3584
|
}
|
|
3788
|
-
if (row.state !==
|
|
3585
|
+
if (row.state !== import_sdk12.DelegationStates.OFFERED) {
|
|
3789
3586
|
throw new Error(
|
|
3790
3587
|
`${cmdName}: delegation ${args.delegationId} transitioned to '${row.state}' while waiting for on-chain lock confirmation; cannot ${args.action}. Re-read the delegation timeline with \`heyarp delegations ${args.relationshipId}\` to see the latest state.`
|
|
3791
3588
|
);
|
|
3792
3589
|
}
|
|
3793
|
-
log(
|
|
3590
|
+
log(import_chalk9.default.dim(`[--wait-for-lock] delegation ${args.delegationId} ready (state=${row.state}); proceeding with ${args.action}.`));
|
|
3794
3591
|
return row;
|
|
3795
3592
|
}
|
|
3796
3593
|
function parseLockWaitTimeout(cmdName, raw) {
|
|
@@ -3816,12 +3613,12 @@ function parseLockWaitInterval(cmdName, raw) {
|
|
|
3816
3613
|
return n;
|
|
3817
3614
|
}
|
|
3818
3615
|
function printIngestResult(result) {
|
|
3819
|
-
console.log(
|
|
3820
|
-
console.log(`${
|
|
3821
|
-
console.log(`${
|
|
3822
|
-
console.log(`${
|
|
3823
|
-
console.log(`${
|
|
3824
|
-
console.log(`${
|
|
3616
|
+
console.log(import_chalk9.default.green("\nDelivered."));
|
|
3617
|
+
console.log(`${import_chalk9.default.bold("Event id")}: ${import_chalk9.default.cyan(result.eventId)}`);
|
|
3618
|
+
console.log(`${import_chalk9.default.bold("Relationship id")}: ${import_chalk9.default.cyan(result.relationshipId)}`);
|
|
3619
|
+
console.log(`${import_chalk9.default.bold("Chain index")}: ${import_chalk9.default.cyan(String(result.relationshipEventIndex))}`);
|
|
3620
|
+
console.log(`${import_chalk9.default.bold("Server timestamp")}: ${import_chalk9.default.cyan(result.serverTimestamp)}`);
|
|
3621
|
+
console.log(`${import_chalk9.default.bold("Server event hash")}: ${import_chalk9.default.cyan(result.serverEventHash)}`);
|
|
3825
3622
|
}
|
|
3826
3623
|
function parseOfferTerms(cmdName, opts) {
|
|
3827
3624
|
const out = {};
|
|
@@ -3845,7 +3642,7 @@ function parseOfferTerms(cmdName, opts) {
|
|
|
3845
3642
|
if (opts.amount) {
|
|
3846
3643
|
out.amount = opts.amount;
|
|
3847
3644
|
if (!opts.currency) {
|
|
3848
|
-
throw new Error(`${cmdName}: --amount requires --currency. Shorthand: ${
|
|
3645
|
+
throw new Error(`${cmdName}: --amount requires --currency. Shorthand: ${import_sdk12.WELL_KNOWN_ASSET_KEYS.join(", ")}, or raw CAIP-19 + --currency-decimals.`);
|
|
3849
3646
|
}
|
|
3850
3647
|
out.currency = buildAssetIdentifier(cmdName, DELEGATION_CURRENCY_FLAGS, opts.currency, opts.currencyDecimals, opts.currencySymbol);
|
|
3851
3648
|
} else if (opts.currency) {
|
|
@@ -3868,7 +3665,7 @@ function resolveOfferDelegationId(rawCliId, escrow) {
|
|
|
3868
3665
|
cliId = rawCliId.toLowerCase();
|
|
3869
3666
|
}
|
|
3870
3667
|
if (escrow === void 0) {
|
|
3871
|
-
return cliId ?? (0,
|
|
3668
|
+
return cliId ?? (0, import_sdk12.uuidV4)();
|
|
3872
3669
|
}
|
|
3873
3670
|
if (escrow.delegationIdFromLock !== void 0) {
|
|
3874
3671
|
const fileId = escrow.delegationIdFromLock;
|
|
@@ -3893,20 +3690,15 @@ function requireUuidNormalised(cmdName, raw, label) {
|
|
|
3893
3690
|
requireUuid2(cmdName, raw, label);
|
|
3894
3691
|
return raw.toLowerCase();
|
|
3895
3692
|
}
|
|
3896
|
-
function requireDid(cmdName, did, label) {
|
|
3897
|
-
if (typeof did !== "string" || !did.startsWith("did:arp:") || did.length <= "did:arp:".length) {
|
|
3898
|
-
throw new Error(`${cmdName}: ${label} must look like 'did:arp:...' (got '${did}')`);
|
|
3899
|
-
}
|
|
3900
|
-
}
|
|
3901
3693
|
function collectRepeated(value, previous) {
|
|
3902
3694
|
return [...previous, value];
|
|
3903
3695
|
}
|
|
3904
3696
|
function parseDeclineReason(cmdName, raw) {
|
|
3905
3697
|
if (raw === void 0 || raw === "") {
|
|
3906
|
-
throw new Error(`${cmdName}: --reason is required when declining (one of: ${
|
|
3698
|
+
throw new Error(`${cmdName}: --reason is required when declining (one of: ${import_sdk12.DECLINE_REASONS.join(", ")})`);
|
|
3907
3699
|
}
|
|
3908
|
-
if (!(0,
|
|
3909
|
-
throw new Error(`${cmdName}: --reason must be one of ${
|
|
3700
|
+
if (!(0, import_sdk12.isDeclineReason)(raw)) {
|
|
3701
|
+
throw new Error(`${cmdName}: --reason must be one of ${import_sdk12.DECLINE_REASONS.join(", ")} (got '${raw}')`);
|
|
3910
3702
|
}
|
|
3911
3703
|
return raw;
|
|
3912
3704
|
}
|
|
@@ -3921,10 +3713,10 @@ function parseReasonDetail(cmdName, raw) {
|
|
|
3921
3713
|
return raw;
|
|
3922
3714
|
}
|
|
3923
3715
|
function buildAssetIdentifier(cmdName, labels, rawCurrency, rawDecimals, rawSymbol) {
|
|
3924
|
-
const resolved = (0,
|
|
3716
|
+
const resolved = (0, import_sdk12.resolveAsset)(rawCurrency);
|
|
3925
3717
|
if (!resolved) {
|
|
3926
3718
|
throw new Error(
|
|
3927
|
-
`${cmdName}: ${labels.currencyFlag} '${rawCurrency}' is not a known shorthand or a valid CAIP-19 string. Shorthand: ${
|
|
3719
|
+
`${cmdName}: ${labels.currencyFlag} '${rawCurrency}' is not a known shorthand or a valid CAIP-19 string. Shorthand: ${import_sdk12.WELL_KNOWN_ASSET_KEYS.join(", ")}. Or pass a raw CAIP-19 id (e.g. "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/spl:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") with ${labels.decimalsFlag}.`
|
|
3928
3720
|
);
|
|
3929
3721
|
}
|
|
3930
3722
|
let decimals = resolved.decimals;
|
|
@@ -3933,20 +3725,20 @@ function buildAssetIdentifier(cmdName, labels, rawCurrency, rawDecimals, rawSymb
|
|
|
3933
3725
|
throw new Error(`${cmdName}: ${labels.currencyFlag} is a raw CAIP-19 string; ${labels.decimalsFlag} (0-18) is required to convert amounts to base units.`);
|
|
3934
3726
|
}
|
|
3935
3727
|
const parsed = Number(rawDecimals);
|
|
3936
|
-
if (!Number.isInteger(parsed) || parsed <
|
|
3728
|
+
if (!Number.isInteger(parsed) || parsed < import_sdk12.ASSET_DECIMALS_MIN || parsed > import_sdk12.ASSET_DECIMALS_MAX) {
|
|
3937
3729
|
throw new Error(`${cmdName}: ${labels.decimalsFlag} must be an integer in [0, 18] (got '${rawDecimals}').`);
|
|
3938
3730
|
}
|
|
3939
3731
|
decimals = parsed;
|
|
3940
3732
|
} else if (rawDecimals !== void 0) {
|
|
3941
3733
|
const parsed = Number(rawDecimals);
|
|
3942
|
-
if (!Number.isInteger(parsed) || parsed <
|
|
3734
|
+
if (!Number.isInteger(parsed) || parsed < import_sdk12.ASSET_DECIMALS_MIN || parsed > import_sdk12.ASSET_DECIMALS_MAX) {
|
|
3943
3735
|
throw new Error(`${cmdName}: ${labels.decimalsFlag} must be an integer in [0, 18] (got '${rawDecimals}').`);
|
|
3944
3736
|
}
|
|
3945
3737
|
decimals = parsed;
|
|
3946
3738
|
}
|
|
3947
3739
|
let symbol = resolved.symbol;
|
|
3948
3740
|
if (rawSymbol !== void 0) {
|
|
3949
|
-
if (rawSymbol.length <
|
|
3741
|
+
if (rawSymbol.length < import_sdk12.ASSET_SYMBOL_MIN_LEN || rawSymbol.length > import_sdk12.ASSET_SYMBOL_MAX_LEN) {
|
|
3950
3742
|
throw new Error(`${cmdName}: ${labels.symbolFlag} must be 1-16 chars (got length ${rawSymbol.length}).`);
|
|
3951
3743
|
}
|
|
3952
3744
|
symbol = rawSymbol;
|
|
@@ -3960,12 +3752,12 @@ var DELEGATION_CURRENCY_FLAGS = {
|
|
|
3960
3752
|
};
|
|
3961
3753
|
|
|
3962
3754
|
// src/commands/delegations.ts
|
|
3963
|
-
var
|
|
3964
|
-
var
|
|
3755
|
+
var import_sdk13 = require("@heyanon-arp/sdk");
|
|
3756
|
+
var import_chalk10 = __toESM(require("chalk"));
|
|
3965
3757
|
init_api();
|
|
3966
|
-
var ALLOWED_STATES = /* @__PURE__ */ new Set([
|
|
3758
|
+
var ALLOWED_STATES = /* @__PURE__ */ new Set([import_sdk13.DelegationStates.OFFERED, import_sdk13.DelegationStates.ACCEPTED, import_sdk13.DelegationStates.DECLINED, import_sdk13.DelegationStates.CANCELED]);
|
|
3967
3759
|
function registerDelegationsCommand(root) {
|
|
3968
|
-
root.command("delegations").description("List delegations for a relationship (one row per delegationId, oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (offered|accepted|declined|canceled)").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
|
|
3760
|
+
root.command("delegations").description("List delegations for a relationship (one row per delegationId, oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (offered|accepted|declined|canceled)").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
3969
3761
|
"--verbose",
|
|
3970
3762
|
'After the one-line summaries, print a framed "Full delegation payloads (N rows)" block \u2014 each row labelled with full delegationId (`delegation accept` / `delegation decline` / `work request` need it) and dumped as JSON. Mutually exclusive with --json.',
|
|
3971
3763
|
false
|
|
@@ -3982,10 +3774,10 @@ async function runDelegations(relationshipId, opts) {
|
|
|
3982
3774
|
const limit = parseLimit2(opts.limit);
|
|
3983
3775
|
const state = parseState(opts.state);
|
|
3984
3776
|
const api = new ArpApiClient(opts.server);
|
|
3985
|
-
const sender = resolveSenderAgent("delegations", opts.server, opts.fromDid);
|
|
3986
|
-
progress(opts.json,
|
|
3987
|
-
progress(opts.json,
|
|
3988
|
-
progress(opts.json,
|
|
3777
|
+
const sender = resolveSenderAgent("delegations", opts.server, opts.fromDid, opts.from);
|
|
3778
|
+
progress(opts.json, import_chalk10.default.dim(`Server: ${api.serverUrl}`));
|
|
3779
|
+
progress(opts.json, import_chalk10.default.dim(`Signer: ${sender.did}`));
|
|
3780
|
+
progress(opts.json, import_chalk10.default.dim(`Relationship: ${relationshipId}`));
|
|
3989
3781
|
const query = { limit };
|
|
3990
3782
|
if (state) query.state = state;
|
|
3991
3783
|
if (opts.after) query.after = opts.after;
|
|
@@ -3996,7 +3788,7 @@ async function runDelegations(relationshipId, opts) {
|
|
|
3996
3788
|
return;
|
|
3997
3789
|
}
|
|
3998
3790
|
if (rows.length === 0) {
|
|
3999
|
-
console.log(
|
|
3791
|
+
console.log(import_chalk10.default.dim("\n(no delegations for this relationship)"));
|
|
4000
3792
|
return;
|
|
4001
3793
|
}
|
|
4002
3794
|
console.log("");
|
|
@@ -4012,19 +3804,19 @@ async function runDelegations(relationshipId, opts) {
|
|
|
4012
3804
|
}));
|
|
4013
3805
|
}
|
|
4014
3806
|
const lastId = rows[rows.length - 1].id;
|
|
4015
|
-
console.log(
|
|
3807
|
+
console.log(import_chalk10.default.dim(`
|
|
4016
3808
|
${rows.length} delegation row(s). Paginate with --after ${lastId}.`));
|
|
4017
3809
|
}
|
|
4018
3810
|
function formatDelegationLine(d, selfDid, opts = {}) {
|
|
4019
|
-
const idHead_ =
|
|
3811
|
+
const idHead_ = import_chalk10.default.bold(opts.fullIds ? d.delegationId : idHead(d.delegationId));
|
|
4020
3812
|
const state = colorState(d.state).padEnd(stateColumnWidth());
|
|
4021
|
-
const offerer = d.offererDid === selfDid ?
|
|
3813
|
+
const offerer = d.offererDid === selfDid ? import_chalk10.default.bold("me") : import_chalk10.default.dim(opts.fullIds ? d.offererDid : didHead(d.offererDid));
|
|
4022
3814
|
const amount = formatAmount(d);
|
|
4023
|
-
const title = d.title ?
|
|
3815
|
+
const title = d.title ? import_chalk10.default.dim(`"${truncate2(d.title, 40)}"`) : import_chalk10.default.dim("(no title)");
|
|
4024
3816
|
let declineSuffix = "";
|
|
4025
|
-
if (d.state ===
|
|
3817
|
+
if (d.state === import_sdk13.DelegationStates.DECLINED && d.declineReason) {
|
|
4026
3818
|
const detail = d.declineReasonDetail ? `: ${truncate2(d.declineReasonDetail, 40)}` : "";
|
|
4027
|
-
declineSuffix = ` ${
|
|
3819
|
+
declineSuffix = ` ${import_chalk10.default.dim(`(reason: ${d.declineReason}${detail})`)}`;
|
|
4028
3820
|
}
|
|
4029
3821
|
return `${idHead_} ${state} ${offerer} ${amount} ${title}${declineSuffix}`;
|
|
4030
3822
|
}
|
|
@@ -4037,35 +3829,35 @@ function colorState(s) {
|
|
|
4037
3829
|
// returns `undefined` and `formatDelegationLine` crashes with
|
|
4038
3830
|
// `TypeError: Cannot read properties of undefined (reading
|
|
4039
3831
|
// 'padEnd')` on any listing containing such a row.
|
|
4040
|
-
case
|
|
4041
|
-
return
|
|
4042
|
-
case
|
|
4043
|
-
return
|
|
4044
|
-
case
|
|
4045
|
-
return
|
|
3832
|
+
case import_sdk13.DelegationStates.OFFERED:
|
|
3833
|
+
return import_chalk10.default.yellow("offered");
|
|
3834
|
+
case import_sdk13.DelegationStates.PENDING_LOCK_FINALIZATION:
|
|
3835
|
+
return import_chalk10.default.yellow("pending_lock");
|
|
3836
|
+
case import_sdk13.DelegationStates.ACCEPTED:
|
|
3837
|
+
return import_chalk10.default.green("accepted");
|
|
4046
3838
|
// The on-chain escrow lock is confirmed. Distinct branch so a
|
|
4047
3839
|
// LOCKED row renders without hitting the defensive fallback
|
|
4048
3840
|
// (which would otherwise echo the raw state).
|
|
4049
|
-
case
|
|
4050
|
-
return
|
|
4051
|
-
case
|
|
4052
|
-
return
|
|
4053
|
-
case
|
|
4054
|
-
return
|
|
3841
|
+
case import_sdk13.DelegationStates.LOCKED:
|
|
3842
|
+
return import_chalk10.default.green("locked");
|
|
3843
|
+
case import_sdk13.DelegationStates.DECLINED:
|
|
3844
|
+
return import_chalk10.default.red("declined");
|
|
3845
|
+
case import_sdk13.DelegationStates.CANCELED:
|
|
3846
|
+
return import_chalk10.default.dim("canceled");
|
|
4055
3847
|
// Terminal escrow outcomes: completed = payee paid;
|
|
4056
3848
|
// failed = create_lock never landed; refunded = funds returned
|
|
4057
3849
|
// to the buyer (work expired / dispute closed);
|
|
4058
3850
|
// dispute_resolved = operator ruled.
|
|
4059
|
-
case
|
|
4060
|
-
return
|
|
4061
|
-
case
|
|
4062
|
-
return
|
|
4063
|
-
case
|
|
4064
|
-
return
|
|
4065
|
-
case
|
|
4066
|
-
return
|
|
4067
|
-
case
|
|
4068
|
-
return
|
|
3851
|
+
case import_sdk13.DelegationStates.COMPLETED:
|
|
3852
|
+
return import_chalk10.default.green("completed");
|
|
3853
|
+
case import_sdk13.DelegationStates.FAILED:
|
|
3854
|
+
return import_chalk10.default.red("failed");
|
|
3855
|
+
case import_sdk13.DelegationStates.REFUNDED:
|
|
3856
|
+
return import_chalk10.default.red("refunded");
|
|
3857
|
+
case import_sdk13.DelegationStates.DISPUTING:
|
|
3858
|
+
return import_chalk10.default.yellow("disputing");
|
|
3859
|
+
case import_sdk13.DelegationStates.DISPUTE_RESOLVED:
|
|
3860
|
+
return import_chalk10.default.red("dispute_resolved");
|
|
4069
3861
|
default: {
|
|
4070
3862
|
const _exhaustive = s;
|
|
4071
3863
|
void _exhaustive;
|
|
@@ -4077,9 +3869,9 @@ function stateColumnWidth() {
|
|
|
4077
3869
|
return 12;
|
|
4078
3870
|
}
|
|
4079
3871
|
function formatAmount(d) {
|
|
4080
|
-
if (!d.amount) return
|
|
3872
|
+
if (!d.amount) return import_chalk10.default.dim("(no amount)");
|
|
4081
3873
|
const currency = d.currency ? d.currency.symbol ?? d.currency.assetId : "?";
|
|
4082
|
-
return
|
|
3874
|
+
return import_chalk10.default.cyan(`${d.amount} ${currency}`);
|
|
4083
3875
|
}
|
|
4084
3876
|
function idHead(id) {
|
|
4085
3877
|
if (id.length <= 12) return id;
|
|
@@ -4110,7 +3902,7 @@ function parseLimit2(raw) {
|
|
|
4110
3902
|
}
|
|
4111
3903
|
|
|
4112
3904
|
// src/commands/did-doc.ts
|
|
4113
|
-
var
|
|
3905
|
+
var import_sdk14 = require("@heyanon-arp/sdk");
|
|
4114
3906
|
init_api();
|
|
4115
3907
|
function registerDidDocCommand(root) {
|
|
4116
3908
|
root.command("did-doc").description(
|
|
@@ -4119,7 +3911,7 @@ function registerDidDocCommand(root) {
|
|
|
4119
3911
|
"--field <path>",
|
|
4120
3912
|
"Extract a single value via a dotted path. Supports object property access (`id`), numeric array indexes (`verificationMethod.0`), and `#fragment` array selectors that match a verification-method or service entry by its `id` suffix (`verificationMethod.#settlement.publicKeyMultibase`). Two well-known shortcuts skip the path entirely AND strip the multibase prefix: `settlementPublicKey` / `identityPublicKey` emit the raw base58 pubkey ready for flags like `--recipient-pubkey`. Scalar values (string / number / boolean) emit raw to stdout for shell composition (`KEY=$(heyarp did-doc ... --field ...)`); objects / arrays emit as pretty-printed JSON. Mutually exclusive with `--json` since `--field` already controls the shape."
|
|
4121
3913
|
).action(async (did, opts) => {
|
|
4122
|
-
if (!(0,
|
|
3914
|
+
if (!(0, import_sdk14.isValidDid)(did)) {
|
|
4123
3915
|
throw new Error(`'${did}' is not a syntactically valid did:arp identifier`);
|
|
4124
3916
|
}
|
|
4125
3917
|
if (opts.json && opts.field !== void 0) {
|
|
@@ -4231,8 +4023,8 @@ function describeShape(value) {
|
|
|
4231
4023
|
}
|
|
4232
4024
|
|
|
4233
4025
|
// src/commands/doctor.ts
|
|
4234
|
-
var
|
|
4235
|
-
var
|
|
4026
|
+
var import_sdk15 = require("@heyanon-arp/sdk");
|
|
4027
|
+
var import_chalk11 = __toESM(require("chalk"));
|
|
4236
4028
|
init_api();
|
|
4237
4029
|
function registerDoctorCommand(root) {
|
|
4238
4030
|
root.command("doctor").description("Liveness probe for a counterparty: resolve DID document + read protocol activity. No auth.").argument("<did>", "did:arp:<base58btc> of the agent to probe").option("--server <url>", "Override ARP server base URL").option("--json", "Machine-readable: single JSON object on stdout. Pipe-safe.", false).action(async (did, opts) => {
|
|
@@ -4241,7 +4033,7 @@ function registerDoctorCommand(root) {
|
|
|
4241
4033
|
}
|
|
4242
4034
|
var LISTENING_THRESHOLD_SECONDS = 15 * 60;
|
|
4243
4035
|
async function runDoctor(did, opts) {
|
|
4244
|
-
if (!(0,
|
|
4036
|
+
if (!(0, import_sdk15.isValidDid)(did)) {
|
|
4245
4037
|
throw new Error(`'${did}' is not a syntactically valid did:arp identifier`);
|
|
4246
4038
|
}
|
|
4247
4039
|
const api = new ArpApiClient(opts.server);
|
|
@@ -4325,52 +4117,52 @@ async function probe(api, did) {
|
|
|
4325
4117
|
}
|
|
4326
4118
|
function formatDoctorReport(r) {
|
|
4327
4119
|
const lines = [];
|
|
4328
|
-
lines.push(`${
|
|
4329
|
-
lines.push(`${
|
|
4120
|
+
lines.push(`${import_chalk11.default.dim("Server:")} ${r.server}`);
|
|
4121
|
+
lines.push(`${import_chalk11.default.dim("Target DID:")} ${r.did}`);
|
|
4330
4122
|
if (!r.didDocument.found) {
|
|
4331
|
-
lines.push(`${
|
|
4123
|
+
lines.push(`${import_chalk11.default.dim("DID doc:")} ${import_chalk11.default.red("\u2717")} not found`);
|
|
4332
4124
|
} else {
|
|
4333
4125
|
const registered = r.didDocument.registeredAt ? ` (registered ${r.didDocument.registeredAt})` : "";
|
|
4334
|
-
lines.push(`${
|
|
4126
|
+
lines.push(`${import_chalk11.default.dim("DID doc:")} ${import_chalk11.default.green("\u2713")} resolved${registered}`);
|
|
4335
4127
|
}
|
|
4336
4128
|
if (r.activity) {
|
|
4337
4129
|
if (r.activity.lastEventAt === null) {
|
|
4338
|
-
lines.push(`${
|
|
4130
|
+
lines.push(`${import_chalk11.default.dim("Activity:")} ${import_chalk11.default.dim("(no events ever \u2014 fresh agent)")}`);
|
|
4339
4131
|
} else {
|
|
4340
4132
|
const ageMin = r.activity.ageSeconds !== null ? Math.floor(r.activity.ageSeconds / 60) : null;
|
|
4341
4133
|
const ageStr = ageMin !== null && ageMin > 0 ? `${ageMin}m ago` : `${r.activity.ageSeconds}s ago`;
|
|
4342
|
-
lines.push(`${
|
|
4134
|
+
lines.push(`${import_chalk11.default.dim("Activity:")} last event ${ageStr} (${r.activity.lastEventAt})`);
|
|
4343
4135
|
}
|
|
4344
4136
|
if (r.activity.lastSeenAt !== null && r.activity.lastSeenAt !== void 0) {
|
|
4345
4137
|
const seenMin = r.activity.seenAgeSeconds !== null && r.activity.seenAgeSeconds !== void 0 ? Math.floor(r.activity.seenAgeSeconds / 60) : null;
|
|
4346
4138
|
const seenStr = seenMin !== null && seenMin > 0 ? `${seenMin}m ago` : `${r.activity.seenAgeSeconds}s ago`;
|
|
4347
|
-
lines.push(`${
|
|
4139
|
+
lines.push(`${import_chalk11.default.dim("Last seen:")} signed request ${seenStr} (${r.activity.lastSeenAt})`);
|
|
4348
4140
|
}
|
|
4349
4141
|
if (r.activity.inboxStreamActive === true) {
|
|
4350
|
-
lines.push(`${
|
|
4142
|
+
lines.push(`${import_chalk11.default.dim("Inbox SSE:")} ${import_chalk11.default.green("\u2713")} active subscription on the central server`);
|
|
4351
4143
|
}
|
|
4352
4144
|
}
|
|
4353
|
-
const verdictColor = r.verdict === "LISTENING" ?
|
|
4145
|
+
const verdictColor = r.verdict === "LISTENING" ? import_chalk11.default.green : r.verdict === "DORMANT" ? import_chalk11.default.red : import_chalk11.default.yellow;
|
|
4354
4146
|
lines.push("");
|
|
4355
|
-
lines.push(`${
|
|
4147
|
+
lines.push(`${import_chalk11.default.bold("Verdict:")} ${verdictColor(r.verdict)} \u2014 ${r.reason}`);
|
|
4356
4148
|
return lines.join("\n");
|
|
4357
4149
|
}
|
|
4358
4150
|
|
|
4359
4151
|
// src/commands/envelope.ts
|
|
4360
|
-
var
|
|
4152
|
+
var import_chalk12 = __toESM(require("chalk"));
|
|
4361
4153
|
init_api();
|
|
4362
4154
|
function registerEnvelopeCommand(root) {
|
|
4363
|
-
root.command("envelope").description("Fetch one canonical envelope by eventId \u2014 full body for inspection (signed read)").argument("<event-id>", "Event UUID \u2014 copy from `heyarp inbox`, `heyarp events`, or a counterparty citation").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable: emit only the envelope JSON object on stdout (no prelude, no chalk). Pipe-safe.", false).action(async (eventId, opts) => {
|
|
4155
|
+
root.command("envelope").description("Fetch one canonical envelope by eventId \u2014 full body for inspection (signed read)").argument("<event-id>", "Event UUID \u2014 copy from `heyarp inbox`, `heyarp events`, or a counterparty citation").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable: emit only the envelope JSON object on stdout (no prelude, no chalk). Pipe-safe.", false).action(async (eventId, opts) => {
|
|
4364
4156
|
await runEnvelope(eventId, opts);
|
|
4365
4157
|
});
|
|
4366
4158
|
}
|
|
4367
4159
|
async function runEnvelope(eventId, opts) {
|
|
4368
4160
|
const api = new ArpApiClient(opts.server);
|
|
4369
|
-
const sender = resolveSenderAgent("envelope", opts.server, opts.fromDid);
|
|
4161
|
+
const sender = resolveSenderAgent("envelope", opts.server, opts.fromDid, opts.from);
|
|
4370
4162
|
if (!opts.json) {
|
|
4371
|
-
console.log(
|
|
4372
|
-
console.log(
|
|
4373
|
-
console.log(
|
|
4163
|
+
console.log(import_chalk12.default.dim(`Server: ${api.serverUrl}`));
|
|
4164
|
+
console.log(import_chalk12.default.dim(`Signer: ${sender.did}`));
|
|
4165
|
+
console.log(import_chalk12.default.dim(`Event: ${eventId}`));
|
|
4374
4166
|
}
|
|
4375
4167
|
const signer = makeSigner(sender);
|
|
4376
4168
|
const event = await api.getEvent(sender.did, eventId, signer);
|
|
@@ -4379,43 +4171,43 @@ async function runEnvelope(eventId, opts) {
|
|
|
4379
4171
|
return;
|
|
4380
4172
|
}
|
|
4381
4173
|
console.log("");
|
|
4382
|
-
console.log(
|
|
4174
|
+
console.log(import_chalk12.default.bold("Envelope:"));
|
|
4383
4175
|
console.log(formatJson(event));
|
|
4384
4176
|
console.log("");
|
|
4385
4177
|
console.log(formatHints(event));
|
|
4386
4178
|
}
|
|
4387
4179
|
function formatHints(event) {
|
|
4388
4180
|
const lines = [];
|
|
4389
|
-
lines.push(`${
|
|
4390
|
-
lines.push(`${
|
|
4391
|
-
lines.push(`${
|
|
4392
|
-
lines.push(`${
|
|
4181
|
+
lines.push(`${import_chalk12.default.dim("relationshipId:")} ${import_chalk12.default.cyan(event.relationshipId)}`);
|
|
4182
|
+
lines.push(`${import_chalk12.default.dim("serverEventHash:")} ${import_chalk12.default.cyan(event.serverEventHash)}`);
|
|
4183
|
+
lines.push(`${import_chalk12.default.dim("eventId:")} ${import_chalk12.default.cyan(event.eventId)}`);
|
|
4184
|
+
lines.push(`${import_chalk12.default.dim("relationshipEventIndex:")} ${import_chalk12.default.cyan(String(event.relationshipEventIndex))}`);
|
|
4393
4185
|
return lines.join("\n");
|
|
4394
4186
|
}
|
|
4395
4187
|
|
|
4396
4188
|
// src/commands/escrow.ts
|
|
4397
|
-
var
|
|
4189
|
+
var import_sdk17 = require("@heyanon-arp/sdk");
|
|
4398
4190
|
var import_utils2 = require("@noble/hashes/utils");
|
|
4399
|
-
var
|
|
4191
|
+
var import_chalk13 = __toESM(require("chalk"));
|
|
4400
4192
|
init_api();
|
|
4401
4193
|
|
|
4402
4194
|
// src/commands/escrow-actions.ts
|
|
4403
4195
|
var import_node_crypto = require("crypto");
|
|
4404
|
-
var
|
|
4405
|
-
var
|
|
4196
|
+
var import_sdk16 = require("@heyanon-arp/sdk");
|
|
4197
|
+
var import_web32 = require("@solana/web3.js");
|
|
4406
4198
|
init_api();
|
|
4407
4199
|
var FEE_BUFFER_LAMPORTS = 10000000n;
|
|
4408
4200
|
async function setup(cmd, delegationIdArg, opts) {
|
|
4409
|
-
const agent = resolveSenderAgent(cmd, opts.server, opts.fromDid);
|
|
4201
|
+
const agent = resolveSenderAgent(cmd, opts.server, opts.fromDid, opts.from);
|
|
4410
4202
|
const keypair = keypairFromAgent(agent);
|
|
4411
4203
|
const api = new ArpApiClient(opts.server);
|
|
4412
|
-
const programId = new
|
|
4204
|
+
const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts, cmd));
|
|
4413
4205
|
const rpcUrl = resolveRpcUrlStrict(opts, cmd);
|
|
4414
|
-
const conn = new
|
|
4206
|
+
const conn = new import_web32.Connection(rpcUrl, "confirmed");
|
|
4415
4207
|
const delegationId = normaliseDelegationId(delegationIdArg);
|
|
4416
|
-
const fetched = await fetchLockAccount(conn, programId, delegationId);
|
|
4208
|
+
const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, delegationId);
|
|
4417
4209
|
if (!fetched) {
|
|
4418
|
-
const lockPda = deriveLockPda(programId, (0,
|
|
4210
|
+
const lockPda = (0, import_sdk9.deriveLockPda)(programId, (0, import_sdk16.deriveLockId)(delegationId)).toBase58();
|
|
4419
4211
|
throw new Error(
|
|
4420
4212
|
`${cmd}: no on-chain Lock for delegation ${delegationId} (PDA ${lockPda} not found on ${rpcUrl}). Either the buyer hasn't funded yet (delegation fund \u2192 server relays create_lock), or you're pointing at the wrong cluster/program.`
|
|
4421
4213
|
);
|
|
@@ -4440,10 +4232,10 @@ function nowSecs() {
|
|
|
4440
4232
|
function deadlinePassed(ctx) {
|
|
4441
4233
|
return ctx.lock.expiry > 0n && nowSecs() >= ctx.lock.expiry;
|
|
4442
4234
|
}
|
|
4443
|
-
var SYSTEM_PROGRAM_B58 =
|
|
4235
|
+
var SYSTEM_PROGRAM_B58 = import_sdk16.SYSTEM_PROGRAM_ID_BASE58;
|
|
4444
4236
|
function effectiveFeeRecipient(lock) {
|
|
4445
|
-
if (lock.feeRecipientAtLock !== SYSTEM_PROGRAM_B58) return new
|
|
4446
|
-
if (lock.treasuryAtLock && lock.treasuryAtLock !== SYSTEM_PROGRAM_B58) return new
|
|
4237
|
+
if (lock.feeRecipientAtLock !== SYSTEM_PROGRAM_B58) return new import_web32.PublicKey(lock.feeRecipientAtLock);
|
|
4238
|
+
if (lock.treasuryAtLock && lock.treasuryAtLock !== SYSTEM_PROGRAM_B58) return new import_web32.PublicKey(lock.treasuryAtLock);
|
|
4447
4239
|
throw new Error(
|
|
4448
4240
|
"escrow: this lock snapshots the system program as BOTH fee_recipient and treasury \u2014 no writable fee account exists; the on-chain Config was initialized inconsistently."
|
|
4449
4241
|
);
|
|
@@ -4461,7 +4253,7 @@ async function preflightLamports(ctx, stake, what) {
|
|
|
4461
4253
|
}
|
|
4462
4254
|
}
|
|
4463
4255
|
async function sendIx(ctx, ix) {
|
|
4464
|
-
const tx = new
|
|
4256
|
+
const tx = new import_web32.Transaction().add(ix);
|
|
4465
4257
|
tx.feePayer = ctx.keypair.publicKey;
|
|
4466
4258
|
const { blockhash, lastValidBlockHeight } = await ctx.conn.getLatestBlockhash("confirmed");
|
|
4467
4259
|
tx.recentBlockhash = blockhash;
|
|
@@ -4502,28 +4294,28 @@ function emit(ctx, action, signature, extra = {}) {
|
|
|
4502
4294
|
}
|
|
4503
4295
|
async function acceptHandler(delegationId, opts) {
|
|
4504
4296
|
const ctx = await setup("escrow accept", delegationId, opts);
|
|
4505
|
-
requireState(ctx, [
|
|
4297
|
+
requireState(ctx, [import_sdk16.LockStates.CREATED], "Accept is only possible before any other transition; if it shows in_progress you already accepted.");
|
|
4506
4298
|
requireSigner(ctx, "payee", ctx.lock.payee);
|
|
4507
4299
|
const stake = ctx.lock.workerStakeAtLock;
|
|
4508
4300
|
await preflightLamports(ctx, stake, `the worker stake (${stake} lamports, returned when the lock settles in your favour)`);
|
|
4509
4301
|
progress(ctx.opts.json, `accepting lock ${ctx.lock.lockId.slice(0, 16)}\u2026 \u2014 staking ${stake} lamports from ${ctx.keypair.publicKey.toBase58()}`);
|
|
4510
|
-
const sig = await sendIx(ctx, buildAcceptLockIx({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
|
|
4302
|
+
const sig = await sendIx(ctx, (0, import_sdk9.buildAcceptLockIx)({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
|
|
4511
4303
|
emit(ctx, "accept", sig, { worker_stake: stake.toString() });
|
|
4512
4304
|
}
|
|
4513
4305
|
async function submitWorkHandler(delegationId, opts) {
|
|
4514
4306
|
const ctx = await setup("escrow submit-work", delegationId, opts);
|
|
4515
|
-
requireState(ctx, [
|
|
4307
|
+
requireState(ctx, [import_sdk16.LockStates.IN_PROGRESS], "Submit needs an accepted lock ('created' \u2192 run `heyarp escrow accept` first; terminal \u2192 the cycle already ended).");
|
|
4516
4308
|
requireSigner(ctx, "payee", ctx.lock.payee);
|
|
4517
4309
|
if (deadlinePassed(ctx)) {
|
|
4518
4310
|
throw new Error(
|
|
4519
4311
|
`escrow submit-work: the work window expired at ${expiryIso(ctx)} \u2014 the chain will reject submit_work and the buyer can claim the escrow back (claim_expired_work). Nothing to salvage on-chain.`
|
|
4520
4312
|
);
|
|
4521
4313
|
}
|
|
4522
|
-
const sig = await sendIx(ctx, buildSubmitWorkIx({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
|
|
4314
|
+
const sig = await sendIx(ctx, (0, import_sdk9.buildSubmitWorkIx)({ programId: ctx.programId, lockId: ctx.lockId, payee: ctx.keypair.publicKey }));
|
|
4523
4315
|
let reviewDeadline = null;
|
|
4524
4316
|
try {
|
|
4525
|
-
const fresh = await fetchLockAccount(ctx.conn, ctx.programId, ctx.delegationId);
|
|
4526
|
-
if (fresh && fresh.lock.state ===
|
|
4317
|
+
const fresh = await (0, import_sdk9.fetchLockAccount)(ctx.conn, ctx.programId, ctx.delegationId);
|
|
4318
|
+
if (fresh && fresh.lock.state === import_sdk16.LockStates.SUBMITTED && fresh.lock.expiry > 0n) {
|
|
4527
4319
|
reviewDeadline = new Date(Number(fresh.lock.expiry) * 1e3).toISOString();
|
|
4528
4320
|
}
|
|
4529
4321
|
} catch {
|
|
@@ -4536,34 +4328,34 @@ async function submitWorkHandler(delegationId, opts) {
|
|
|
4536
4328
|
}
|
|
4537
4329
|
async function claimHandler(delegationId, opts) {
|
|
4538
4330
|
const ctx = await setup("escrow claim", delegationId, opts);
|
|
4539
|
-
requireState(ctx, [
|
|
4331
|
+
requireState(ctx, [import_sdk16.LockStates.SUBMITTED], "Claim needs submitted work ('in_progress' \u2192 the worker must `escrow submit-work` first; 'paid' \u2192 already claimed).");
|
|
4540
4332
|
const me = ctx.keypair.publicKey.toBase58();
|
|
4541
4333
|
let role;
|
|
4542
4334
|
if (me === ctx.lock.payer) {
|
|
4543
|
-
role =
|
|
4335
|
+
role = import_sdk16.EscrowReleaseMethods.BUYER_APPROVED;
|
|
4544
4336
|
} else if (me === ctx.lock.payee) {
|
|
4545
4337
|
if (!deadlinePassed(ctx)) {
|
|
4546
4338
|
throw new Error(
|
|
4547
4339
|
`escrow claim: the review window is still open (until ${expiryIso(ctx)}). As the worker you can self-claim only AFTER it lapses; before that the buyer must approve (or dispute).`
|
|
4548
4340
|
);
|
|
4549
4341
|
}
|
|
4550
|
-
role =
|
|
4342
|
+
role = import_sdk16.EscrowReleaseMethods.REVIEW_TIMEOUT;
|
|
4551
4343
|
} else {
|
|
4552
4344
|
throw new Error(`escrow claim: your settlement key ${me} is neither the payer (${ctx.lock.payer}) nor the payee (${ctx.lock.payee}) of this lock.`);
|
|
4553
4345
|
}
|
|
4554
4346
|
progress(
|
|
4555
4347
|
ctx.opts.json,
|
|
4556
|
-
role ===
|
|
4348
|
+
role === import_sdk16.EscrowReleaseMethods.BUYER_APPROVED ? "approving payment as the buyer \u2014 this RELEASES the escrow and is irreversible" : "self-claiming after review timeout"
|
|
4557
4349
|
);
|
|
4558
4350
|
const sig = await sendIx(
|
|
4559
4351
|
ctx,
|
|
4560
|
-
buildClaimWorkPaymentIx({
|
|
4352
|
+
(0, import_sdk9.buildClaimWorkPaymentIx)({
|
|
4561
4353
|
programId: ctx.programId,
|
|
4562
4354
|
lockId: ctx.lockId,
|
|
4563
4355
|
authority: ctx.keypair.publicKey,
|
|
4564
|
-
payer: new
|
|
4565
|
-
payee: new
|
|
4566
|
-
mint: ctx.lock.isNative ? null : new
|
|
4356
|
+
payer: new import_web32.PublicKey(ctx.lock.payer),
|
|
4357
|
+
payee: new import_web32.PublicKey(ctx.lock.payee),
|
|
4358
|
+
mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint),
|
|
4567
4359
|
feeRecipient: effectiveFeeRecipient(ctx.lock)
|
|
4568
4360
|
})
|
|
4569
4361
|
);
|
|
@@ -4571,40 +4363,40 @@ async function claimHandler(delegationId, opts) {
|
|
|
4571
4363
|
}
|
|
4572
4364
|
async function cancelHandler(delegationId, opts) {
|
|
4573
4365
|
const ctx = await setup("escrow cancel", delegationId, opts);
|
|
4574
|
-
requireState(ctx, [
|
|
4366
|
+
requireState(ctx, [import_sdk16.LockStates.CREATED], "Cancel is the pre-accept exit only \u2014 once the worker accepted ('in_progress') the windows model governs.");
|
|
4575
4367
|
requireSigner(ctx, "payer", ctx.lock.payer);
|
|
4576
4368
|
const sig = await sendIx(
|
|
4577
4369
|
ctx,
|
|
4578
|
-
buildCancelLockIx({
|
|
4370
|
+
(0, import_sdk9.buildCancelLockIx)({
|
|
4579
4371
|
programId: ctx.programId,
|
|
4580
4372
|
lockId: ctx.lockId,
|
|
4581
4373
|
payer: ctx.keypair.publicKey,
|
|
4582
|
-
mint: ctx.lock.isNative ? null : new
|
|
4374
|
+
mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
|
|
4583
4375
|
})
|
|
4584
4376
|
);
|
|
4585
4377
|
emit(ctx, "cancel", sig, { refunded_amount: ctx.lock.amount.toString() });
|
|
4586
4378
|
}
|
|
4587
4379
|
async function claimExpiredHandler(delegationId, opts) {
|
|
4588
4380
|
const ctx = await setup("escrow claim-expired", delegationId, opts);
|
|
4589
|
-
requireState(ctx, [
|
|
4381
|
+
requireState(ctx, [import_sdk16.LockStates.IN_PROGRESS], "Claim-expired recovers an accepted-but-never-submitted lock; 'submitted' work goes through claim/dispute instead.");
|
|
4590
4382
|
requireSigner(ctx, "payer", ctx.lock.payer);
|
|
4591
4383
|
if (!deadlinePassed(ctx)) {
|
|
4592
4384
|
throw new Error(`escrow claim-expired: the work window is still open (until ${expiryIso(ctx)}). The worker can still submit; the chain will reject this claim until then.`);
|
|
4593
4385
|
}
|
|
4594
4386
|
const sig = await sendIx(
|
|
4595
4387
|
ctx,
|
|
4596
|
-
buildClaimExpiredWorkIx({
|
|
4388
|
+
(0, import_sdk9.buildClaimExpiredWorkIx)({
|
|
4597
4389
|
programId: ctx.programId,
|
|
4598
4390
|
lockId: ctx.lockId,
|
|
4599
4391
|
payer: ctx.keypair.publicKey,
|
|
4600
|
-
mint: ctx.lock.isNative ? null : new
|
|
4392
|
+
mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
|
|
4601
4393
|
})
|
|
4602
4394
|
);
|
|
4603
4395
|
emit(ctx, "claim-expired", sig, { refunded_amount: ctx.lock.amount.toString(), worker_stake_forfeited: ctx.lock.workerStakeAtLock.toString() });
|
|
4604
4396
|
}
|
|
4605
4397
|
async function disputeOpenHandler(delegationId, opts) {
|
|
4606
4398
|
const ctx = await setup("escrow dispute open", delegationId, opts);
|
|
4607
|
-
requireState(ctx, [
|
|
4399
|
+
requireState(ctx, [import_sdk16.LockStates.SUBMITTED], "Disputes open against SUBMITTED work, inside the review window.");
|
|
4608
4400
|
requireSigner(ctx, "payer", ctx.lock.payer);
|
|
4609
4401
|
if (deadlinePassed(ctx)) {
|
|
4610
4402
|
throw new Error(
|
|
@@ -4614,12 +4406,12 @@ async function disputeOpenHandler(delegationId, opts) {
|
|
|
4614
4406
|
const stake = ctx.lock.workerStakeAtLock;
|
|
4615
4407
|
await preflightLamports(ctx, stake, `the dispute stake (${stake} lamports \u2014 returned if the operator rules for you or the dispute times out)`);
|
|
4616
4408
|
progress(ctx.opts.json, `opening dispute \u2014 staking ${stake} lamports; the operator has the dispute window to rule, after that either party can close`);
|
|
4617
|
-
const sig = await sendIx(ctx, buildOpenDisputeIx({ programId: ctx.programId, lockId: ctx.lockId, payer: ctx.keypair.publicKey }));
|
|
4409
|
+
const sig = await sendIx(ctx, (0, import_sdk9.buildOpenDisputeIx)({ programId: ctx.programId, lockId: ctx.lockId, payer: ctx.keypair.publicKey }));
|
|
4618
4410
|
emit(ctx, "dispute-open", sig, { buyer_stake: stake.toString() });
|
|
4619
4411
|
}
|
|
4620
4412
|
async function disputeCloseHandler(delegationId, opts) {
|
|
4621
4413
|
const ctx = await setup("escrow dispute close", delegationId, opts);
|
|
4622
|
-
requireState(ctx, [
|
|
4414
|
+
requireState(ctx, [import_sdk16.LockStates.DISPUTING], "Close only applies to an OPEN dispute that the operator never resolved.");
|
|
4623
4415
|
const me = ctx.keypair.publicKey.toBase58();
|
|
4624
4416
|
if (me !== ctx.lock.payer && me !== ctx.lock.payee) {
|
|
4625
4417
|
throw new Error(`escrow dispute close: your settlement key ${me} is neither party of this lock.`);
|
|
@@ -4631,20 +4423,20 @@ async function disputeCloseHandler(delegationId, opts) {
|
|
|
4631
4423
|
}
|
|
4632
4424
|
const sig = await sendIx(
|
|
4633
4425
|
ctx,
|
|
4634
|
-
buildCloseDisputeIx({
|
|
4426
|
+
(0, import_sdk9.buildCloseDisputeIx)({
|
|
4635
4427
|
programId: ctx.programId,
|
|
4636
4428
|
lockId: ctx.lockId,
|
|
4637
4429
|
authority: ctx.keypair.publicKey,
|
|
4638
|
-
payer: new
|
|
4639
|
-
payee: new
|
|
4640
|
-
mint: ctx.lock.isNative ? null : new
|
|
4430
|
+
payer: new import_web32.PublicKey(ctx.lock.payer),
|
|
4431
|
+
payee: new import_web32.PublicKey(ctx.lock.payee),
|
|
4432
|
+
mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint)
|
|
4641
4433
|
})
|
|
4642
4434
|
);
|
|
4643
4435
|
emit(ctx, "dispute-close", sig, {});
|
|
4644
4436
|
}
|
|
4645
4437
|
async function disputeResolveHandler(delegationId, opts) {
|
|
4646
4438
|
const ctx = await setup("escrow dispute resolve", delegationId, opts);
|
|
4647
|
-
requireState(ctx, [
|
|
4439
|
+
requireState(ctx, [import_sdk16.LockStates.DISPUTING], "Resolve only applies to an OPEN dispute, inside the dispute window.");
|
|
4648
4440
|
if (deadlinePassed(ctx)) {
|
|
4649
4441
|
throw new Error(
|
|
4650
4442
|
`escrow dispute resolve: the dispute window lapsed at ${expiryIso(ctx)} \u2014 the chain rejects late rulings (LockExpired); either party can now \`escrow dispute close\` instead.`
|
|
@@ -4663,15 +4455,15 @@ async function disputeResolveHandler(delegationId, opts) {
|
|
|
4663
4455
|
const disputeId = Uint8Array.from(Buffer.from(disputeUuid.replace(/-/g, ""), "hex"));
|
|
4664
4456
|
const sig = await sendIx(
|
|
4665
4457
|
ctx,
|
|
4666
|
-
buildResolveDisputeIx({
|
|
4458
|
+
(0, import_sdk9.buildResolveDisputeIx)({
|
|
4667
4459
|
programId: ctx.programId,
|
|
4668
4460
|
lockId: ctx.lockId,
|
|
4669
4461
|
operator: ctx.keypair.publicKey,
|
|
4670
|
-
payer: new
|
|
4671
|
-
winner: new
|
|
4462
|
+
payer: new import_web32.PublicKey(ctx.lock.payer),
|
|
4463
|
+
winner: new import_web32.PublicKey(winner),
|
|
4672
4464
|
feeRecipient: effectiveFeeRecipient(ctx.lock),
|
|
4673
|
-
treasury: new
|
|
4674
|
-
mint: ctx.lock.isNative ? null : new
|
|
4465
|
+
treasury: new import_web32.PublicKey(ctx.lock.treasuryAtLock),
|
|
4466
|
+
mint: ctx.lock.isNative ? null : new import_web32.PublicKey(ctx.lock.mint),
|
|
4675
4467
|
args: { isPayerWinner, reasonHash, disputeId }
|
|
4676
4468
|
})
|
|
4677
4469
|
);
|
|
@@ -4679,16 +4471,16 @@ async function disputeResolveHandler(delegationId, opts) {
|
|
|
4679
4471
|
}
|
|
4680
4472
|
async function showHandler(delegationId, opts) {
|
|
4681
4473
|
const api = new ArpApiClient(opts.server);
|
|
4682
|
-
const programId = new
|
|
4474
|
+
const programId = new import_web32.PublicKey(await resolveProgramIdStrict(api, opts, "escrow show"));
|
|
4683
4475
|
const rpcUrl = resolveRpcUrlStrict(opts, "escrow show");
|
|
4684
|
-
const conn = new
|
|
4476
|
+
const conn = new import_web32.Connection(rpcUrl, "confirmed");
|
|
4685
4477
|
const normalised = normaliseDelegationId(delegationId);
|
|
4686
|
-
const fetched = await fetchLockAccount(conn, programId, normalised);
|
|
4478
|
+
const fetched = await (0, import_sdk9.fetchLockAccount)(conn, programId, normalised);
|
|
4687
4479
|
if (!fetched) {
|
|
4688
4480
|
jsonOut({
|
|
4689
4481
|
delegation_id: normalised.slice("del_".length),
|
|
4690
4482
|
lock_exists: false,
|
|
4691
|
-
lock_pda: deriveLockPda(programId, (0,
|
|
4483
|
+
lock_pda: (0, import_sdk9.deriveLockPda)(programId, (0, import_sdk16.deriveLockId)(normalised)).toBase58(),
|
|
4692
4484
|
rpc_url: redactRpcUrl(rpcUrl)
|
|
4693
4485
|
});
|
|
4694
4486
|
return;
|
|
@@ -4713,7 +4505,34 @@ async function showHandler(delegationId, opts) {
|
|
|
4713
4505
|
});
|
|
4714
4506
|
}
|
|
4715
4507
|
function sharedFlags(cmd) {
|
|
4716
|
-
return cmd.option("--server <url>", "Override ARP server base URL (program-id discovery)").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--rpc-url <url>", "Solana RPC URL (STRICT: flag > ARP_ESCROW_RPC_URL env > `heyarp config rpcUrl`; no public fallback for state-changing txs)").option("--program-id <pubkey>", "Escrow program id (STRICT: flag > env > server discovery; no hardcoded fallback)").option("--json", "Machine-readable JSON output", false);
|
|
4508
|
+
return cmd.option("--server <url>", "Override ARP server base URL (program-id discovery)").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--rpc-url <url>", "Solana RPC URL (STRICT: flag > ARP_ESCROW_RPC_URL env > `heyarp config rpcUrl`; no public fallback for state-changing txs)").option("--program-id <pubkey>", "Escrow program id (STRICT: flag > env > server discovery; no hardcoded fallback)").option("--json", "Machine-readable JSON output", false);
|
|
4509
|
+
}
|
|
4510
|
+
async function disputeShowHandler(delegationId, opts) {
|
|
4511
|
+
const delId = delegationId.replace(/^del_/, "");
|
|
4512
|
+
const api = new ArpApiClient(opts.server);
|
|
4513
|
+
const sender = resolveSenderAgent("escrow dispute show", opts.server, opts.fromDid, opts.from);
|
|
4514
|
+
const row = await api.getDisputeResolution(delId, makeSigner(sender));
|
|
4515
|
+
progress(opts.json, `Server: ${api.serverUrl}`);
|
|
4516
|
+
progress(opts.json, `Signer: ${sender.did}`);
|
|
4517
|
+
if (opts.json) {
|
|
4518
|
+
jsonOut(row);
|
|
4519
|
+
return;
|
|
4520
|
+
}
|
|
4521
|
+
const winner = row.winnerRole === "payer" ? "BUYER (payer)" : row.winnerRole === "payee" ? "WORKER (payee)" : "(undecided)";
|
|
4522
|
+
console.log("");
|
|
4523
|
+
console.log(`Dispute resolution \u2014 delegation ${row.delegationId}`);
|
|
4524
|
+
console.log(` status: ${row.status}`);
|
|
4525
|
+
console.log(` winner: ${winner}${row.winnerDid ? ` ${row.winnerDid}` : ""}`);
|
|
4526
|
+
console.log(` is_payer_winner: ${row.isPayerWinner}`);
|
|
4527
|
+
console.log(` source: ${row.verdictSource ?? "(none)"} policy: ${row.policyId ?? "(none)"}`);
|
|
4528
|
+
console.log(` snapshot_hash: ${row.snapshotHash ?? "(none)"}`);
|
|
4529
|
+
console.log(` reason_hash: ${row.reasonHashHex ?? "(none)"}`);
|
|
4530
|
+
console.log(` resolve tx: ${row.solanaSignature ?? "(none)"}`);
|
|
4531
|
+
console.log(` attempts: ${row.attempts}${row.lastError ? ` last_error: ${row.lastError}` : ""}`);
|
|
4532
|
+
console.log("\n reasoning:");
|
|
4533
|
+
console.log(
|
|
4534
|
+
(row.reasoning ?? "(none)").split("\n").map((l) => ` ${l}`).join("\n")
|
|
4535
|
+
);
|
|
4717
4536
|
}
|
|
4718
4537
|
function registerEscrowActionCommands(escrow) {
|
|
4719
4538
|
sharedFlags(
|
|
@@ -4749,6 +4568,9 @@ function registerEscrowActionCommands(escrow) {
|
|
|
4749
4568
|
"OPERATOR: rule the dispute (winner takes the escrow; stakes split per config). Requires the on-chain-registered operator key. Disputing \u2192 DisputeResolved."
|
|
4750
4569
|
).option("--payer-wins", "Rule for the buyer").option("--payee-wins", "Rule for the worker").option("--reason <text>", "Resolution reasoning \u2014 sha256 recorded on-chain as reason_hash")
|
|
4751
4570
|
).action(disputeResolveHandler);
|
|
4571
|
+
dispute.command("show <delegation-id>").description(
|
|
4572
|
+
"Read the arbiter's verdict for a disputed delegation \u2014 winner + DID, source (llm | objective_fallback), reasoning, status, resolve tx. Signed server read; parties only."
|
|
4573
|
+
).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable JSON output", false).action(disputeShowHandler);
|
|
4752
4574
|
sharedFlags(escrow.command("show <delegation-id>").description("Decode + print the on-chain Lock account (state, parties, amounts, rolling deadline). Read-only.")).action(
|
|
4753
4575
|
showHandler
|
|
4754
4576
|
);
|
|
@@ -4765,13 +4587,13 @@ function registerEscrowCommands(root) {
|
|
|
4765
4587
|
"Compute canonical condition_hash (32-byte hex) for `heyarp wallet create-lock --condition-hash <hex>` from the DELEGATION terms. Projects the flags to the canonical subset and hashes via SDK deriveDelegationConditionHash \u2014 no server fetch. The SAME terms MUST go into `delegation offer` or the server rejects the lock (ESC_LOCK_CONDITION_HASH_MISMATCH)."
|
|
4766
4588
|
).requiredOption("--delegation-id <id>", "Delegation UUID this lock binds (drives the on-chain lock_id + the condition_hash identity binding)").requiredOption("--scope <text>", "scope_summary \u2014 short prose describing the agreed work").option(
|
|
4767
4589
|
"--currency <s>",
|
|
4768
|
-
`Asset identifier bound into the hash: shorthand (${
|
|
4769
|
-
).option("--currency-decimals <n>", "Decimal places (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--json", "Machine-readable JSON: {delegation_id, condition_hash_hex, projected_subset}", false).action(async (opts) => {
|
|
4590
|
+
`Asset identifier bound into the hash: shorthand (${import_sdk17.WELL_KNOWN_ASSET_KEYS.join("|")}) OR raw CAIP-19 string. Optional but must match the offer's --currency.`
|
|
4591
|
+
).option("--currency-decimals <n>", "Decimal places (0-18). Required only when --currency is raw CAIP-19.").option("--currency-symbol <s>", 'Optional UI hint ("USDC", "SOL"). Max 16 chars.').option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--json", "Machine-readable JSON: {delegation_id, condition_hash_hex, projected_subset}", false).action(async (opts) => {
|
|
4770
4592
|
await runDeriveConditionHash(opts);
|
|
4771
4593
|
});
|
|
4772
4594
|
cmd.command("recover-sequence").description(
|
|
4773
4595
|
"Repair a desynced local `lastSenderSequence` after a post-commit failure the CLI couldn't auto-classify (e.g. `INTERNAL_SERVER_ERROR` from the global Internal filter \u2014 pre-/post-commit origin is ambiguous, so auto-advance is unsafe). Queries the server's owner-only `/sender-sequence` endpoint and compares; with --apply, updates local agent state to match. Default is dry-run \u2014 prints the diff and exits 0 if in-sync, 1 if drift detected."
|
|
4774
|
-
).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--apply", "Apply the fix (write the server-known value to local state). Default: dry-run.", false).option("--json", "Machine-readable JSON: {local, server, drift, applied}", false).action(async (opts) => {
|
|
4596
|
+
).option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--apply", "Apply the fix (write the server-known value to local state). Default: dry-run.", false).option("--json", "Machine-readable JSON: {local, server, drift, applied}", false).action(async (opts) => {
|
|
4775
4597
|
await runRecoverSequence(opts);
|
|
4776
4598
|
});
|
|
4777
4599
|
}
|
|
@@ -4779,7 +4601,7 @@ async function runEscrowInfo(opts) {
|
|
|
4779
4601
|
const api = new ArpApiClient(opts.server);
|
|
4780
4602
|
const status = await api.getEscrowConfig();
|
|
4781
4603
|
if (opts.json) {
|
|
4782
|
-
progress(true,
|
|
4604
|
+
progress(true, import_chalk13.default.dim(`Server: ${api.serverUrl}`));
|
|
4783
4605
|
jsonOut(status);
|
|
4784
4606
|
} else {
|
|
4785
4607
|
console.log(formatEscrowConfigStatus(api.serverUrl, status));
|
|
@@ -4788,35 +4610,35 @@ async function runEscrowInfo(opts) {
|
|
|
4788
4610
|
function formatEscrowConfigStatus(serverUrl, s) {
|
|
4789
4611
|
const lines = [];
|
|
4790
4612
|
const win = (secs) => secs % 3600 === 0 ? `${secs / 3600}h` : secs % 60 === 0 ? `${secs / 60}m` : `${secs}s`;
|
|
4791
|
-
lines.push(`${
|
|
4792
|
-
lines.push(`${
|
|
4793
|
-
lines.push(`${
|
|
4794
|
-
lines.push(`${
|
|
4795
|
-
lines.push(`${
|
|
4613
|
+
lines.push(`${import_chalk13.default.dim("Server:")} ${serverUrl}`);
|
|
4614
|
+
lines.push(`${import_chalk13.default.dim("Program ID:")} ${s.programId}`);
|
|
4615
|
+
lines.push(`${import_chalk13.default.dim("Admin:")} ${s.admin}`);
|
|
4616
|
+
lines.push(`${import_chalk13.default.dim("Treasury:")} ${s.treasury}`);
|
|
4617
|
+
lines.push(`${import_chalk13.default.dim("Paused:")} ${s.paused ? import_chalk13.default.yellow("YES (new locks rejected)") : import_chalk13.default.green("no")}`);
|
|
4796
4618
|
lines.push("");
|
|
4797
|
-
lines.push(
|
|
4798
|
-
lines.push(` ${
|
|
4799
|
-
lines.push(` ${
|
|
4800
|
-
lines.push(` ${
|
|
4619
|
+
lines.push(import_chalk13.default.bold("Windows (rolling deadlines):"));
|
|
4620
|
+
lines.push(` ${import_chalk13.default.dim("work:")} ${win(s.workWindowSecs)} ${import_chalk13.default.dim("(accept \u2192 submit_work)")}`);
|
|
4621
|
+
lines.push(` ${import_chalk13.default.dim("review:")} ${win(s.reviewWindowSecs)} ${import_chalk13.default.dim("(submit_work \u2192 buyer approve / worker self-claim)")}`);
|
|
4622
|
+
lines.push(` ${import_chalk13.default.dim("dispute:")} ${win(s.disputeWindowSecs)} ${import_chalk13.default.dim("(open_dispute \u2192 operator resolve / timeout close)")}`);
|
|
4801
4623
|
lines.push("");
|
|
4802
|
-
lines.push(
|
|
4803
|
-
lines.push(` ${
|
|
4804
|
-
lines.push(` ${
|
|
4624
|
+
lines.push(import_chalk13.default.bold("Stakes:"));
|
|
4625
|
+
lines.push(` ${import_chalk13.default.dim("worker stake:")} ${s.workerStakeLamports} lamports ${import_chalk13.default.dim("(escrowed at accept_lock, returned on completion)")}`);
|
|
4626
|
+
lines.push(` ${import_chalk13.default.dim("operator dispute fee:")} ${s.operatorDisputeFeeLamports} lamports`);
|
|
4805
4627
|
lines.push("");
|
|
4806
|
-
lines.push(
|
|
4628
|
+
lines.push(import_chalk13.default.bold("Protocol fee:"));
|
|
4807
4629
|
if (!s.feeEnabled || s.feeBps === 0) {
|
|
4808
|
-
lines.push(` ${
|
|
4809
|
-
lines.push(` ${
|
|
4810
|
-
lines.push(` ${
|
|
4630
|
+
lines.push(` ${import_chalk13.default.green("DISABLED")}`);
|
|
4631
|
+
lines.push(` ${import_chalk13.default.dim("fee_bps:")} ${s.feeBps}`);
|
|
4632
|
+
lines.push(` ${import_chalk13.default.dim("fee_recipient:")} ${s.feeRecipient}`);
|
|
4811
4633
|
lines.push("");
|
|
4812
|
-
lines.push(
|
|
4634
|
+
lines.push(import_chalk13.default.dim(` New locks will snapshot fee_bps=0 \u2014 payee receives 100% on claim.`));
|
|
4813
4635
|
} else {
|
|
4814
4636
|
const pct = (s.feeBps / 100).toFixed(2);
|
|
4815
|
-
lines.push(` ${
|
|
4816
|
-
lines.push(` ${
|
|
4637
|
+
lines.push(` ${import_chalk13.default.yellow("ENABLED")} \u2014 ${pct}% of payee slice (${s.feeBps} bps)`);
|
|
4638
|
+
lines.push(` ${import_chalk13.default.dim("fee_recipient:")} ${s.feeRecipient}`);
|
|
4817
4639
|
lines.push("");
|
|
4818
|
-
lines.push(
|
|
4819
|
-
lines.push(
|
|
4640
|
+
lines.push(import_chalk13.default.dim(` New locks will snapshot fee_bps=${s.feeBps} onto themselves.`));
|
|
4641
|
+
lines.push(import_chalk13.default.dim(` Existing locks keep their lock-time snapshot \u2014 no retroactive change.`));
|
|
4820
4642
|
}
|
|
4821
4643
|
return lines.join("\n");
|
|
4822
4644
|
}
|
|
@@ -4840,11 +4662,11 @@ async function runDeriveConditionHash(opts) {
|
|
|
4840
4662
|
throw new Error(`${cmdName}: --scope is required (binds scope_summary into the condition_hash)`);
|
|
4841
4663
|
}
|
|
4842
4664
|
const api = new ArpApiClient(opts.server);
|
|
4843
|
-
const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid);
|
|
4844
|
-
progress(opts.json,
|
|
4845
|
-
progress(opts.json,
|
|
4665
|
+
const sender = resolveSenderAgent(cmdName, opts.server, opts.fromDid, opts.from);
|
|
4666
|
+
progress(opts.json, import_chalk13.default.dim(`Server: ${api.serverUrl}`));
|
|
4667
|
+
progress(opts.json, import_chalk13.default.dim(`Signer: ${sender.did}`));
|
|
4846
4668
|
const subset = projectDelegationForHash(cmdName, opts, delegationId);
|
|
4847
|
-
const hashBytes = (0,
|
|
4669
|
+
const hashBytes = (0, import_sdk17.deriveDelegationConditionHash)(subset);
|
|
4848
4670
|
const hex = (0, import_utils2.bytesToHex)(hashBytes);
|
|
4849
4671
|
if (opts.json) {
|
|
4850
4672
|
jsonOut({
|
|
@@ -4854,14 +4676,14 @@ async function runDeriveConditionHash(opts) {
|
|
|
4854
4676
|
});
|
|
4855
4677
|
return;
|
|
4856
4678
|
}
|
|
4857
|
-
console.log(
|
|
4858
|
-
console.log(
|
|
4859
|
-
console.log(
|
|
4860
|
-
if (subset.currency !== void 0) console.log(
|
|
4679
|
+
console.log(import_chalk13.default.dim(`Delegation: ${delegationId}`));
|
|
4680
|
+
console.log(import_chalk13.default.dim("Subset hashed:"));
|
|
4681
|
+
console.log(import_chalk13.default.dim(` scopeSummary: ${subset.scopeSummary ?? "(unset)"}`));
|
|
4682
|
+
if (subset.currency !== void 0) console.log(import_chalk13.default.dim(` currency.asset_id: ${subset.currency.asset_id}`));
|
|
4861
4683
|
console.log("");
|
|
4862
|
-
console.log(`${
|
|
4684
|
+
console.log(`${import_chalk13.default.bold("condition_hash:")} ${hex}`);
|
|
4863
4685
|
console.log("");
|
|
4864
|
-
console.log(
|
|
4686
|
+
console.log(import_chalk13.default.dim(`Pass to: heyarp wallet create-lock --delegation-id ${delegationId} --condition-hash ${hex} ...`));
|
|
4865
4687
|
}
|
|
4866
4688
|
function classifyRecoverOutcome(local, server) {
|
|
4867
4689
|
if (local === server) return { kind: "in-sync", value: local };
|
|
@@ -4869,7 +4691,7 @@ function classifyRecoverOutcome(local, server) {
|
|
|
4869
4691
|
return { kind: "ahead", local, server, drift: local - server };
|
|
4870
4692
|
}
|
|
4871
4693
|
async function runRecoverSequence(opts) {
|
|
4872
|
-
const sender = resolveSenderAgent("escrow recover-sequence", opts.server, opts.fromDid);
|
|
4694
|
+
const sender = resolveSenderAgent("escrow recover-sequence", opts.server, opts.fromDid, opts.from);
|
|
4873
4695
|
const signer = makeSigner(sender);
|
|
4874
4696
|
const api = new ArpApiClient(opts.server);
|
|
4875
4697
|
const local = sender.lastSenderSequence ?? 0;
|
|
@@ -4894,43 +4716,43 @@ async function runRecoverSequence(opts) {
|
|
|
4894
4716
|
applied: opts.apply === true && outcome.kind === "behind"
|
|
4895
4717
|
});
|
|
4896
4718
|
} else {
|
|
4897
|
-
console.log(
|
|
4898
|
-
console.log(
|
|
4719
|
+
console.log(import_chalk13.default.dim(`DID: ${sender.did}`));
|
|
4720
|
+
console.log(import_chalk13.default.dim(`Server: ${api.serverUrl}`));
|
|
4899
4721
|
console.log("");
|
|
4900
|
-
console.log(`${
|
|
4901
|
-
console.log(`${
|
|
4722
|
+
console.log(`${import_chalk13.default.bold("Local lastSenderSequence:")} ${local}`);
|
|
4723
|
+
console.log(`${import_chalk13.default.bold("Server lastSenderSequence:")} ${server}`);
|
|
4902
4724
|
console.log("");
|
|
4903
4725
|
if (outcome.kind === "in-sync") {
|
|
4904
|
-
console.log(
|
|
4726
|
+
console.log(import_chalk13.default.green("\u2713 In sync \u2014 no recovery needed."));
|
|
4905
4727
|
} else if (outcome.kind === "behind") {
|
|
4906
|
-
console.log(
|
|
4728
|
+
console.log(import_chalk13.default.yellow(`\u26A0 Local is BEHIND by ${outcome.drift}. Server has accepted envelopes the CLI didn't classify as post-commit.`));
|
|
4907
4729
|
if (opts.apply) {
|
|
4908
|
-
console.log(
|
|
4730
|
+
console.log(import_chalk13.default.dim("Writing server value to local state..."));
|
|
4909
4731
|
} else {
|
|
4910
|
-
console.log(
|
|
4732
|
+
console.log(import_chalk13.default.dim("Dry-run. Pass --apply to update local state to match server."));
|
|
4911
4733
|
}
|
|
4912
4734
|
} else {
|
|
4913
|
-
console.log(
|
|
4914
|
-
console.log(
|
|
4915
|
-
console.log(
|
|
4916
|
-
console.log(
|
|
4917
|
-
console.log(
|
|
4735
|
+
console.log(import_chalk13.default.red(`\u2717 Local is AHEAD of server by ${outcome.drift}. This should not happen under normal protocol flow.`));
|
|
4736
|
+
console.log(import_chalk13.default.dim("NOT applying \u2014 manual investigation needed. Possible causes:"));
|
|
4737
|
+
console.log(import_chalk13.default.dim(" - Local agents.json edited by hand to a wrong value"));
|
|
4738
|
+
console.log(import_chalk13.default.dim(" - Server data lost / rolled back"));
|
|
4739
|
+
console.log(import_chalk13.default.dim(" - HEYARP_HOME pointed at a wrong account"));
|
|
4918
4740
|
}
|
|
4919
4741
|
}
|
|
4920
4742
|
if (outcome.kind === "behind" && opts.apply) {
|
|
4921
4743
|
updateAgentLocal(opts.server, sender.did, { lastSenderSequence: outcome.server });
|
|
4922
|
-
if (!opts.json) console.log(
|
|
4744
|
+
if (!opts.json) console.log(import_chalk13.default.green(`\u2713 Local lastSenderSequence updated: ${local} \u2192 ${outcome.server}`));
|
|
4923
4745
|
}
|
|
4924
4746
|
if (outcome.kind === "behind" && !opts.apply) process.exitCode = 1;
|
|
4925
4747
|
if (outcome.kind === "ahead") process.exitCode = 2;
|
|
4926
4748
|
}
|
|
4927
4749
|
|
|
4928
4750
|
// src/commands/events.ts
|
|
4929
|
-
var
|
|
4930
|
-
var
|
|
4751
|
+
var import_sdk18 = require("@heyanon-arp/sdk");
|
|
4752
|
+
var import_chalk14 = __toESM(require("chalk"));
|
|
4931
4753
|
init_api();
|
|
4932
4754
|
function registerEventsCommand(root) {
|
|
4933
|
-
root.command("events").description("List events for a relationship (chain order, ascending index)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--since <n>", "Cursor: only events with relationshipEventIndex >= since").option("--limit <n>", "Max events to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
|
|
4755
|
+
root.command("events").description("List events for a relationship (chain order, ascending index)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--since <n>", "Cursor: only events with relationshipEventIndex >= since").option("--limit <n>", "Max events to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
4934
4756
|
"--verbose",
|
|
4935
4757
|
'After the summary table, print a framed "Full event payloads (N rows)" block \u2014 each event labelled with full eventId + serverEventHash and dumped as JSON. Mutually exclusive with --json.',
|
|
4936
4758
|
false
|
|
@@ -4969,16 +4791,16 @@ async function runEvents(relationshipId, opts) {
|
|
|
4969
4791
|
const limit = parseLimit3(opts.limit);
|
|
4970
4792
|
const since = parseSince(opts.since);
|
|
4971
4793
|
const api = new ArpApiClient(opts.server);
|
|
4972
|
-
const sender = resolveSenderAgent("events", opts.server, opts.fromDid);
|
|
4794
|
+
const sender = resolveSenderAgent("events", opts.server, opts.fromDid, opts.from);
|
|
4973
4795
|
if (!opts.json) {
|
|
4974
|
-
console.log(
|
|
4975
|
-
console.log(
|
|
4976
|
-
console.log(
|
|
4796
|
+
console.log(import_chalk14.default.dim(`Server: ${api.serverUrl}`));
|
|
4797
|
+
console.log(import_chalk14.default.dim(`Signer: ${sender.did}`));
|
|
4798
|
+
console.log(import_chalk14.default.dim(`Relationship: ${relationshipId}`));
|
|
4977
4799
|
}
|
|
4978
4800
|
const query = { limit };
|
|
4979
4801
|
if (since !== void 0) query.since = since;
|
|
4980
|
-
if (opts.successOnly) query.readModelStatus =
|
|
4981
|
-
else if (opts.rejectedOnly) query.readModelStatus =
|
|
4802
|
+
if (opts.successOnly) query.readModelStatus = import_sdk18.ReadModelStatuses.MATERIALIZED;
|
|
4803
|
+
else if (opts.rejectedOnly) query.readModelStatus = import_sdk18.ReadModelStatuses.REJECTED;
|
|
4982
4804
|
const signer = makeSigner(sender);
|
|
4983
4805
|
const events = await api.listEvents(relationshipId, signer, query);
|
|
4984
4806
|
if (opts.json) {
|
|
@@ -4986,7 +4808,7 @@ async function runEvents(relationshipId, opts) {
|
|
|
4986
4808
|
return;
|
|
4987
4809
|
}
|
|
4988
4810
|
if (events.length === 0) {
|
|
4989
|
-
console.log(
|
|
4811
|
+
console.log(import_chalk14.default.dim("\n(no events for this relationship)"));
|
|
4990
4812
|
return;
|
|
4991
4813
|
}
|
|
4992
4814
|
console.log("");
|
|
@@ -5002,20 +4824,20 @@ async function runEvents(relationshipId, opts) {
|
|
|
5002
4824
|
}));
|
|
5003
4825
|
}
|
|
5004
4826
|
const lastIndex = events[events.length - 1].relationshipEventIndex;
|
|
5005
|
-
console.log(
|
|
4827
|
+
console.log(import_chalk14.default.dim(`
|
|
5006
4828
|
${events.length} event(s). Paginate with --since ${lastIndex + 1}.`));
|
|
5007
4829
|
}
|
|
5008
4830
|
function formatEventLine(ev, selfDid, opts = {}) {
|
|
5009
|
-
const idx =
|
|
4831
|
+
const idx = import_chalk14.default.bold(`#${ev.relationshipEventIndex}`);
|
|
5010
4832
|
const eventId = opts.fullIds ? ev.eventId : eventIdHead(ev.eventId);
|
|
5011
4833
|
const type = ev.type.padEnd(20);
|
|
5012
4834
|
const direction = directionLabel(ev, selfDid, opts);
|
|
5013
4835
|
const hash = opts.fullIds ? ev.serverEventHash : hashHead(ev.serverEventHash);
|
|
5014
4836
|
const extra = extraDetail(ev);
|
|
5015
|
-
const tail = extra ? ` ${
|
|
5016
|
-
const status = ev.readModelStatus ??
|
|
5017
|
-
const statusGlyph = status ===
|
|
5018
|
-
return `${statusGlyph}${idx} ${
|
|
4837
|
+
const tail = extra ? ` ${import_chalk14.default.dim(`(${extra})`)}` : "";
|
|
4838
|
+
const status = ev.readModelStatus ?? import_sdk18.ReadModelStatuses.MATERIALIZED;
|
|
4839
|
+
const statusGlyph = status === import_sdk18.ReadModelStatuses.REJECTED ? `${import_chalk14.default.red("\u2717")} ` : " ";
|
|
4840
|
+
return `${statusGlyph}${idx} ${import_chalk14.default.cyan(eventId)} ${type} ${direction} ${import_chalk14.default.cyan(hash)}${tail}`;
|
|
5019
4841
|
}
|
|
5020
4842
|
function eventIdHead(eventId) {
|
|
5021
4843
|
if (eventId.length <= 20) return eventId;
|
|
@@ -5024,9 +4846,9 @@ function eventIdHead(eventId) {
|
|
|
5024
4846
|
function directionLabel(ev, selfDid, opts = {}) {
|
|
5025
4847
|
const senderHead = opts.fullIds ? ev.senderDid : didHead2(ev.senderDid);
|
|
5026
4848
|
const recipientHead = opts.fullIds ? ev.recipientDid : didHead2(ev.recipientDid);
|
|
5027
|
-
if (ev.senderDid === selfDid) return `${
|
|
5028
|
-
if (ev.recipientDid === selfDid) return `${
|
|
5029
|
-
return `${
|
|
4849
|
+
if (ev.senderDid === selfDid) return `${import_chalk14.default.bold("me")} \u2192 ${import_chalk14.default.dim(recipientHead)}`;
|
|
4850
|
+
if (ev.recipientDid === selfDid) return `${import_chalk14.default.dim(senderHead)} \u2192 ${import_chalk14.default.bold("me")}`;
|
|
4851
|
+
return `${import_chalk14.default.dim(senderHead)} \u2192 ${import_chalk14.default.dim(recipientHead)}`;
|
|
5030
4852
|
}
|
|
5031
4853
|
function extraDetail(ev) {
|
|
5032
4854
|
if (ev.type === "handshake_response") {
|
|
@@ -5063,7 +4885,7 @@ function parseSince(raw) {
|
|
|
5063
4885
|
}
|
|
5064
4886
|
|
|
5065
4887
|
// src/commands/guide.ts
|
|
5066
|
-
var
|
|
4888
|
+
var import_chalk15 = __toESM(require("chalk"));
|
|
5067
4889
|
|
|
5068
4890
|
// src/guide/source.ts
|
|
5069
4891
|
var GUIDE_TITLE = "HeyARP CLI \u2014 agent guide";
|
|
@@ -5597,7 +5419,7 @@ var GUIDE_SECTIONS = [
|
|
|
5597
5419
|
" 1. heyarp login link this CLI to your Solana wallet \u2014 hand the",
|
|
5598
5420
|
" printed URL to your HUMAN operator (browser",
|
|
5599
5421
|
" approval; registration REQUIRES it)",
|
|
5600
|
-
" 2. heyarp register
|
|
5422
|
+
" 2. heyarp register --name <handle> create your DID + Ed25519 keys (handle: unique, lowercase a-z0-9_ 3-32, immutable \u2014 others can address you by it instead of your DID, e.g. `send-handshake <handle>`; `heyarp whois <handle>` resolves it)",
|
|
5601
5423
|
" 3. heyarp whoami confirm your DID + login account are set",
|
|
5602
5424
|
" 4. role for THIS deal: you SEND the offer \u2192 buyer; an offer ARRIVES \u2192 worker",
|
|
5603
5425
|
" 5. BUYER only \u2014 fund your settlement wallet: `whoami --local` \u2192",
|
|
@@ -5704,7 +5526,7 @@ function renderCommand(c) {
|
|
|
5704
5526
|
${c.description}`;
|
|
5705
5527
|
}
|
|
5706
5528
|
function renderSection(s) {
|
|
5707
|
-
const lines = [
|
|
5529
|
+
const lines = [import_chalk15.default.bold(s.title)];
|
|
5708
5530
|
if (s.body && s.body.length > 0) lines.push(...s.body);
|
|
5709
5531
|
if (s.nextActions && s.nextActions.length > 0) {
|
|
5710
5532
|
lines.push(" Commands:");
|
|
@@ -5731,21 +5553,21 @@ function modeHeader(mode) {
|
|
|
5731
5553
|
""
|
|
5732
5554
|
];
|
|
5733
5555
|
case "role":
|
|
5734
|
-
return [
|
|
5556
|
+
return [import_chalk15.default.dim(`(${mode.role} guide \u2014 your slice only; run \`heyarp guide\` for the overview)`), ""];
|
|
5735
5557
|
case "setup":
|
|
5736
|
-
return [
|
|
5558
|
+
return [import_chalk15.default.dim("(setup \u2014 role-agnostic; run `heyarp guide` for the overview)"), ""];
|
|
5737
5559
|
case "troubleshoot":
|
|
5738
|
-
return [
|
|
5560
|
+
return [import_chalk15.default.dim("(troubleshooting \u2014 role-agnostic)"), ""];
|
|
5739
5561
|
}
|
|
5740
5562
|
}
|
|
5741
5563
|
function modeFooter(mode) {
|
|
5742
5564
|
if (mode.kind === "overview") {
|
|
5743
|
-
return ["",
|
|
5565
|
+
return ["", import_chalk15.default.dim("Full reference per role: `heyarp guide --role worker|buyer`. Docs: https://www.npmjs.com/package/@heyanon-arp/cli")];
|
|
5744
5566
|
}
|
|
5745
5567
|
return [];
|
|
5746
5568
|
}
|
|
5747
5569
|
function renderGuide(mode = { kind: "overview" }) {
|
|
5748
|
-
const blocks = [
|
|
5570
|
+
const blocks = [import_chalk15.default.bold(GUIDE_TITLE), "", ...modeHeader(mode)];
|
|
5749
5571
|
for (const s of selectSections(mode)) {
|
|
5750
5572
|
blocks.push(renderSection(s), "");
|
|
5751
5573
|
}
|
|
@@ -5795,7 +5617,7 @@ function renderPrompt(mode, opts = { concise: false }) {
|
|
|
5795
5617
|
// src/commands/homes.ts
|
|
5796
5618
|
var import_node_fs6 = require("fs");
|
|
5797
5619
|
var import_node_path6 = require("path");
|
|
5798
|
-
var
|
|
5620
|
+
var import_chalk16 = __toESM(require("chalk"));
|
|
5799
5621
|
var import_prompts = __toESM(require("prompts"));
|
|
5800
5622
|
|
|
5801
5623
|
// src/homes.ts
|
|
@@ -5889,27 +5711,27 @@ function runHomes(opts) {
|
|
|
5889
5711
|
return;
|
|
5890
5712
|
}
|
|
5891
5713
|
if (rows.length === 0) {
|
|
5892
|
-
console.log(
|
|
5893
|
-
console.log(
|
|
5714
|
+
console.log(import_chalk16.default.dim("(no HEYARP_HOME directories registered yet \u2014 run `heyarp register` once and the registry populates itself)"));
|
|
5715
|
+
console.log(import_chalk16.default.dim(` registry path: ${homesRegistryPath()}`));
|
|
5894
5716
|
return;
|
|
5895
5717
|
}
|
|
5896
5718
|
const header = ["Path", "Agents", "Last seen", "Status"];
|
|
5897
5719
|
const data = rows.map((r) => [
|
|
5898
|
-
r.path + (r.isCurrent ?
|
|
5720
|
+
r.path + (r.isCurrent ? import_chalk16.default.green(" (current)") : ""),
|
|
5899
5721
|
String(r.agentCount),
|
|
5900
5722
|
formatRelativeTime(r.lastSeenAt),
|
|
5901
|
-
r.exists ?
|
|
5723
|
+
r.exists ? import_chalk16.default.green("ok") : import_chalk16.default.red("missing")
|
|
5902
5724
|
]);
|
|
5903
5725
|
console.log("");
|
|
5904
5726
|
console.log(formatTable(header, data));
|
|
5905
|
-
console.log(
|
|
5727
|
+
console.log(import_chalk16.default.dim(`
|
|
5906
5728
|
Registry path: ${homesRegistryPath()}`));
|
|
5907
|
-
console.log(
|
|
5729
|
+
console.log(import_chalk16.default.dim(`Set HEYARP_HOME=<path> in a shell to switch between homes; run \`heyarp homes forget <path>\` to drop a stale entry.`));
|
|
5908
5730
|
}
|
|
5909
5731
|
async function runForget(path, opts) {
|
|
5910
5732
|
if (!opts.yes) {
|
|
5911
|
-
console.log(
|
|
5912
|
-
console.log(
|
|
5733
|
+
console.log(import_chalk16.default.yellow(`About to remove '${path}' from the homes registry.`));
|
|
5734
|
+
console.log(import_chalk16.default.dim(" Note: this only forgets the registry entry; the directory + its agents.json are NOT touched."));
|
|
5913
5735
|
const answer = await (0, import_prompts.default)(
|
|
5914
5736
|
{
|
|
5915
5737
|
type: "confirm",
|
|
@@ -5919,21 +5741,21 @@ async function runForget(path, opts) {
|
|
|
5919
5741
|
},
|
|
5920
5742
|
{
|
|
5921
5743
|
onCancel: () => {
|
|
5922
|
-
console.log(
|
|
5744
|
+
console.log(import_chalk16.default.yellow("Aborted."));
|
|
5923
5745
|
process.exit(130);
|
|
5924
5746
|
}
|
|
5925
5747
|
}
|
|
5926
5748
|
);
|
|
5927
5749
|
if (!answer.confirm) {
|
|
5928
|
-
console.log(
|
|
5750
|
+
console.log(import_chalk16.default.dim("Aborted (no changes)."));
|
|
5929
5751
|
return;
|
|
5930
5752
|
}
|
|
5931
5753
|
}
|
|
5932
5754
|
const removed = forgetHome(path);
|
|
5933
5755
|
if (removed) {
|
|
5934
|
-
console.log(
|
|
5756
|
+
console.log(import_chalk16.default.green(`\u2713 forgot ${path}`));
|
|
5935
5757
|
} else {
|
|
5936
|
-
console.log(
|
|
5758
|
+
console.log(import_chalk16.default.dim(`(no entry for ${path} in the registry \u2014 already absent)`));
|
|
5937
5759
|
}
|
|
5938
5760
|
}
|
|
5939
5761
|
function countAgents(homePath) {
|
|
@@ -5958,13 +5780,13 @@ function formatTable(header, data) {
|
|
|
5958
5780
|
const padding = " ".repeat(Math.max(0, widths[i] - lengths[i]));
|
|
5959
5781
|
return cell + padding;
|
|
5960
5782
|
}).join(" ");
|
|
5961
|
-
const headerLine =
|
|
5783
|
+
const headerLine = import_chalk16.default.bold(
|
|
5962
5784
|
pad(
|
|
5963
5785
|
header,
|
|
5964
5786
|
header.map((s) => s.length)
|
|
5965
5787
|
)
|
|
5966
5788
|
);
|
|
5967
|
-
const sepLine =
|
|
5789
|
+
const sepLine = import_chalk16.default.dim(
|
|
5968
5790
|
pad(
|
|
5969
5791
|
widths.map((w) => "-".repeat(w)),
|
|
5970
5792
|
widths
|
|
@@ -5991,7 +5813,7 @@ function formatRelativeTime(iso) {
|
|
|
5991
5813
|
}
|
|
5992
5814
|
|
|
5993
5815
|
// src/commands/inbox.ts
|
|
5994
|
-
var
|
|
5816
|
+
var import_chalk17 = __toESM(require("chalk"));
|
|
5995
5817
|
init_api();
|
|
5996
5818
|
function formatTailStartedPing(input) {
|
|
5997
5819
|
const ping = {
|
|
@@ -6009,7 +5831,7 @@ function registerInboxCommand(root) {
|
|
|
6009
5831
|
).argument("[did]", "Recipient DID (did:arp:...) \u2014 must have local state. Optional when --from-did is given OR exactly one agent is registered for the resolved server.").option("--server <url>", "Override ARP server base URL").option("--limit <n>", "Max events to return (1..100)", "20").option("--before <iso>", "Cursor: only events strictly OLDER than this RFC 3339 timestamp").option("--before-event-id <id>", "Tiebreaker for --before \u2014 pass the previous page's last eventId").option(
|
|
6010
5832
|
"--since <iso>",
|
|
6011
5833
|
"Forward cursor: only events strictly NEWER than this RFC 3339 timestamp. Polling workers persist this between iterations to skip already-handled envelopes (fixes the double-fire pattern of re-reading from the same head). Pages are returned OLDEST-FIRST when --since is used alone (so a poller can advance its watermark to the page tail without losing backlogged events); combine with --before for a newest-first range query."
|
|
6012
|
-
).option("--since-event-id <id>", "Tiebreaker for --since \u2014 pass the previous tick's last handled eventId. Combine with --since for same-millisecond stability.").option("--verbose", "After the table, print the full JSON envelope for each event with a per-row label that includes the full serverEventHash + eventId", false).option("--json", "Machine-readable mode \u2014 emit a single JSON array of events, no human-format summary, no chalk colors. Pipe-safe.", false).option("--full-ids", "Print sender DID and full serverEventHash in the table (no truncation). Use when you need to copy-paste either value into another command.", false).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option(
|
|
5834
|
+
).option("--since-event-id <id>", "Tiebreaker for --since \u2014 pass the previous tick's last handled eventId. Combine with --since for same-millisecond stability.").option("--verbose", "After the table, print the full JSON envelope for each event with a per-row label that includes the full serverEventHash + eventId", false).option("--json", "Machine-readable mode \u2014 emit a single JSON array of events, no human-format summary, no chalk colors. Pipe-safe.", false).option("--full-ids", "Print sender DID and full serverEventHash in the table (no truncation). Use when you need to copy-paste either value into another command.", false).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
6013
5835
|
"--tail",
|
|
6014
5836
|
// The polling output (`heyarp inbox --json`) emits raw
|
|
6015
5837
|
// `EventPublic[]` rows with `.body` at the top level, but
|
|
@@ -6030,7 +5852,7 @@ async function runInbox(positionalDid, opts) {
|
|
|
6030
5852
|
throw new Error(`inbox: positional <did> (${positionalDid}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
|
|
6031
5853
|
}
|
|
6032
5854
|
const explicitDid = positionalDid ?? opts.fromDid;
|
|
6033
|
-
const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("inbox", opts.server, void 0);
|
|
5855
|
+
const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("inbox", opts.server, void 0, opts.from);
|
|
6034
5856
|
const did = local.did;
|
|
6035
5857
|
if (opts.tail) {
|
|
6036
5858
|
await runInboxTail(did, local, opts);
|
|
@@ -6038,8 +5860,8 @@ async function runInbox(positionalDid, opts) {
|
|
|
6038
5860
|
}
|
|
6039
5861
|
const api = new ArpApiClient(opts.server);
|
|
6040
5862
|
if (!opts.json) {
|
|
6041
|
-
console.log(
|
|
6042
|
-
console.log(
|
|
5863
|
+
console.log(import_chalk17.default.dim(`Server: ${api.serverUrl}`));
|
|
5864
|
+
console.log(import_chalk17.default.dim(`Signer: ${local.did}`));
|
|
6043
5865
|
}
|
|
6044
5866
|
const query = { limit };
|
|
6045
5867
|
if (opts.before) query.before = opts.before;
|
|
@@ -6053,7 +5875,7 @@ async function runInbox(positionalDid, opts) {
|
|
|
6053
5875
|
return;
|
|
6054
5876
|
}
|
|
6055
5877
|
if (events.length === 0) {
|
|
6056
|
-
console.log(
|
|
5878
|
+
console.log(import_chalk17.default.dim("\n(no events addressed to me \u2014 `heyarp events <relationship-id>` shows the chain-wide listing)"));
|
|
6057
5879
|
return;
|
|
6058
5880
|
}
|
|
6059
5881
|
console.log("");
|
|
@@ -6068,16 +5890,16 @@ async function runInbox(positionalDid, opts) {
|
|
|
6068
5890
|
secondary: `eventId=${ev.eventId} serverEventHash=${ev.serverEventHash}`
|
|
6069
5891
|
}));
|
|
6070
5892
|
}
|
|
6071
|
-
const addressedToMeHint =
|
|
5893
|
+
const addressedToMeHint = import_chalk17.default.dim(" (envelopes addressed to me \u2014 for the full chain see `heyarp events <relationship-id>`)");
|
|
6072
5894
|
if (opts.since && !opts.before) {
|
|
6073
5895
|
console.log(
|
|
6074
|
-
|
|
5896
|
+
import_chalk17.default.dim(
|
|
6075
5897
|
`
|
|
6076
5898
|
${events.length} event(s) (oldest-first).${addressedToMeHint} Advance the forward cursor with --since <serverTimestamp> --since-event-id <eventId> using the LAST row above.`
|
|
6077
5899
|
)
|
|
6078
5900
|
);
|
|
6079
5901
|
} else {
|
|
6080
|
-
console.log(
|
|
5902
|
+
console.log(import_chalk17.default.dim(`
|
|
6081
5903
|
${events.length} event(s).${addressedToMeHint} Paginate with --before <serverTimestamp> --before-event-id <eventId> using the LAST row above.`));
|
|
6082
5904
|
}
|
|
6083
5905
|
}
|
|
@@ -6092,7 +5914,7 @@ async function runInboxTail(did, local, opts) {
|
|
|
6092
5914
|
} else {
|
|
6093
5915
|
warn(
|
|
6094
5916
|
opts.json,
|
|
6095
|
-
|
|
5917
|
+
import_chalk17.default.yellow(
|
|
6096
5918
|
"\u26A0 inbox --tail: stdout is piped but `process.stdout._handle.setBlocking` is unavailable in this Node runtime. Buffered writes may delay event delivery. Fall back to polling (`heyarp inbox --json`) if events stop arriving."
|
|
6097
5919
|
)
|
|
6098
5920
|
);
|
|
@@ -6102,9 +5924,9 @@ async function runInboxTail(did, local, opts) {
|
|
|
6102
5924
|
if (opts.json) {
|
|
6103
5925
|
console.log(formatTailStartedPing({ server: api.serverUrl, signer: local.did, stdoutBlockingApplied }));
|
|
6104
5926
|
} else {
|
|
6105
|
-
console.log(
|
|
6106
|
-
console.log(
|
|
6107
|
-
console.log(
|
|
5927
|
+
console.log(import_chalk17.default.dim(`Server: ${api.serverUrl}`));
|
|
5928
|
+
console.log(import_chalk17.default.dim(`Signer: ${local.did}`));
|
|
5929
|
+
console.log(import_chalk17.default.dim("Mode: --tail (live SSE, Ctrl-C to stop)"));
|
|
6108
5930
|
}
|
|
6109
5931
|
const controller = new AbortController();
|
|
6110
5932
|
let userAborted = false;
|
|
@@ -6123,7 +5945,7 @@ async function runInboxTail(did, local, opts) {
|
|
|
6123
5945
|
}
|
|
6124
5946
|
if (event.type === "heartbeat") continue;
|
|
6125
5947
|
if (event.type === "connected") {
|
|
6126
|
-
console.log(
|
|
5948
|
+
console.log(import_chalk17.default.green("\u25CF stream open \u2014 listening for envelopes..."));
|
|
6127
5949
|
continue;
|
|
6128
5950
|
}
|
|
6129
5951
|
if (event.type === "envelope") {
|
|
@@ -6137,7 +5959,7 @@ async function runInboxTail(did, local, opts) {
|
|
|
6137
5959
|
}
|
|
6138
5960
|
continue;
|
|
6139
5961
|
}
|
|
6140
|
-
console.log(
|
|
5962
|
+
console.log(import_chalk17.default.dim(`(unknown event: ${event.type})`));
|
|
6141
5963
|
}
|
|
6142
5964
|
if (!userAborted) {
|
|
6143
5965
|
throw new Error("inbox --tail: stream ended unexpectedly (server may have restarted, or change stream errored). Re-run to reconnect.");
|
|
@@ -6145,7 +5967,7 @@ async function runInboxTail(did, local, opts) {
|
|
|
6145
5967
|
} catch (err) {
|
|
6146
5968
|
const name = err.name;
|
|
6147
5969
|
if (name === "AbortError" || userAborted) {
|
|
6148
|
-
if (!opts.json) console.log(
|
|
5970
|
+
if (!opts.json) console.log(import_chalk17.default.dim("\nstream closed."));
|
|
6149
5971
|
return;
|
|
6150
5972
|
}
|
|
6151
5973
|
throw err;
|
|
@@ -6165,15 +5987,15 @@ function formatInboxTable(events, opts = {}) {
|
|
|
6165
5987
|
]);
|
|
6166
5988
|
const widths = header.map((h, i) => Math.max(h.length, ...data.map((row) => row[i].length)));
|
|
6167
5989
|
const pad = (cells) => cells.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
6168
|
-
const lines = [
|
|
6169
|
-
const detail = events.map((ev) => ` ${
|
|
5990
|
+
const lines = [import_chalk17.default.bold(pad(header)), import_chalk17.default.dim(pad(widths.map((w) => "-".repeat(w)))), ...data.map((row) => pad(row))];
|
|
5991
|
+
const detail = events.map((ev) => ` ${import_chalk17.default.dim("eventId:")} ${import_chalk17.default.cyan(ev.eventId)} ${import_chalk17.default.dim("serverTimestamp:")} ${import_chalk17.default.cyan(ev.serverTimestamp)}`).join("\n");
|
|
6170
5992
|
return `${lines.join("\n")}
|
|
6171
5993
|
|
|
6172
|
-
${
|
|
5994
|
+
${import_chalk17.default.bold("Pagination cursors")} (last \u2192 first):
|
|
6173
5995
|
${detail}`;
|
|
6174
5996
|
}
|
|
6175
5997
|
function hashHead2(hash) {
|
|
6176
|
-
if (!hash) return
|
|
5998
|
+
if (!hash) return import_chalk17.default.dim("(none)");
|
|
6177
5999
|
if (hash.length <= 14) return hash;
|
|
6178
6000
|
return `${hash.slice(0, 14)}...`;
|
|
6179
6001
|
}
|
|
@@ -6189,8 +6011,8 @@ function parseLimit4(raw) {
|
|
|
6189
6011
|
// src/commands/keys.ts
|
|
6190
6012
|
var import_node_crypto2 = require("crypto");
|
|
6191
6013
|
var import_node_fs7 = require("fs");
|
|
6192
|
-
var
|
|
6193
|
-
var
|
|
6014
|
+
var import_sdk19 = require("@heyanon-arp/sdk");
|
|
6015
|
+
var import_chalk18 = __toESM(require("chalk"));
|
|
6194
6016
|
function writeSecretFile(path, body) {
|
|
6195
6017
|
const tmp = `${path}.tmp.${(0, import_node_crypto2.randomBytes)(8).toString("hex")}`;
|
|
6196
6018
|
const fd = (0, import_node_fs7.openSync)(tmp, "wx", 384);
|
|
@@ -6217,19 +6039,19 @@ function writeSecretFile(path, body) {
|
|
|
6217
6039
|
function registerKeysCommand(root) {
|
|
6218
6040
|
const keys = root.command("keys").description("Local key utilities");
|
|
6219
6041
|
keys.command("gen").description("Generate a fresh identity + settlement keypair (no save by default)").action(() => {
|
|
6220
|
-
const identity = (0,
|
|
6221
|
-
const settlement = (0,
|
|
6042
|
+
const identity = (0, import_sdk19.generateKeyPair)();
|
|
6043
|
+
const settlement = (0, import_sdk19.generateKeyPair)();
|
|
6222
6044
|
const out = [
|
|
6223
|
-
|
|
6224
|
-
` public (base58btc): ${
|
|
6225
|
-
` secret (base64) : ${
|
|
6045
|
+
import_chalk18.default.bold("Identity key (Ed25519)"),
|
|
6046
|
+
` public (base58btc): ${import_chalk18.default.cyan((0, import_sdk19.base58btcEncode)(identity.publicKey))}`,
|
|
6047
|
+
` secret (base64) : ${import_chalk18.default.yellow(Buffer.from(identity.secretKey).toString("base64"))}`,
|
|
6226
6048
|
"",
|
|
6227
|
-
|
|
6228
|
-
` public (base58btc): ${
|
|
6229
|
-
` secret (base64) : ${
|
|
6049
|
+
import_chalk18.default.bold("Settlement key (Ed25519)"),
|
|
6050
|
+
` public (base58btc): ${import_chalk18.default.cyan((0, import_sdk19.base58btcEncode)(settlement.publicKey))}`,
|
|
6051
|
+
` secret (base64) : ${import_chalk18.default.yellow(Buffer.from(settlement.secretKey).toString("base64"))}`,
|
|
6230
6052
|
"",
|
|
6231
|
-
|
|
6232
|
-
` ${
|
|
6053
|
+
import_chalk18.default.bold("Resulting DID"),
|
|
6054
|
+
` ${import_chalk18.default.cyan((0, import_sdk19.formatDid)(identity.publicKey))}`
|
|
6233
6055
|
];
|
|
6234
6056
|
console.log(out.join("\n"));
|
|
6235
6057
|
});
|
|
@@ -6238,20 +6060,20 @@ function registerKeysCommand(root) {
|
|
|
6238
6060
|
const json = JSON.stringify(toKeyBundle(agent, (/* @__PURE__ */ new Date()).toISOString()), null, 2);
|
|
6239
6061
|
if (opts.out) {
|
|
6240
6062
|
writeSecretFile(opts.out, json);
|
|
6241
|
-
process.stderr.write(
|
|
6063
|
+
process.stderr.write(import_chalk18.default.yellow(`\u26A0 wrote SECRET key bundle to ${opts.out} (mode 0600) \u2014 keep it offline; anyone with this file can operate ${did}.
|
|
6242
6064
|
`));
|
|
6243
6065
|
console.log(opts.out);
|
|
6244
6066
|
} else {
|
|
6245
|
-
process.stderr.write(
|
|
6067
|
+
process.stderr.write(import_chalk18.default.yellow("\u26A0 this is a SECRET key bundle \u2014 redirect to a file and keep it offline.\n"));
|
|
6246
6068
|
console.log(json);
|
|
6247
6069
|
}
|
|
6248
6070
|
});
|
|
6249
6071
|
keys.command("whoami").description("Print the DID derived from a base64-encoded identity secret key").argument("<secret-key-b64>", "32-byte Ed25519 seed, base64").action((secretKeyB64) => {
|
|
6250
6072
|
const seed = decodeSeed(secretKeyB64);
|
|
6251
|
-
const pub = (0,
|
|
6252
|
-
const did = (0,
|
|
6253
|
-
console.log(`${
|
|
6254
|
-
console.log(`${
|
|
6073
|
+
const pub = (0, import_sdk19.getPublicKey)(seed);
|
|
6074
|
+
const did = (0, import_sdk19.formatDid)(pub);
|
|
6075
|
+
console.log(`${import_chalk18.default.bold("DID")}: ${import_chalk18.default.cyan(did)}`);
|
|
6076
|
+
console.log(`${import_chalk18.default.bold("Identity public key (base58btc)")}: ${import_chalk18.default.cyan((0, import_sdk19.base58btcEncode)(pub))}`);
|
|
6255
6077
|
});
|
|
6256
6078
|
}
|
|
6257
6079
|
function decodeSeed(b64) {
|
|
@@ -6268,7 +6090,7 @@ function decodeSeed(b64) {
|
|
|
6268
6090
|
}
|
|
6269
6091
|
|
|
6270
6092
|
// src/commands/list.ts
|
|
6271
|
-
var
|
|
6093
|
+
var import_chalk19 = __toESM(require("chalk"));
|
|
6272
6094
|
function registerListCommand(root) {
|
|
6273
6095
|
root.command("list").description("List agents registered locally (~/.heyarp/agents.json)").option("--json", "Machine-readable mode \u2014 emit the local agents as a single JSON array on stdout ({serverUrl, did, name, tags, registeredAt}[]).", false).action((opts) => {
|
|
6274
6096
|
const rows = listAgents();
|
|
@@ -6277,7 +6099,7 @@ function registerListCommand(root) {
|
|
|
6277
6099
|
return;
|
|
6278
6100
|
}
|
|
6279
6101
|
if (rows.length === 0) {
|
|
6280
|
-
console.log(
|
|
6102
|
+
console.log(import_chalk19.default.dim(`No local agents. State file: ${stateFilePath()}`));
|
|
6281
6103
|
return;
|
|
6282
6104
|
}
|
|
6283
6105
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -6289,7 +6111,7 @@ function registerListCommand(root) {
|
|
|
6289
6111
|
for (const [serverUrl, group] of grouped) {
|
|
6290
6112
|
if (!first) console.log("");
|
|
6291
6113
|
first = false;
|
|
6292
|
-
console.log(
|
|
6114
|
+
console.log(import_chalk19.default.bold(`Server: ${serverUrl}`));
|
|
6293
6115
|
console.log(formatAgentsTable(group.map(({ agent }) => ({ did: agent.did, name: agent.name, tags: agent.tags, registeredAt: agent.registeredAt }))));
|
|
6294
6116
|
}
|
|
6295
6117
|
});
|
|
@@ -6297,7 +6119,7 @@ function registerListCommand(root) {
|
|
|
6297
6119
|
|
|
6298
6120
|
// src/commands/login.ts
|
|
6299
6121
|
var import_node_crypto3 = require("crypto");
|
|
6300
|
-
var
|
|
6122
|
+
var import_chalk20 = __toESM(require("chalk"));
|
|
6301
6123
|
init_api();
|
|
6302
6124
|
var POLL_INTERVAL_MS = 2e3;
|
|
6303
6125
|
var POLL_TIMEOUT_MS = 11 * 6e4;
|
|
@@ -6367,9 +6189,9 @@ function registerLoginCommand(root) {
|
|
|
6367
6189
|
jsonOut({ serverUrl: result.serverUrl, wallet: result.wallet, credentialsPath: credentialsFilePath() });
|
|
6368
6190
|
} else {
|
|
6369
6191
|
console.log("");
|
|
6370
|
-
console.log(`${
|
|
6371
|
-
console.log(
|
|
6372
|
-
console.log(
|
|
6192
|
+
console.log(`${import_chalk20.default.green("Logged in as")} ${import_chalk20.default.cyan(result.wallet)}`);
|
|
6193
|
+
console.log(import_chalk20.default.dim(`If that is not the wallet you approved with, run heyarp logout immediately.`));
|
|
6194
|
+
console.log(import_chalk20.default.dim(`Credential saved to ${credentialsFilePath()} (mode 0600).`));
|
|
6373
6195
|
}
|
|
6374
6196
|
} catch (err) {
|
|
6375
6197
|
emitActionError(err, cmd);
|
|
@@ -6379,7 +6201,7 @@ function registerLoginCommand(root) {
|
|
|
6379
6201
|
}
|
|
6380
6202
|
|
|
6381
6203
|
// src/commands/logout.ts
|
|
6382
|
-
var
|
|
6204
|
+
var import_chalk21 = __toESM(require("chalk"));
|
|
6383
6205
|
init_api();
|
|
6384
6206
|
function registerLogoutCommand(root) {
|
|
6385
6207
|
root.command("logout").description("Log out of the ARP server: revoke the stored CLI auth token (best-effort) and delete the local credential for this server.").option("--server <url>", "Override ARP server base URL").option("--json", "machine-readable output ({ serverUrl, loggedOut, wallet? })", false).action(async (opts, cmd) => {
|
|
@@ -6404,7 +6226,7 @@ function registerLogoutCommand(root) {
|
|
|
6404
6226
|
if (opts.json) {
|
|
6405
6227
|
jsonOut({ serverUrl: api.serverUrl, loggedOut: true, wallet: credential.wallet });
|
|
6406
6228
|
} else {
|
|
6407
|
-
console.log(`${
|
|
6229
|
+
console.log(`${import_chalk21.default.green("Logged out of")} ${api.serverUrl} ${import_chalk21.default.dim(`(was ${credential.wallet})`)}`);
|
|
6408
6230
|
}
|
|
6409
6231
|
} catch (err) {
|
|
6410
6232
|
emitActionError(err, cmd);
|
|
@@ -6413,13 +6235,65 @@ function registerLogoutCommand(root) {
|
|
|
6413
6235
|
});
|
|
6414
6236
|
}
|
|
6415
6237
|
|
|
6238
|
+
// src/commands/name.ts
|
|
6239
|
+
var import_sdk20 = require("@heyanon-arp/sdk");
|
|
6240
|
+
var import_chalk22 = __toESM(require("chalk"));
|
|
6241
|
+
init_api();
|
|
6242
|
+
function registerNameCommand(root) {
|
|
6243
|
+
const name = root.command("name").description("Agent name (handle) utilities.");
|
|
6244
|
+
name.command("check").description("Check whether an agent name (handle) can be registered \u2014 reports invalid / reserved / taken / available without registering.").argument("<name>", "Candidate handle (lowercase a-z0-9_, 3-32 chars)").option("--server <url>", "Override ARP server base URL").option("--json", "Emit {name, available, reason, did?} as a single JSON object on stdout.", false).action(async (input, opts) => {
|
|
6245
|
+
const result = await runNameCheck(input, opts);
|
|
6246
|
+
if (opts.json) {
|
|
6247
|
+
jsonOut(result);
|
|
6248
|
+
} else {
|
|
6249
|
+
printNameCheck(input, result);
|
|
6250
|
+
}
|
|
6251
|
+
if (!result.available) process.exitCode = 1;
|
|
6252
|
+
});
|
|
6253
|
+
}
|
|
6254
|
+
async function runNameCheck(input, opts) {
|
|
6255
|
+
const name = (0, import_sdk20.normalizeName)(input);
|
|
6256
|
+
if (!(0, import_sdk20.isValidAgentName)(name)) {
|
|
6257
|
+
return { name, available: false, reason: "invalid" };
|
|
6258
|
+
}
|
|
6259
|
+
if ((0, import_sdk20.isReservedName)(name)) {
|
|
6260
|
+
return { name, available: false, reason: "reserved" };
|
|
6261
|
+
}
|
|
6262
|
+
const api = new ArpApiClient(opts.server);
|
|
6263
|
+
progress(opts.json, import_chalk22.default.dim(`Server: ${api.serverUrl}`));
|
|
6264
|
+
try {
|
|
6265
|
+
const profile = await api.discoverByName(name);
|
|
6266
|
+
return { name, available: false, reason: "taken", did: profile.did };
|
|
6267
|
+
} catch (err) {
|
|
6268
|
+
if (err instanceof ApiError && err.payload.code === "AGENT_NOT_FOUND") {
|
|
6269
|
+
return { name, available: true, reason: null };
|
|
6270
|
+
}
|
|
6271
|
+
throw err;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
function printNameCheck(input, r) {
|
|
6275
|
+
switch (r.reason) {
|
|
6276
|
+
case "invalid":
|
|
6277
|
+
console.log(`${import_chalk22.default.red("\u2717")} '${input}' is not a valid handle \u2014 must be lowercase a-z0-9_, 3-32 chars.`);
|
|
6278
|
+
break;
|
|
6279
|
+
case "reserved":
|
|
6280
|
+
console.log(`${import_chalk22.default.red("\u2717")} '${r.name}' is reserved and cannot be registered.`);
|
|
6281
|
+
break;
|
|
6282
|
+
case "taken":
|
|
6283
|
+
console.log(`${import_chalk22.default.yellow("\u2717")} '${r.name}' is taken \u2192 ${import_chalk22.default.cyan(r.did ?? "(unknown DID)")}`);
|
|
6284
|
+
break;
|
|
6285
|
+
default:
|
|
6286
|
+
console.log(`${import_chalk22.default.green("\u2713")} '${r.name}' is available.`);
|
|
6287
|
+
}
|
|
6288
|
+
}
|
|
6289
|
+
|
|
6416
6290
|
// src/commands/profile.ts
|
|
6417
|
-
var
|
|
6418
|
-
var
|
|
6291
|
+
var import_sdk21 = require("@heyanon-arp/sdk");
|
|
6292
|
+
var import_chalk23 = __toESM(require("chalk"));
|
|
6419
6293
|
init_api();
|
|
6420
6294
|
function registerProfileCommand(root) {
|
|
6421
6295
|
root.command("profile").description("Composed agent profile: public fields + reputation + liveness, in one read.").argument("<did>", "did:arp:<base58btc> identifier").option("--server <url>", "Override ARP server base URL").option("--json", "Emit the profile as JSON on stdout.", false).action(async (did, opts) => {
|
|
6422
|
-
if (!(0,
|
|
6296
|
+
if (!(0, import_sdk21.isValidDid)(did)) {
|
|
6423
6297
|
throw new Error(`'${did}' is not a syntactically valid did:arp identifier`);
|
|
6424
6298
|
}
|
|
6425
6299
|
const api = new ArpApiClient(opts.server);
|
|
@@ -6430,33 +6304,33 @@ function registerProfileCommand(root) {
|
|
|
6430
6304
|
}
|
|
6431
6305
|
const j = false;
|
|
6432
6306
|
const s = p.reputation.scores;
|
|
6433
|
-
const live = p.liveness.online ?
|
|
6307
|
+
const live = p.liveness.online ? import_chalk23.default.green("\u25CF online") : import_chalk23.default.dim("\u25CB offline");
|
|
6434
6308
|
const tags = p.tags.map(sanitizeForTerminal).filter((t) => t.length > 0);
|
|
6435
|
-
progress(j,
|
|
6436
|
-
if (p.description) progress(j,
|
|
6437
|
-
progress(j, ` ${live}${p.liveness.inboxStreamActive ?
|
|
6438
|
-
progress(j, ` tags: ${tags.length ? tags.join(", ") :
|
|
6309
|
+
progress(j, import_chalk23.default.bold(`${p.name ? sanitizeForTerminal(p.name) : "(unnamed)"} ${import_chalk23.default.dim(p.did)}`));
|
|
6310
|
+
if (p.description) progress(j, import_chalk23.default.dim(` ${sanitizeForTerminal(p.description)}`));
|
|
6311
|
+
progress(j, ` ${live}${p.liveness.inboxStreamActive ? import_chalk23.default.green(" \xB7 stream attached") : ""} \xB7 last seen ${p.liveness.lastSeenAt ?? "\u2014"}`);
|
|
6312
|
+
progress(j, ` tags: ${tags.length ? tags.join(", ") : import_chalk23.default.dim("none")}`);
|
|
6439
6313
|
progress(j, "");
|
|
6440
|
-
progress(j,
|
|
6314
|
+
progress(j, import_chalk23.default.bold(" Reputation") + import_chalk23.default.dim(" (informational)"));
|
|
6441
6315
|
progress(
|
|
6442
6316
|
j,
|
|
6443
6317
|
` composite ${s.composite.toFixed(2)} \xB7 reliability ${s.reliability.toFixed(2)} \xB7 settlement ${s.settlement.toFixed(2)} \xB7 dispute-health ${s.disputeHealth.toFixed(2)}`
|
|
6444
6318
|
);
|
|
6445
|
-
progress(j,
|
|
6319
|
+
progress(j, import_chalk23.default.dim(` ${p.reputation.computed ? `computed ${p.reputation.lastComputedAt}` : "never computed (neutral cold-start)"}`));
|
|
6446
6320
|
});
|
|
6447
6321
|
}
|
|
6448
6322
|
|
|
6449
6323
|
// src/commands/receipt.ts
|
|
6450
|
-
var
|
|
6324
|
+
var import_sdk22 = require("@heyanon-arp/sdk");
|
|
6451
6325
|
var import_shield2 = require("@heyanon-arp/shield");
|
|
6452
|
-
var
|
|
6326
|
+
var import_chalk24 = __toESM(require("chalk"));
|
|
6453
6327
|
init_api();
|
|
6454
6328
|
function registerReceiptCommands(root) {
|
|
6455
6329
|
const cmd = root.command("receipt").description("Receipt envelopes \u2014 the payee proposes a delivery record (payment consent is on-chain via claim_work_payment)");
|
|
6456
6330
|
registerPropose(cmd);
|
|
6457
6331
|
}
|
|
6458
6332
|
function registerPropose(parent) {
|
|
6459
|
-
parent.command("propose").description("Send a receipt envelope as the PAYEE. Row lands PROPOSED; the buyer approves payment on-chain via claim_work_payment.").argument("<recipient
|
|
6333
|
+
parent.command("propose").description("Send a receipt envelope as the PAYEE. Row lands PROPOSED; the buyer approves payment on-chain via claim_work_payment.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (= caller / offerer of the parent delegation)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").argument("[request-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_request payload being settled. Omit when --auto-hashes is set.").argument("[response-hash]", "sha256:<64 hex> \u2014 SHA-256 of the work_response payload being settled. Omit when --auto-hashes is set.").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--verdict <s>", "verdict_proposed (accepted | accepted_with_notes | rejected)", "accepted").option("--notes-hash <sha256>", "Optional sha256:<64 hex> notes hash").option("--deliverable-hash <sha256>", "Optional sha256:<64 hex> deliverable hash").option("--input-tokens <n>", "Optional usage.input_tokens").option("--output-tokens <n>", "Optional usage.output_tokens").option("--latency-ms <n>", "Optional usage.latency_ms").option("--model <name>", "Optional usage.model").option("--computed-amount <s>", "Optional usage.computed_amount").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option(
|
|
6460
6334
|
"--auto-hashes",
|
|
6461
6335
|
"Compute request_hash + response_hash automatically from the work-log row at (--rel-id, <delegation-id>, --request-id). Positional <request-hash>/<response-hash> become optional; if supplied they must match the computed values (consistency check). --rel-id and --request-id auto-resolve from local state when unambiguous \u2014 pass them explicitly only if the lookup finds multiple candidates.",
|
|
6462
6336
|
false
|
|
@@ -6476,7 +6350,7 @@ function registerPropose(parent) {
|
|
|
6476
6350
|
} catch (err) {
|
|
6477
6351
|
emitActionError(err, cmd);
|
|
6478
6352
|
if (!opts.json && err instanceof ApiError && err.payload.code === "RECEIPT_ALREADY_EXISTS") {
|
|
6479
|
-
console.error(
|
|
6353
|
+
console.error(import_chalk24.default.dim(" This receipt already exists (a prior propose committed it). Do NOT re-propose \u2014 payment consent is on-chain (claim_work_payment)."));
|
|
6480
6354
|
}
|
|
6481
6355
|
process.exitCode = 1;
|
|
6482
6356
|
}
|
|
@@ -6488,7 +6362,7 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6488
6362
|
"receipt propose: --verbose and --json are mutually exclusive. --json already emits the full server response as a structured payload; --verbose adds an envelope + response dump on top that would break `--json | jq`."
|
|
6489
6363
|
);
|
|
6490
6364
|
}
|
|
6491
|
-
|
|
6365
|
+
recipientDid = await resolveRecipient(opts.server, "receipt propose", recipientDid, { json: opts.json });
|
|
6492
6366
|
delegationId = requireUuidNormalised2("receipt propose", delegationId, "<delegation-id>");
|
|
6493
6367
|
if (opts.relId) opts.relId = requireUuidNormalised2("receipt propose", opts.relId, "--rel-id");
|
|
6494
6368
|
const verdict = parseVerdict("receipt propose", opts.verdict);
|
|
@@ -6497,12 +6371,12 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6497
6371
|
if (opts.deliverableHash) requireSha256("receipt propose", opts.deliverableHash, "--deliverable-hash");
|
|
6498
6372
|
const usage = parseUsage("receipt propose", opts);
|
|
6499
6373
|
const api = new ArpApiClient(opts.server);
|
|
6500
|
-
const sender = resolveSenderAgent("receipt propose", opts.server, opts.fromDid);
|
|
6374
|
+
const sender = resolveSenderAgent("receipt propose", opts.server, opts.fromDid, opts.from);
|
|
6501
6375
|
if (!opts.relId && opts.autoHashes) {
|
|
6502
6376
|
opts.relId = await resolveAutoRelId(api, sender, delegationId);
|
|
6503
6377
|
progress(
|
|
6504
6378
|
opts.json,
|
|
6505
|
-
|
|
6379
|
+
import_chalk24.default.dim(`[auto-rel-id] resolved --rel-id=${opts.relId} (delegation found in exactly one of your relationships; pass --rel-id explicitly to override)`)
|
|
6506
6380
|
);
|
|
6507
6381
|
}
|
|
6508
6382
|
if (opts.relId) {
|
|
@@ -6518,7 +6392,7 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6518
6392
|
opts.requestId = await resolveAutoRequestId(api, sender, opts.relId, delegationId);
|
|
6519
6393
|
progress(
|
|
6520
6394
|
opts.json,
|
|
6521
|
-
|
|
6395
|
+
import_chalk24.default.dim(
|
|
6522
6396
|
`[auto-request-id] resolved --request-id=${opts.requestId} (unique 'responded' work_log under this delegation; pass --request-id explicitly to override)`
|
|
6523
6397
|
)
|
|
6524
6398
|
);
|
|
@@ -6537,8 +6411,8 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6537
6411
|
}
|
|
6538
6412
|
requestHash = computed.requestHash;
|
|
6539
6413
|
responseHash = computed.responseHash;
|
|
6540
|
-
progress(opts.json,
|
|
6541
|
-
progress(opts.json,
|
|
6414
|
+
progress(opts.json, import_chalk24.default.dim(`[auto-hashes] request_hash: ${requestHash} (from work-log ${opts.relId}/${delegationId}/${opts.requestId})`));
|
|
6415
|
+
progress(opts.json, import_chalk24.default.dim(`[auto-hashes] response_hash: ${responseHash}`));
|
|
6542
6416
|
} else {
|
|
6543
6417
|
if (requestHashArg === void 0 || responseHashArg === void 0) {
|
|
6544
6418
|
throw new Error("receipt propose: <request-hash> and <response-hash> are required (or pass --auto-hashes + --rel-id + --request-id to derive them from the work-log)");
|
|
@@ -6558,11 +6432,11 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6558
6432
|
if (opts.deliverableHash) content.deliverable_hash = opts.deliverableHash;
|
|
6559
6433
|
if (usage) content.usage = usage;
|
|
6560
6434
|
const body = { type: "receipt", content };
|
|
6561
|
-
progress(opts.json,
|
|
6562
|
-
progress(opts.json,
|
|
6563
|
-
progress(opts.json,
|
|
6564
|
-
progress(opts.json,
|
|
6565
|
-
progress(opts.json,
|
|
6435
|
+
progress(opts.json, import_chalk24.default.dim(`Server: ${api.serverUrl}`));
|
|
6436
|
+
progress(opts.json, import_chalk24.default.dim(`Sender (payee): ${sender.did}`));
|
|
6437
|
+
progress(opts.json, import_chalk24.default.dim(`Recipient (caller): ${recipientDid}`));
|
|
6438
|
+
progress(opts.json, import_chalk24.default.dim(`Delegation: ${delegationId}`));
|
|
6439
|
+
progress(opts.json, import_chalk24.default.dim(`Verdict (proposed): ${verdict}`));
|
|
6566
6440
|
const result = await sendReceiptEnvelope({ api, sender, recipientDid, body, attachments: void 0, ttlSeconds, verbose: opts.verbose, server: opts.server });
|
|
6567
6441
|
if (opts.json) {
|
|
6568
6442
|
const json = {
|
|
@@ -6583,10 +6457,10 @@ async function runPropose(recipientDid, delegationId, requestHashArg, responseHa
|
|
|
6583
6457
|
return;
|
|
6584
6458
|
}
|
|
6585
6459
|
printIngestResult2(result);
|
|
6586
|
-
console.log(
|
|
6587
|
-
Receipt event hash: ${
|
|
6588
|
-
console.log(
|
|
6589
|
-
console.log(
|
|
6460
|
+
console.log(import_chalk24.default.dim(`
|
|
6461
|
+
Receipt event hash: ${import_chalk24.default.cyan(result.serverEventHash)}`));
|
|
6462
|
+
console.log(import_chalk24.default.dim("Receipt recorded. Payment consent is ON-CHAIN now: the buyer approves by"));
|
|
6463
|
+
console.log(import_chalk24.default.dim("sending claim_work_payment (or you self-claim after the review window)."));
|
|
6590
6464
|
}
|
|
6591
6465
|
async function assertSenderIsReceiptPayee(api, sender, relationshipId, delegationId) {
|
|
6592
6466
|
const signer = makeSigner(sender);
|
|
@@ -6654,7 +6528,7 @@ async function computeWorkLogHashes(api, sender, relationshipId, delegationId, r
|
|
|
6654
6528
|
`receipt propose --auto-hashes: no work-log row found for (relationshipId=${relationshipId}, delegationId=${delegationId}, requestId=${requestId}). Did the work_request envelope land yet?`
|
|
6655
6529
|
);
|
|
6656
6530
|
}
|
|
6657
|
-
if (workLog.state !==
|
|
6531
|
+
if (workLog.state !== import_sdk22.WorkLogStates.RESPONDED) {
|
|
6658
6532
|
throw new Error(
|
|
6659
6533
|
`receipt propose --auto-hashes: work-log row ${requestId} is in state '${workLog.state}', not 'responded'. The payee must \`work respond\` before a receipt can be proposed.`
|
|
6660
6534
|
);
|
|
@@ -6670,34 +6544,34 @@ async function computeWorkLogHashes(api, sender, relationshipId, delegationId, r
|
|
|
6670
6544
|
};
|
|
6671
6545
|
const responseBody = workLog.responseOutput !== void 0 ? { type: "work_response", content: { delegation_id: workLog.delegationId, request_id: workLog.requestId, output: workLog.responseOutput } } : { type: "work_response", content: { delegation_id: workLog.delegationId, request_id: workLog.requestId, error: workLog.responseError } };
|
|
6672
6546
|
return {
|
|
6673
|
-
requestHash: (0,
|
|
6674
|
-
responseHash: (0,
|
|
6547
|
+
requestHash: (0, import_sdk22.canonicalSha256Hex)(requestBody),
|
|
6548
|
+
responseHash: (0, import_sdk22.canonicalSha256Hex)(responseBody)
|
|
6675
6549
|
};
|
|
6676
6550
|
}
|
|
6677
6551
|
async function sendReceiptEnvelope(args) {
|
|
6678
6552
|
const nextSequence = (args.sender.lastSenderSequence ?? 0) + 1;
|
|
6679
6553
|
const protectedBlock = {
|
|
6680
|
-
protocol_version:
|
|
6681
|
-
purpose:
|
|
6682
|
-
message_id: (0,
|
|
6554
|
+
protocol_version: import_sdk22.CURRENT_PROTOCOL_VERSION,
|
|
6555
|
+
purpose: import_sdk22.Purpose.ENVELOPE,
|
|
6556
|
+
message_id: (0, import_sdk22.uuidV4)(),
|
|
6683
6557
|
sender_did: args.sender.did,
|
|
6684
6558
|
recipient_did: args.recipientDid,
|
|
6685
6559
|
relationship_id: null,
|
|
6686
6560
|
sender_sequence: nextSequence,
|
|
6687
|
-
sender_nonce: (0,
|
|
6688
|
-
timestamp: (0,
|
|
6689
|
-
expires_at: (0,
|
|
6561
|
+
sender_nonce: (0, import_sdk22.senderNonce)(),
|
|
6562
|
+
timestamp: (0, import_sdk22.rfc3339)(),
|
|
6563
|
+
expires_at: (0, import_sdk22.expiresAt)(args.ttlSeconds),
|
|
6690
6564
|
delivery_id: null
|
|
6691
6565
|
};
|
|
6692
6566
|
const signer = makeSigner(args.sender);
|
|
6693
|
-
const envelope = (0,
|
|
6567
|
+
const envelope = (0, import_sdk22.signEnvelope)({
|
|
6694
6568
|
protected: protectedBlock,
|
|
6695
6569
|
body: args.body,
|
|
6696
6570
|
identitySecretKey: signer.identitySecretKey,
|
|
6697
6571
|
attachments: args.attachments
|
|
6698
6572
|
});
|
|
6699
6573
|
if (args.verbose) {
|
|
6700
|
-
console.log(
|
|
6574
|
+
console.log(import_chalk24.default.bold("\nEnvelope (pre-send):"));
|
|
6701
6575
|
console.log(formatJson(envelope));
|
|
6702
6576
|
}
|
|
6703
6577
|
try {
|
|
@@ -6705,24 +6579,24 @@ async function sendReceiptEnvelope(args) {
|
|
|
6705
6579
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
6706
6580
|
return result;
|
|
6707
6581
|
} catch (err) {
|
|
6708
|
-
if (err instanceof ApiError && (0,
|
|
6582
|
+
if (err instanceof ApiError && (0, import_sdk22.isPostCommitErrorCode)(err.payload.code)) {
|
|
6709
6583
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
6710
6584
|
}
|
|
6711
6585
|
throw err;
|
|
6712
6586
|
}
|
|
6713
6587
|
}
|
|
6714
6588
|
function printIngestResult2(result) {
|
|
6715
|
-
console.log(
|
|
6716
|
-
console.log(`${
|
|
6717
|
-
console.log(`${
|
|
6718
|
-
console.log(`${
|
|
6719
|
-
console.log(`${
|
|
6720
|
-
console.log(`${
|
|
6589
|
+
console.log(import_chalk24.default.green("\nDelivered."));
|
|
6590
|
+
console.log(`${import_chalk24.default.bold("Event id")}: ${import_chalk24.default.cyan(result.eventId)}`);
|
|
6591
|
+
console.log(`${import_chalk24.default.bold("Relationship id")}: ${import_chalk24.default.cyan(result.relationshipId)}`);
|
|
6592
|
+
console.log(`${import_chalk24.default.bold("Chain index")}: ${import_chalk24.default.cyan(String(result.relationshipEventIndex))}`);
|
|
6593
|
+
console.log(`${import_chalk24.default.bold("Server timestamp")}: ${import_chalk24.default.cyan(result.serverTimestamp)}`);
|
|
6594
|
+
console.log(`${import_chalk24.default.bold("Server event hash")}: ${import_chalk24.default.cyan(result.serverEventHash)}`);
|
|
6721
6595
|
}
|
|
6722
6596
|
function parseVerdict(cmdName, raw) {
|
|
6723
|
-
if (raw === void 0 || raw === "") return
|
|
6724
|
-
if (!
|
|
6725
|
-
throw new Error(`${cmdName}: --verdict must be one of ${
|
|
6597
|
+
if (raw === void 0 || raw === "") return import_sdk22.ReceiptVerdicts.ACCEPTED;
|
|
6598
|
+
if (!import_sdk22.RECEIPT_VERDICTS.includes(raw)) {
|
|
6599
|
+
throw new Error(`${cmdName}: --verdict must be one of ${import_sdk22.RECEIPT_VERDICTS.join(" | ")} (got '${raw}')`);
|
|
6726
6600
|
}
|
|
6727
6601
|
return raw;
|
|
6728
6602
|
}
|
|
@@ -6759,24 +6633,19 @@ function requireUuid3(cmdName, raw, label) {
|
|
|
6759
6633
|
requireUuid(cmdName, raw, label);
|
|
6760
6634
|
}
|
|
6761
6635
|
function requireSha256(cmdName, raw, label) {
|
|
6762
|
-
if (!(0,
|
|
6636
|
+
if (!(0, import_sdk22.isSha256Hex)(raw)) {
|
|
6763
6637
|
throw new Error(`${cmdName}: ${label} must match 'sha256:<64 lowercase hex>' (got '${raw}')`);
|
|
6764
6638
|
}
|
|
6765
6639
|
}
|
|
6766
|
-
function requireDid2(cmdName, did, label) {
|
|
6767
|
-
if (typeof did !== "string" || !did.startsWith("did:arp:") || did.length <= "did:arp:".length) {
|
|
6768
|
-
throw new Error(`${cmdName}: ${label} must look like 'did:arp:...' (got '${did}')`);
|
|
6769
|
-
}
|
|
6770
|
-
}
|
|
6771
6640
|
|
|
6772
6641
|
// src/commands/receipts.ts
|
|
6773
|
-
var
|
|
6774
|
-
var
|
|
6642
|
+
var import_sdk23 = require("@heyanon-arp/sdk");
|
|
6643
|
+
var import_chalk25 = __toESM(require("chalk"));
|
|
6775
6644
|
init_api();
|
|
6776
6645
|
function registerReceiptsCommand(root) {
|
|
6777
6646
|
root.command("receipts").description(
|
|
6778
6647
|
"List receipts for a relationship (one row per (delegationId, requestHash, responseHash), oldest-first). Receipt rows expose the chain hash as `receiptEventHash` (NOT `serverEventHash` \u2014 that field is the wider envelope identifier on `heyarp events` rows). Scripts using `--json | jq .receiptEventHash` get the value; `jq .serverEventHash` silently returns null because the row doesn't carry that key."
|
|
6779
|
-
).argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--delegation-id <uuid>", "Narrow to receipts under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
|
|
6648
|
+
).argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--delegation-id <uuid>", "Narrow to receipts under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
6780
6649
|
"--verbose",
|
|
6781
6650
|
'After the one-line summaries, print a framed "Full receipt payloads (N rows)" block \u2014 each row labelled with full delegationId + requestHash + responseHash and dumped as JSON. Mutually exclusive with --json.',
|
|
6782
6651
|
false
|
|
@@ -6792,11 +6661,11 @@ async function runReceipts(relationshipId, opts) {
|
|
|
6792
6661
|
}
|
|
6793
6662
|
const limit = parseLimit5(opts.limit);
|
|
6794
6663
|
const api = new ArpApiClient(opts.server);
|
|
6795
|
-
const sender = resolveSenderAgent("receipts", opts.server, opts.fromDid);
|
|
6664
|
+
const sender = resolveSenderAgent("receipts", opts.server, opts.fromDid, opts.from);
|
|
6796
6665
|
if (!opts.json) {
|
|
6797
|
-
console.log(
|
|
6798
|
-
console.log(
|
|
6799
|
-
console.log(
|
|
6666
|
+
console.log(import_chalk25.default.dim(`Server: ${api.serverUrl}`));
|
|
6667
|
+
console.log(import_chalk25.default.dim(`Signer: ${sender.did}`));
|
|
6668
|
+
console.log(import_chalk25.default.dim(`Relationship: ${relationshipId}`));
|
|
6800
6669
|
}
|
|
6801
6670
|
const query = { limit };
|
|
6802
6671
|
if (opts.delegationId) query.delegationId = opts.delegationId;
|
|
@@ -6808,7 +6677,7 @@ async function runReceipts(relationshipId, opts) {
|
|
|
6808
6677
|
return;
|
|
6809
6678
|
}
|
|
6810
6679
|
if (rows.length === 0) {
|
|
6811
|
-
console.log(
|
|
6680
|
+
console.log(import_chalk25.default.dim("\n(no receipts for this relationship)"));
|
|
6812
6681
|
return;
|
|
6813
6682
|
}
|
|
6814
6683
|
console.log("");
|
|
@@ -6825,29 +6694,29 @@ async function runReceipts(relationshipId, opts) {
|
|
|
6825
6694
|
}));
|
|
6826
6695
|
}
|
|
6827
6696
|
const lastId = rows[rows.length - 1].id;
|
|
6828
|
-
console.log(
|
|
6697
|
+
console.log(import_chalk25.default.dim(`
|
|
6829
6698
|
${rows.length} receipt row(s). Paginate with --after ${lastId}.`));
|
|
6830
6699
|
}
|
|
6831
6700
|
function formatReceiptLine(r, selfDid, opts = {}) {
|
|
6832
6701
|
const delegationPart = opts.fullIds ? r.delegationId : idHead2(r.delegationId);
|
|
6833
6702
|
const requestHashPart = opts.fullIds ? r.requestHash : hashHead3(r.requestHash);
|
|
6834
|
-
const id =
|
|
6703
|
+
const id = import_chalk25.default.bold(`${delegationPart}/${requestHashPart}`);
|
|
6835
6704
|
const callerHead = opts.fullIds ? r.callerDid : didHead3(r.callerDid);
|
|
6836
6705
|
const payeeHead = opts.fullIds ? r.payeeDid : didHead3(r.payeeDid);
|
|
6837
|
-
const direction = r.payeeDid === selfDid ? `${
|
|
6706
|
+
const direction = r.payeeDid === selfDid ? `${import_chalk25.default.bold("me")}(payee) \u2192 ${import_chalk25.default.dim(callerHead)}` : `${import_chalk25.default.dim(payeeHead)}(payee) \u2192 ${import_chalk25.default.bold("me")}`;
|
|
6838
6707
|
const verdict = formatVerdict(r);
|
|
6839
6708
|
const responseTail = opts.fullIds ? `
|
|
6840
|
-
${
|
|
6709
|
+
${import_chalk25.default.dim("responseHash:")} ${import_chalk25.default.cyan(r.responseHash)}` : "";
|
|
6841
6710
|
return `${id} ${direction} ${verdict}${responseTail}`;
|
|
6842
6711
|
}
|
|
6843
6712
|
function formatVerdict(r) {
|
|
6844
6713
|
switch (r.verdictProposed) {
|
|
6845
|
-
case
|
|
6846
|
-
return
|
|
6847
|
-
case
|
|
6848
|
-
return
|
|
6849
|
-
case
|
|
6850
|
-
return
|
|
6714
|
+
case import_sdk23.ReceiptVerdicts.ACCEPTED:
|
|
6715
|
+
return import_chalk25.default.green("accepted");
|
|
6716
|
+
case import_sdk23.ReceiptVerdicts.ACCEPTED_WITH_NOTES:
|
|
6717
|
+
return import_chalk25.default.yellow("accepted_with_notes");
|
|
6718
|
+
case import_sdk23.ReceiptVerdicts.REJECTED:
|
|
6719
|
+
return import_chalk25.default.red("rejected");
|
|
6851
6720
|
}
|
|
6852
6721
|
}
|
|
6853
6722
|
function idHead2(id) {
|
|
@@ -6873,8 +6742,8 @@ function parseLimit5(raw) {
|
|
|
6873
6742
|
|
|
6874
6743
|
// src/commands/recover.ts
|
|
6875
6744
|
var import_node_fs8 = require("fs");
|
|
6876
|
-
var
|
|
6877
|
-
var
|
|
6745
|
+
var import_sdk24 = require("@heyanon-arp/sdk");
|
|
6746
|
+
var import_chalk26 = __toESM(require("chalk"));
|
|
6878
6747
|
init_api();
|
|
6879
6748
|
function registerRecoverCommand(root) {
|
|
6880
6749
|
root.command("recover").description(
|
|
@@ -6894,23 +6763,23 @@ async function runRecover(opts) {
|
|
|
6894
6763
|
}
|
|
6895
6764
|
const bundle = validateKeyBundle(raw);
|
|
6896
6765
|
const identitySecret = new Uint8Array(Buffer.from(bundle.identitySecretKeyB64, "base64"));
|
|
6897
|
-
const identityPub = (0,
|
|
6898
|
-
const derivedDid = (0,
|
|
6766
|
+
const identityPub = (0, import_sdk24.base58btcDecode)(bundle.identityPublicKeyB58);
|
|
6767
|
+
const derivedDid = (0, import_sdk24.formatDid)(identityPub);
|
|
6899
6768
|
if (derivedDid !== bundle.did) {
|
|
6900
6769
|
throw new Error(`recover: key file is inconsistent \u2014 its DID (${bundle.did}) does not match its identity public key (${derivedDid})`);
|
|
6901
6770
|
}
|
|
6902
6771
|
const probe2 = new TextEncoder().encode("heyarp-recover-keycheck");
|
|
6903
|
-
if (!(0,
|
|
6772
|
+
if (!(0, import_sdk24.verify)((0, import_sdk24.sign)(probe2, identitySecret), probe2, identityPub)) {
|
|
6904
6773
|
throw new Error("recover: the identity secret key does not match the public key in this bundle");
|
|
6905
6774
|
}
|
|
6906
6775
|
const settlementSecret = new Uint8Array(Buffer.from(bundle.settlementSecretKeyB64, "base64"));
|
|
6907
|
-
const settlementPub = (0,
|
|
6908
|
-
if (!(0,
|
|
6776
|
+
const settlementPub = (0, import_sdk24.base58btcDecode)(bundle.settlementPublicKeyB58);
|
|
6777
|
+
if (!(0, import_sdk24.verify)((0, import_sdk24.sign)(probe2, settlementSecret), probe2, settlementPub)) {
|
|
6909
6778
|
throw new Error("recover: the settlement secret key does not match the settlement public key in this bundle");
|
|
6910
6779
|
}
|
|
6911
6780
|
if (bundle.ownerWallet && bundle.ownerWallet !== credential.wallet) {
|
|
6912
6781
|
process.stderr.write(
|
|
6913
|
-
|
|
6782
|
+
import_chalk26.default.yellow(
|
|
6914
6783
|
`\u26A0 this bundle was exported under wallet ${bundle.ownerWallet}, but you are logged in as ${credential.wallet}. The server will reject the recover unless the agent is yours.
|
|
6915
6784
|
`
|
|
6916
6785
|
)
|
|
@@ -6927,7 +6796,7 @@ async function runRecover(opts) {
|
|
|
6927
6796
|
lastSenderSequence = seq.lastSenderSequence;
|
|
6928
6797
|
} catch (err) {
|
|
6929
6798
|
process.stderr.write(
|
|
6930
|
-
|
|
6799
|
+
import_chalk26.default.yellow(
|
|
6931
6800
|
`\u26A0 could not read the sender sequence from the server (${err.message}). If sends are rejected as backwards, run \`heyarp escrow recover-sequence --apply\`.
|
|
6932
6801
|
`
|
|
6933
6802
|
)
|
|
@@ -6955,14 +6824,14 @@ async function runRecover(opts) {
|
|
|
6955
6824
|
jsonOut({ recovered: true, did: derivedDid, name: row.name });
|
|
6956
6825
|
return;
|
|
6957
6826
|
}
|
|
6958
|
-
console.log(
|
|
6827
|
+
console.log(import_chalk26.default.green(`\u2713 Recovered ${row.name ? `${row.name} ` : ""}${derivedDid} into local state \u2014 you can operate it now.`));
|
|
6959
6828
|
}
|
|
6960
6829
|
|
|
6961
6830
|
// src/commands/register.ts
|
|
6962
6831
|
var import_node_crypto4 = require("crypto");
|
|
6963
6832
|
var import_node_fs9 = require("fs");
|
|
6964
|
-
var
|
|
6965
|
-
var
|
|
6833
|
+
var import_sdk25 = require("@heyanon-arp/sdk");
|
|
6834
|
+
var import_chalk27 = __toESM(require("chalk"));
|
|
6966
6835
|
var import_prompts2 = __toESM(require("prompts"));
|
|
6967
6836
|
init_api();
|
|
6968
6837
|
init_paths();
|
|
@@ -6974,7 +6843,7 @@ function registerRegisterCommand(root) {
|
|
|
6974
6843
|
"`--password` is REQUIRED \u2014 must be at least 8 characters. In interactive mode (--yes omitted) the CLI prompts for it; with --yes it must be passed explicitly.",
|
|
6975
6844
|
"`--yes` is the non-interactive switch \u2014 every required field must arrive via flags (no prompts). Use this for scripted setups."
|
|
6976
6845
|
].join("\n")
|
|
6977
|
-
).option("--server <url>", "Override ARP server base URL").option("--from-keys <file>", "Load identity + settlement keys from a JSON file instead of generating").option("--name <s>", "
|
|
6846
|
+
).option("--server <url>", "Override ARP server base URL").option("--from-keys <file>", "Load identity + settlement keys from a JSON file instead of generating").option("--name <s>", "Unique handle \u2014 lowercase a-z0-9_, 3-32 chars, immutable (skips the name prompt)").option("--description <s>", "Description (skips the description prompt)").option("--tag <s>", "Capability tag \u2014 repeatable, e.g. --tag translation --tag fr", accumulate3, []).option(
|
|
6978
6847
|
"--password <s>",
|
|
6979
6848
|
// `--password` puts the secret in `argv` — visible via
|
|
6980
6849
|
// `ps aux` / kernel process table on shared hosts,
|
|
@@ -7016,44 +6885,44 @@ var defaultRegisterDeps = {
|
|
|
7016
6885
|
async function runRegister(opts, deps = defaultRegisterDeps) {
|
|
7017
6886
|
assertJsonRequiresYes(opts);
|
|
7018
6887
|
const api = deps.makeApi(opts.server);
|
|
7019
|
-
if (!opts.json) console.log(
|
|
6888
|
+
if (!opts.json) console.log(import_chalk27.default.dim(`Server: ${api.serverUrl}`));
|
|
7020
6889
|
const credential = requireCredential("register", api.serverUrl);
|
|
7021
6890
|
if (!opts.json) {
|
|
7022
6891
|
warnIfAgentsAlreadyRegistered(opts.server);
|
|
7023
6892
|
warnIfOrphanHomesPresent();
|
|
7024
6893
|
}
|
|
7025
6894
|
const keys = opts.fromKeys ? loadKeysFromFile(opts.fromKeys) : freshKeys();
|
|
7026
|
-
const did = (0,
|
|
7027
|
-
if (!opts.json) console.log(
|
|
6895
|
+
const did = (0, import_sdk25.formatDid)(keys.identityPublicKey);
|
|
6896
|
+
if (!opts.json) console.log(import_chalk27.default.dim(`DID will be: ${did}`));
|
|
7028
6897
|
const answers = await mergeAnswers(opts);
|
|
7029
6898
|
const scryptSalt = (0, import_node_crypto4.randomBytes)(16);
|
|
7030
|
-
if (!opts.json) console.log(
|
|
7031
|
-
const scryptKey = (0,
|
|
6899
|
+
if (!opts.json) console.log(import_chalk27.default.dim("Deriving scrypt key, this may take a moment..."));
|
|
6900
|
+
const scryptKey = (0, import_sdk25.deriveScryptKey)(answers.password, new Uint8Array(scryptSalt));
|
|
7032
6901
|
const challenge = await api.issueChallenge("register");
|
|
7033
6902
|
const challengeBytes = base64UrlNoPadDecode(challenge.challengeB64);
|
|
7034
6903
|
if (challengeBytes.length !== 32) {
|
|
7035
6904
|
throw new Error(`Server returned a ${challengeBytes.length}-byte challenge; expected 32`);
|
|
7036
6905
|
}
|
|
7037
|
-
const challengeSig = (0,
|
|
7038
|
-
const identityPublicKeyB58 = (0,
|
|
6906
|
+
const challengeSig = (0, import_sdk25.signChallenge)(challengeBytes, keys.identitySecretKey);
|
|
6907
|
+
const identityPublicKeyB58 = (0, import_sdk25.base58btcEncode)(keys.identityPublicKey);
|
|
7039
6908
|
await api.submitChallengeResponse({
|
|
7040
6909
|
challengeId: challenge.challengeId,
|
|
7041
6910
|
identityPublicKey: identityPublicKeyB58,
|
|
7042
6911
|
signature: Buffer.from(challengeSig).toString("base64")
|
|
7043
6912
|
});
|
|
7044
|
-
const settlementPublicKeyB58 = (0,
|
|
7045
|
-
const scryptSaltId = (0,
|
|
6913
|
+
const settlementPublicKeyB58 = (0, import_sdk25.base58btcEncode)(keys.settlementPublicKey);
|
|
6914
|
+
const scryptSaltId = (0, import_sdk25.uuidV4)();
|
|
7046
6915
|
const payload = {
|
|
7047
|
-
purpose:
|
|
6916
|
+
purpose: import_sdk25.Purpose.KEY_LINK,
|
|
7048
6917
|
agent_did: did,
|
|
7049
6918
|
identity_public_key: identityPublicKeyB58,
|
|
7050
6919
|
settlement_public_key: settlementPublicKeyB58,
|
|
7051
|
-
owner_signing_method:
|
|
6920
|
+
owner_signing_method: import_sdk25.OWNER_SIGNING_METHODS[0],
|
|
7052
6921
|
link_method: "manual",
|
|
7053
|
-
created_at: (0,
|
|
7054
|
-
nonce: (0,
|
|
6922
|
+
created_at: (0, import_sdk25.rfc3339)(),
|
|
6923
|
+
nonce: (0, import_sdk25.senderNonce)()
|
|
7055
6924
|
};
|
|
7056
|
-
const attestation = (0,
|
|
6925
|
+
const attestation = (0, import_sdk25.signKeyLinkAttestation)({ payload, scryptKey, scryptSaltId });
|
|
7057
6926
|
const body = {
|
|
7058
6927
|
challengeId: challenge.challengeId,
|
|
7059
6928
|
identityPublicKey: identityPublicKeyB58,
|
|
@@ -7096,7 +6965,7 @@ async function runRegister(opts, deps = defaultRegisterDeps) {
|
|
|
7096
6965
|
try {
|
|
7097
6966
|
result = await api.register(body, credential.token);
|
|
7098
6967
|
} catch (err) {
|
|
7099
|
-
if (err instanceof ApiError && (err.payload.code ===
|
|
6968
|
+
if (err instanceof ApiError && (err.payload.code === import_sdk25.CliAuthTokenErrorCodes.INVALID || err.payload.code === import_sdk25.CliAuthTokenErrorCodes.REQUIRED)) {
|
|
7100
6969
|
throw new Error(
|
|
7101
6970
|
`register: the stored login token for ${api.serverUrl} was rejected (${err.payload.message}) \u2014 run 'heyarp login' again. Your keys are saved locally; re-running register with --from-keys is safe.`
|
|
7102
6971
|
);
|
|
@@ -7115,19 +6984,19 @@ async function runRegister(opts, deps = defaultRegisterDeps) {
|
|
|
7115
6984
|
try {
|
|
7116
6985
|
recordHome(arpHomeDir());
|
|
7117
6986
|
} catch (registryErr) {
|
|
7118
|
-
if (!opts.json) console.log(
|
|
6987
|
+
if (!opts.json) console.log(import_chalk27.default.dim(`(homes registry write failed: ${registryErr.message})`));
|
|
7119
6988
|
}
|
|
7120
6989
|
if (!opts.json) {
|
|
7121
|
-
console.log(
|
|
7122
|
-
console.log(`${
|
|
7123
|
-
console.log(`${
|
|
7124
|
-
console.log(`${
|
|
7125
|
-
console.log(
|
|
6990
|
+
console.log(import_chalk27.default.green("\nRegistered."));
|
|
6991
|
+
console.log(`${import_chalk27.default.bold("DID")}: ${import_chalk27.default.cyan(result.did)}`);
|
|
6992
|
+
console.log(`${import_chalk27.default.bold("Settlement pubkey")} ${import_chalk27.default.dim("(fund with SOL)")}: ${import_chalk27.default.cyan(settlementPublicKeyB58)}`);
|
|
6993
|
+
console.log(`${import_chalk27.default.bold("Owner account")}: ${import_chalk27.default.cyan(credential.wallet)}`);
|
|
6994
|
+
console.log(import_chalk27.default.bold("DID document:"));
|
|
7126
6995
|
console.log(formatJson(result.didDocument));
|
|
7127
6996
|
}
|
|
7128
|
-
if (!opts.json) console.log(
|
|
6997
|
+
if (!opts.json) console.log(import_chalk27.default.green(`
|
|
7129
6998
|
\u2713 Discoverable now via \`heyarp agents\`.`));
|
|
7130
|
-
if (!opts.json) console.log(
|
|
6999
|
+
if (!opts.json) console.log(import_chalk27.default.dim(`
|
|
7131
7000
|
Local state saved to ${arpHomeDir()}/agents.json (mode 0600).`));
|
|
7132
7001
|
if (opts.json) {
|
|
7133
7002
|
console.log(
|
|
@@ -7178,8 +7047,13 @@ async function mergeAnswers(opts) {
|
|
|
7178
7047
|
promptDefs.push({
|
|
7179
7048
|
type: "text",
|
|
7180
7049
|
name: "name",
|
|
7181
|
-
message: "Agent name (
|
|
7182
|
-
validate: (v) =>
|
|
7050
|
+
message: "Agent name \u2014 unique handle (lowercase a-z0-9_, 3-32 chars, immutable; addressable instead of the DID)",
|
|
7051
|
+
validate: (v) => {
|
|
7052
|
+
const n = (0, import_sdk25.normalizeName)(v);
|
|
7053
|
+
if (!(0, import_sdk25.isValidAgentName)(n)) return "must be lowercase a-z0-9_, 3-32 chars";
|
|
7054
|
+
if ((0, import_sdk25.isReservedName)(n)) return `'${n}' is reserved`;
|
|
7055
|
+
return true;
|
|
7056
|
+
}
|
|
7183
7057
|
});
|
|
7184
7058
|
}
|
|
7185
7059
|
if (need.description) {
|
|
@@ -7195,18 +7069,29 @@ async function mergeAnswers(opts) {
|
|
|
7195
7069
|
}
|
|
7196
7070
|
const prompted = promptDefs.length > 0 ? await (0, import_prompts2.default)(promptDefs, {
|
|
7197
7071
|
onCancel: () => {
|
|
7198
|
-
console.log(
|
|
7072
|
+
console.log(import_chalk27.default.yellow("\nAborted."));
|
|
7199
7073
|
process.exit(130);
|
|
7200
7074
|
}
|
|
7201
7075
|
}) : {};
|
|
7202
7076
|
const tags = (opts.tag && opts.tag.length > 0 ? opts.tag : parseTagsCsv(typeof prompted.tagsCsv === "string" ? prompted.tagsCsv : "")).map((t) => t.trim().toLowerCase()).filter((t) => t.length > 0);
|
|
7077
|
+
const name = normalizeAndValidateName(opts.name ?? prompted.name);
|
|
7203
7078
|
return {
|
|
7204
7079
|
password: opts.password ?? prompted.password,
|
|
7205
|
-
name
|
|
7080
|
+
name,
|
|
7206
7081
|
description: opts.description ?? prompted.description ?? "",
|
|
7207
7082
|
tags
|
|
7208
7083
|
};
|
|
7209
7084
|
}
|
|
7085
|
+
function normalizeAndValidateName(raw) {
|
|
7086
|
+
const name = (0, import_sdk25.normalizeName)(raw);
|
|
7087
|
+
if (!(0, import_sdk25.isValidAgentName)(name)) {
|
|
7088
|
+
throw new Error(`register: name '${raw}' must be a lowercase handle \u2014 a-z0-9_, 3-32 chars`);
|
|
7089
|
+
}
|
|
7090
|
+
if ((0, import_sdk25.isReservedName)(name)) {
|
|
7091
|
+
throw new Error(`register: name '${name}' is reserved and cannot be registered`);
|
|
7092
|
+
}
|
|
7093
|
+
return name;
|
|
7094
|
+
}
|
|
7210
7095
|
function warnIfOrphanHomesPresent() {
|
|
7211
7096
|
if (process.env.HEYARP_HOME && process.env.HEYARP_HOME.length > 0) {
|
|
7212
7097
|
return;
|
|
@@ -7216,16 +7101,16 @@ function warnIfOrphanHomesPresent() {
|
|
|
7216
7101
|
try {
|
|
7217
7102
|
others = listHomes().filter((h) => h.path !== current);
|
|
7218
7103
|
} catch (registryErr) {
|
|
7219
|
-
console.log(
|
|
7104
|
+
console.log(import_chalk27.default.dim(`(homes registry unreadable, skipping orphan-home check: ${registryErr.message})`));
|
|
7220
7105
|
return;
|
|
7221
7106
|
}
|
|
7222
7107
|
if (others.length === 0) return;
|
|
7223
|
-
const list = others.map((h) => ` \u2022 ${
|
|
7224
|
-
console.log(
|
|
7108
|
+
const list = others.map((h) => ` \u2022 ${import_chalk27.default.cyan(h.path)} ${import_chalk27.default.dim(`(last seen ${h.lastSeenAt})`)}`).join("\n");
|
|
7109
|
+
console.log(import_chalk27.default.yellow(`
|
|
7225
7110
|
\u26A0 HEYARP_HOME is unset, but other agent homes are registered on this machine:`));
|
|
7226
7111
|
console.log(list);
|
|
7227
7112
|
console.log(
|
|
7228
|
-
|
|
7113
|
+
import_chalk27.default.dim(
|
|
7229
7114
|
` Registering will create a NEW agent under ${current}.
|
|
7230
7115
|
If you meant to add to an existing home, abort (Ctrl-C) and re-run with:
|
|
7231
7116
|
HEYARP_HOME=<path> heyarp register \u2026
|
|
@@ -7238,11 +7123,11 @@ function warnIfAgentsAlreadyRegistered(serverOverride) {
|
|
|
7238
7123
|
const targetServer = resolveServerUrl(serverOverride);
|
|
7239
7124
|
const existing = listAgents().filter((row) => row.serverUrl === targetServer);
|
|
7240
7125
|
if (existing.length === 0) return;
|
|
7241
|
-
const list = existing.map((row) => ` \u2022 ${
|
|
7242
|
-
console.log(
|
|
7126
|
+
const list = existing.map((row) => ` \u2022 ${import_chalk27.default.cyan(row.agent.did)}${row.agent.name ? import_chalk27.default.dim(` (${row.agent.name})`) : ""}`).join("\n");
|
|
7127
|
+
console.log(import_chalk27.default.yellow("\n\u26A0 ~/.heyarp/agents.json already has agent(s) for this server:"));
|
|
7243
7128
|
console.log(list);
|
|
7244
7129
|
console.log(
|
|
7245
|
-
|
|
7130
|
+
import_chalk27.default.dim(
|
|
7246
7131
|
" After this register completes, you will have multiple local DIDs sharing one state file.\n To keep their state isolated, run with HEYARP_HOME pointing at a per-agent dir, e.g.\n HEYARP_HOME=/tmp/agent-alice heyarp register \u2026\n Otherwise, pass --from-did <did> explicitly on every signed command.\n"
|
|
7247
7132
|
)
|
|
7248
7133
|
);
|
|
@@ -7252,8 +7137,8 @@ function parseTagsCsv(raw) {
|
|
|
7252
7137
|
return raw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
7253
7138
|
}
|
|
7254
7139
|
function freshKeys() {
|
|
7255
|
-
const identity = (0,
|
|
7256
|
-
const settlement = (0,
|
|
7140
|
+
const identity = (0, import_sdk25.generateKeyPair)();
|
|
7141
|
+
const settlement = (0, import_sdk25.generateKeyPair)();
|
|
7257
7142
|
return {
|
|
7258
7143
|
identityPublicKey: identity.publicKey,
|
|
7259
7144
|
identitySecretKey: identity.secretKey,
|
|
@@ -7279,9 +7164,9 @@ function loadKeysFromFile(path) {
|
|
|
7279
7164
|
if (identitySecret.length !== 32) throw new Error("--from-keys: identitySecretKeyB64 is not a 32-byte Ed25519 seed");
|
|
7280
7165
|
if (settlementSecret.length !== 32) throw new Error("--from-keys: settlementSecretKeyB64 is not a 32-byte Ed25519 seed");
|
|
7281
7166
|
return {
|
|
7282
|
-
identityPublicKey: (0,
|
|
7167
|
+
identityPublicKey: (0, import_sdk25.getPublicKey)(identitySecret),
|
|
7283
7168
|
identitySecretKey: identitySecret,
|
|
7284
|
-
settlementPublicKey: (0,
|
|
7169
|
+
settlementPublicKey: (0, import_sdk25.getPublicKey)(settlementSecret),
|
|
7285
7170
|
settlementSecretKey: settlementSecret
|
|
7286
7171
|
};
|
|
7287
7172
|
}
|
|
@@ -7297,10 +7182,10 @@ function assertJsonRequiresYes(opts) {
|
|
|
7297
7182
|
}
|
|
7298
7183
|
|
|
7299
7184
|
// src/commands/relationships.ts
|
|
7300
|
-
var
|
|
7301
|
-
var
|
|
7185
|
+
var import_sdk26 = require("@heyanon-arp/sdk");
|
|
7186
|
+
var import_chalk28 = __toESM(require("chalk"));
|
|
7302
7187
|
init_api();
|
|
7303
|
-
var ALLOWED_STATES2 = new Set(
|
|
7188
|
+
var ALLOWED_STATES2 = new Set(import_sdk26.RELATIONSHIP_STATE_NAMES);
|
|
7304
7189
|
function registerRelationshipsCommand(root) {
|
|
7305
7190
|
root.command("relationships").description(
|
|
7306
7191
|
"List relationships <did> belongs to (live + closed pairs, ordered by lastEventAt desc). DID can be passed positionally OR via --from-did; if both are omitted the resolver picks the sole local agent for the server (see `heyarp config set server` + multi-DID disambiguation rules)."
|
|
@@ -7308,7 +7193,7 @@ function registerRelationshipsCommand(root) {
|
|
|
7308
7193
|
"--json",
|
|
7309
7194
|
"Machine-readable mode \u2014 emit the relationships as a single JSON array on stdout (RelationshipPublic[]). Prelude + table move to stderr. Mutually exclusive with --verbose.",
|
|
7310
7195
|
false
|
|
7311
|
-
).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").action(async (did, opts) => {
|
|
7196
|
+
).option("--from-did <did>", "Alias for the positional <did> argument \u2014 accepted for consistency with other signed commands. Must match the positional if both are given.").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").action(async (did, opts) => {
|
|
7312
7197
|
await runRelationships(did, opts);
|
|
7313
7198
|
});
|
|
7314
7199
|
}
|
|
@@ -7324,11 +7209,11 @@ async function runRelationships(positionalDid, opts) {
|
|
|
7324
7209
|
throw new Error(`relationships: positional <did> (${positionalDid}) and --from-did (${opts.fromDid}) disagree \u2014 pass only one`);
|
|
7325
7210
|
}
|
|
7326
7211
|
const explicitDid = positionalDid ?? opts.fromDid;
|
|
7327
|
-
const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("relationships", opts.server, void 0);
|
|
7212
|
+
const local = explicitDid !== void 0 ? loadAgentOrThrow(opts.server, explicitDid) : resolveSenderAgent("relationships", opts.server, void 0, opts.from);
|
|
7328
7213
|
const did = local.did;
|
|
7329
7214
|
const api = new ArpApiClient(opts.server);
|
|
7330
|
-
progress(opts.json,
|
|
7331
|
-
progress(opts.json,
|
|
7215
|
+
progress(opts.json, import_chalk28.default.dim(`Server: ${api.serverUrl}`));
|
|
7216
|
+
progress(opts.json, import_chalk28.default.dim(`Signer: ${local.did}`));
|
|
7332
7217
|
const query = { limit };
|
|
7333
7218
|
if (state) query.state = state;
|
|
7334
7219
|
const signer = makeSigner(local);
|
|
@@ -7338,18 +7223,18 @@ async function runRelationships(positionalDid, opts) {
|
|
|
7338
7223
|
return;
|
|
7339
7224
|
}
|
|
7340
7225
|
if (rows.length === 0) {
|
|
7341
|
-
console.log(
|
|
7226
|
+
console.log(import_chalk28.default.dim("\n(no relationships)"));
|
|
7342
7227
|
return;
|
|
7343
7228
|
}
|
|
7344
7229
|
console.log("");
|
|
7345
7230
|
console.log(formatRelationshipsTable(rows, did));
|
|
7346
7231
|
if (opts.verbose) {
|
|
7347
|
-
console.log(
|
|
7232
|
+
console.log(import_chalk28.default.bold("\nFull relationships:"));
|
|
7348
7233
|
for (const r of rows) {
|
|
7349
7234
|
console.log(formatJson(r));
|
|
7350
7235
|
}
|
|
7351
7236
|
}
|
|
7352
|
-
console.log(
|
|
7237
|
+
console.log(import_chalk28.default.dim(`
|
|
7353
7238
|
${rows.length} relationship(s).`));
|
|
7354
7239
|
}
|
|
7355
7240
|
function formatRelationshipsTable(rows, selfDid) {
|
|
@@ -7357,7 +7242,7 @@ function formatRelationshipsTable(rows, selfDid) {
|
|
|
7357
7242
|
const data = rows.map((r) => [r.relationshipId, otherPair(r, selfDid), r.state, r.lastEventAt ?? "(none)", String(r.lastEventIndex)]);
|
|
7358
7243
|
const widths = header.map((h, i) => Math.max(h.length, ...data.map((row) => row[i].length)));
|
|
7359
7244
|
const pad = (cells) => cells.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
7360
|
-
return [
|
|
7245
|
+
return [import_chalk28.default.bold(pad(header)), import_chalk28.default.dim(pad(widths.map((w) => "-".repeat(w)))), ...data.map((row) => pad(row))].join("\n");
|
|
7361
7246
|
}
|
|
7362
7247
|
function otherPair(r, selfDid) {
|
|
7363
7248
|
if (r.pairDidA === selfDid) return r.pairDidB;
|
|
@@ -7381,12 +7266,12 @@ function parseLimit6(raw) {
|
|
|
7381
7266
|
}
|
|
7382
7267
|
|
|
7383
7268
|
// src/commands/reputation.ts
|
|
7384
|
-
var
|
|
7385
|
-
var
|
|
7269
|
+
var import_sdk27 = require("@heyanon-arp/sdk");
|
|
7270
|
+
var import_chalk29 = __toESM(require("chalk"));
|
|
7386
7271
|
init_api();
|
|
7387
7272
|
function registerReputationCommand(root) {
|
|
7388
7273
|
root.command("reputation").description("Show an agent's informational reputation (composite + component scores + raw counters). Public, no auth. NOT a money/eligibility gate.").argument("<did>", "did:arp:<base58btc> identifier").option("--server <url>", "Override ARP server base URL").option("--json", "Emit the reputation as JSON on stdout.", false).action(async (did, opts) => {
|
|
7389
|
-
if (!(0,
|
|
7274
|
+
if (!(0, import_sdk27.isValidDid)(did)) {
|
|
7390
7275
|
throw new Error(`'${did}' is not a syntactically valid did:arp identifier`);
|
|
7391
7276
|
}
|
|
7392
7277
|
const api = new ArpApiClient(opts.server);
|
|
@@ -7398,10 +7283,10 @@ function registerReputationCommand(root) {
|
|
|
7398
7283
|
const s = rep.scores;
|
|
7399
7284
|
const c = rep.counters;
|
|
7400
7285
|
const j = false;
|
|
7401
|
-
progress(j,
|
|
7286
|
+
progress(j, import_chalk29.default.bold(`Reputation \u2014 ${did}`));
|
|
7402
7287
|
progress(
|
|
7403
7288
|
j,
|
|
7404
|
-
|
|
7289
|
+
import_chalk29.default.dim(` ${rep.informational ? "INFORMATIONAL" : "GATING"} \xB7 ${rep.computed ? `computed ${rep.lastComputedAt}` : "never computed (neutral cold-start)"}`)
|
|
7405
7290
|
);
|
|
7406
7291
|
progress(j, "");
|
|
7407
7292
|
progress(j, ` composite ${bar(s.composite)} ${s.composite.toFixed(2)}`);
|
|
@@ -7409,17 +7294,17 @@ function registerReputationCommand(root) {
|
|
|
7409
7294
|
progress(j, ` settlement ${bar(s.settlement)} ${s.settlement.toFixed(2)}`);
|
|
7410
7295
|
progress(j, ` dispute health ${bar(s.disputeHealth)} ${s.disputeHealth.toFixed(2)}`);
|
|
7411
7296
|
progress(j, "");
|
|
7412
|
-
progress(j,
|
|
7297
|
+
progress(j, import_chalk29.default.dim(" evidence:"));
|
|
7413
7298
|
progress(
|
|
7414
7299
|
j,
|
|
7415
|
-
|
|
7300
|
+
import_chalk29.default.dim(
|
|
7416
7301
|
` on-chain cycles ${c.onchainCycles} \xB7 completed ${c.completedDelegations} (payer ${c.completedAsPayer} / payee ${c.completedAsPayee}) \xB7 failed ${c.failedDelegations}`
|
|
7417
7302
|
)
|
|
7418
7303
|
);
|
|
7419
|
-
progress(j,
|
|
7420
|
-
progress(j,
|
|
7304
|
+
progress(j, import_chalk29.default.dim(` escrows settled ${c.settledEscrows} / refunded ${c.refundedEscrows} \xB7 disputed ${c.disputedEscrows} (adverse ${c.disputesAdverse})`));
|
|
7305
|
+
progress(j, import_chalk29.default.dim(` distinct counterparts ${c.distinctCounterparts} \xB7 active relationships ${c.activeRelationships}`));
|
|
7421
7306
|
progress(j, "");
|
|
7422
|
-
progress(j,
|
|
7307
|
+
progress(j, import_chalk29.default.dim(" Informational only \u2014 a discovery-sort signal, not a money or eligibility gate."));
|
|
7423
7308
|
});
|
|
7424
7309
|
}
|
|
7425
7310
|
function bar(score) {
|
|
@@ -7428,11 +7313,11 @@ function bar(score) {
|
|
|
7428
7313
|
}
|
|
7429
7314
|
|
|
7430
7315
|
// src/commands/send-handshake.ts
|
|
7431
|
-
var
|
|
7432
|
-
var
|
|
7316
|
+
var import_sdk28 = require("@heyanon-arp/sdk");
|
|
7317
|
+
var import_chalk30 = __toESM(require("chalk"));
|
|
7433
7318
|
init_api();
|
|
7434
7319
|
function registerSendHandshakeCommand(root) {
|
|
7435
|
-
root.command("send-handshake").description("Send a handshake envelope to
|
|
7320
|
+
root.command("send-handshake").description("Send a handshake envelope to a recipient (agent name or DID). Server creates the relationship row on first contact.").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--greeting <s>", "Optional greeting text included in body.content").option("--intent <s>", "Optional intent text included in body.content").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk28.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
7436
7321
|
"--json",
|
|
7437
7322
|
"Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, eventId, relationshipId, relationshipEventIndex, serverTimestamp, signedMessageHash, serverEventHash, prevServerEventHash, senderSequence}). The Server/Sender/Recipient prelude moves to stderr so `--json | jq` stays byte-pure. Mutually exclusive with --verbose.",
|
|
7438
7323
|
false
|
|
@@ -7441,46 +7326,44 @@ function registerSendHandshakeCommand(root) {
|
|
|
7441
7326
|
});
|
|
7442
7327
|
}
|
|
7443
7328
|
async function runSendHandshake(recipientDid, opts) {
|
|
7444
|
-
if (!(0, import_sdk25.isValidDid)(recipientDid)) {
|
|
7445
|
-
throw new Error(`send-handshake: <recipient-did> must be a valid did:arp identifier (base58btc-encoded 32-byte Ed25519 pubkey) (got '${recipientDid}')`);
|
|
7446
|
-
}
|
|
7447
7329
|
if (opts.verbose && opts.json) {
|
|
7448
7330
|
throw new Error(
|
|
7449
7331
|
"send-handshake: --verbose and --json are mutually exclusive. --json emits the structured server response; --verbose adds envelope + response dumps that would break `--json | jq`."
|
|
7450
7332
|
);
|
|
7451
7333
|
}
|
|
7334
|
+
recipientDid = await resolveRecipient(opts.server, "send-handshake", recipientDid, { json: opts.json });
|
|
7452
7335
|
const ttlSeconds = parseTtl3(opts.ttl);
|
|
7453
7336
|
const api = new ArpApiClient(opts.server);
|
|
7454
|
-
progress(opts.json,
|
|
7455
|
-
const sender = resolveSenderAgent("send-handshake", opts.server, opts.fromDid);
|
|
7456
|
-
progress(opts.json,
|
|
7457
|
-
progress(opts.json,
|
|
7337
|
+
progress(opts.json, import_chalk30.default.dim(`Server: ${api.serverUrl}`));
|
|
7338
|
+
const sender = resolveSenderAgent("send-handshake", opts.server, opts.fromDid, opts.from);
|
|
7339
|
+
progress(opts.json, import_chalk30.default.dim(`Sender: ${sender.did}`));
|
|
7340
|
+
progress(opts.json, import_chalk30.default.dim(`Recipient: ${recipientDid}`));
|
|
7458
7341
|
const content = {};
|
|
7459
7342
|
if (opts.greeting) content.greeting = opts.greeting;
|
|
7460
7343
|
if (opts.intent) content.intent = opts.intent;
|
|
7461
7344
|
const body = { type: "handshake", content };
|
|
7462
7345
|
const nextSequence = (sender.lastSenderSequence ?? 0) + 1;
|
|
7463
7346
|
const protectedBlock = {
|
|
7464
|
-
protocol_version:
|
|
7465
|
-
purpose:
|
|
7466
|
-
message_id: (0,
|
|
7347
|
+
protocol_version: import_sdk28.CURRENT_PROTOCOL_VERSION,
|
|
7348
|
+
purpose: import_sdk28.Purpose.ENVELOPE,
|
|
7349
|
+
message_id: (0, import_sdk28.uuidV4)(),
|
|
7467
7350
|
sender_did: sender.did,
|
|
7468
7351
|
recipient_did: recipientDid,
|
|
7469
7352
|
relationship_id: null,
|
|
7470
7353
|
sender_sequence: nextSequence,
|
|
7471
|
-
sender_nonce: (0,
|
|
7472
|
-
timestamp: (0,
|
|
7473
|
-
expires_at: (0,
|
|
7354
|
+
sender_nonce: (0, import_sdk28.senderNonce)(),
|
|
7355
|
+
timestamp: (0, import_sdk28.rfc3339)(),
|
|
7356
|
+
expires_at: (0, import_sdk28.expiresAt)(ttlSeconds),
|
|
7474
7357
|
delivery_id: null
|
|
7475
7358
|
};
|
|
7476
7359
|
const signer = makeSigner(sender);
|
|
7477
|
-
const envelope = (0,
|
|
7360
|
+
const envelope = (0, import_sdk28.signEnvelope)({
|
|
7478
7361
|
protected: protectedBlock,
|
|
7479
7362
|
body,
|
|
7480
7363
|
identitySecretKey: signer.identitySecretKey
|
|
7481
7364
|
});
|
|
7482
7365
|
if (opts.verbose) {
|
|
7483
|
-
console.log(
|
|
7366
|
+
console.log(import_chalk30.default.bold("\nEnvelope (pre-send):"));
|
|
7484
7367
|
console.log(formatJson(envelope));
|
|
7485
7368
|
}
|
|
7486
7369
|
const result = await api.ingest(envelope);
|
|
@@ -7500,23 +7383,23 @@ async function runSendHandshake(recipientDid, opts) {
|
|
|
7500
7383
|
});
|
|
7501
7384
|
return;
|
|
7502
7385
|
}
|
|
7503
|
-
console.log(
|
|
7504
|
-
console.log(`${
|
|
7505
|
-
console.log(`${
|
|
7506
|
-
console.log(`${
|
|
7507
|
-
console.log(`${
|
|
7508
|
-
console.log(`${
|
|
7509
|
-
console.log(`${
|
|
7386
|
+
console.log(import_chalk30.default.green("\nDelivered."));
|
|
7387
|
+
console.log(`${import_chalk30.default.bold("Event id")}: ${import_chalk30.default.cyan(result.eventId)}`);
|
|
7388
|
+
console.log(`${import_chalk30.default.bold("Relationship id")}: ${import_chalk30.default.cyan(result.relationshipId)}`);
|
|
7389
|
+
console.log(`${import_chalk30.default.bold("Chain index")}: ${import_chalk30.default.cyan(String(result.relationshipEventIndex))}`);
|
|
7390
|
+
console.log(`${import_chalk30.default.bold("Server timestamp")}: ${import_chalk30.default.cyan(result.serverTimestamp)}`);
|
|
7391
|
+
console.log(`${import_chalk30.default.bold("Signed message hash")}: ${import_chalk30.default.cyan(result.signedMessageHash)}`);
|
|
7392
|
+
console.log(`${import_chalk30.default.bold("Server event hash")}: ${import_chalk30.default.cyan(result.serverEventHash)}`);
|
|
7510
7393
|
if (result.prevServerEventHash) {
|
|
7511
|
-
console.log(`${
|
|
7394
|
+
console.log(`${import_chalk30.default.bold("Prev server event hash")}: ${import_chalk30.default.cyan(result.prevServerEventHash)}`);
|
|
7512
7395
|
} else {
|
|
7513
|
-
console.log(`${
|
|
7396
|
+
console.log(`${import_chalk30.default.bold("Prev server event hash")}: ${import_chalk30.default.dim("(null \u2014 first event of this relationship)")}`);
|
|
7514
7397
|
}
|
|
7515
7398
|
if (opts.verbose) {
|
|
7516
|
-
console.log(
|
|
7399
|
+
console.log(import_chalk30.default.bold("\nFull server response:"));
|
|
7517
7400
|
console.log(formatJson(result));
|
|
7518
7401
|
}
|
|
7519
|
-
console.log(
|
|
7402
|
+
console.log(import_chalk30.default.dim(`
|
|
7520
7403
|
Local sender_sequence advanced to ${nextSequence}.`));
|
|
7521
7404
|
}
|
|
7522
7405
|
function parseTtl3(raw) {
|
|
@@ -7529,19 +7412,19 @@ function parseTtl3(raw) {
|
|
|
7529
7412
|
}
|
|
7530
7413
|
|
|
7531
7414
|
// src/commands/send-handshake-response.ts
|
|
7532
|
-
var
|
|
7533
|
-
var
|
|
7415
|
+
var import_sdk29 = require("@heyanon-arp/sdk");
|
|
7416
|
+
var import_chalk31 = __toESM(require("chalk"));
|
|
7534
7417
|
init_api();
|
|
7535
|
-
var ALLOWED_DECISIONS = new Set(
|
|
7418
|
+
var ALLOWED_DECISIONS = new Set(import_sdk29.HANDSHAKE_DECISIONS);
|
|
7536
7419
|
function registerSendHandshakeResponseCommand(root) {
|
|
7537
|
-
root.command("send-handshake-response").description("Accept or decline an inbound handshake from <recipient-did>. Server reuses the existing relationship row.").argument("<recipient-did>", "Recipient agent DID (did:arp:...) \u2014 the original handshake sender").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--decision <s>", "REQUIRED: accept or decline").option("--notes <s>", "Optional notes included in body.content").option(
|
|
7420
|
+
root.command("send-handshake-response").description("Accept or decline an inbound handshake from <recipient-did>. Server reuses the existing relationship row.").argument("<recipient-did>", "Recipient agent DID (did:arp:...) \u2014 the original handshake sender").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--decision <s>", "REQUIRED: accept or decline").option("--notes <s>", "Optional notes included in body.content").option(
|
|
7538
7421
|
"--reason <code>",
|
|
7539
7422
|
// REQUIRED when --decision=decline. Optional otherwise.
|
|
7540
7423
|
// We don't use commander's requiredOption because it
|
|
7541
7424
|
// would fire for the accept path too; validate manually
|
|
7542
7425
|
// after decision is parsed.
|
|
7543
|
-
`When --decision=decline: required reason code (one of: ${
|
|
7544
|
-
).option("--reason-detail <s>", "Optional free-text elaboration alongside --reason (max 512 chars).").option("--ttl <seconds>", `Envelope TTL in seconds (max ${
|
|
7426
|
+
`When --decision=decline: required reason code (one of: ${import_sdk29.DECLINE_REASONS.join(", ")}). Carried in body.content.reason.`
|
|
7427
|
+
).option("--reason-detail <s>", "Optional free-text elaboration alongside --reason (max 512 chars).").option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk29.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
7545
7428
|
"--json",
|
|
7546
7429
|
"Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, decision, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash, prevServerEventHash}; idempotent short-circuit adds {idempotent:true}). Prelude + banners move off stdout; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.",
|
|
7547
7430
|
false
|
|
@@ -7559,23 +7442,23 @@ async function runSendHandshakeResponse(recipientDid, opts) {
|
|
|
7559
7442
|
"send-handshake-response: --verbose and --json are mutually exclusive. --json emits the structured server response; --verbose adds envelope + response dumps that would break `--json | jq`."
|
|
7560
7443
|
);
|
|
7561
7444
|
}
|
|
7562
|
-
if (!(0,
|
|
7445
|
+
if (!(0, import_sdk29.isValidDid)(recipientDid)) {
|
|
7563
7446
|
throw new Error(`send-handshake-response: <recipient-did> must be a valid did:arp identifier (base58btc-encoded 32-byte Ed25519 pubkey) (got '${recipientDid}')`);
|
|
7564
7447
|
}
|
|
7565
7448
|
const decision = parseDecision(opts.decision);
|
|
7566
7449
|
const ttlSeconds = parseTtl4(opts.ttl);
|
|
7567
7450
|
let declinePayload = null;
|
|
7568
|
-
if (decision ===
|
|
7451
|
+
if (decision === import_sdk29.HandshakeDecisions.DECLINE) {
|
|
7569
7452
|
const reason = parseDeclineReason("send-handshake-response", opts.reason);
|
|
7570
7453
|
const detail = parseReasonDetail("send-handshake-response", opts.reasonDetail);
|
|
7571
7454
|
declinePayload = detail ? { reason, reasonDetail: detail } : { reason };
|
|
7572
7455
|
}
|
|
7573
7456
|
const api = new ArpApiClient(opts.server);
|
|
7574
|
-
progress(opts.json,
|
|
7575
|
-
const sender = resolveSenderAgent("send-handshake-response", opts.server, opts.fromDid);
|
|
7576
|
-
progress(opts.json,
|
|
7577
|
-
progress(opts.json,
|
|
7578
|
-
progress(opts.json,
|
|
7457
|
+
progress(opts.json, import_chalk31.default.dim(`Server: ${api.serverUrl}`));
|
|
7458
|
+
const sender = resolveSenderAgent("send-handshake-response", opts.server, opts.fromDid, opts.from);
|
|
7459
|
+
progress(opts.json, import_chalk31.default.dim(`Sender: ${sender.did}`));
|
|
7460
|
+
progress(opts.json, import_chalk31.default.dim(`Recipient: ${recipientDid}`));
|
|
7461
|
+
progress(opts.json, import_chalk31.default.dim(`Decision: ${decision}`));
|
|
7579
7462
|
const signer = makeSigner(sender);
|
|
7580
7463
|
if (!opts.force) {
|
|
7581
7464
|
try {
|
|
@@ -7605,13 +7488,13 @@ async function runSendHandshakeResponse(recipientDid, opts) {
|
|
|
7605
7488
|
});
|
|
7606
7489
|
return;
|
|
7607
7490
|
}
|
|
7608
|
-
progress(opts.json,
|
|
7491
|
+
progress(opts.json, import_chalk31.default.yellow(`
|
|
7609
7492
|
[--idempotency] Relationship ${existing.relationshipId} with ${recipientDid} is already 'active'.`));
|
|
7610
7493
|
progress(
|
|
7611
7494
|
opts.json,
|
|
7612
|
-
|
|
7495
|
+
import_chalk31.default.dim(`A previous accept from this signer (event ${previousResponseFromMe.eventId}) landed successfully. Skipping re-send (use --force to override).`)
|
|
7613
7496
|
);
|
|
7614
|
-
progress(opts.json,
|
|
7497
|
+
progress(opts.json, import_chalk31.default.dim(`Last event index: ${existing.lastEventIndex}, last server event hash: ${existing.lastServerEventHash ?? "(none)"}`));
|
|
7615
7498
|
return;
|
|
7616
7499
|
}
|
|
7617
7500
|
throw new Error(
|
|
@@ -7622,7 +7505,7 @@ async function runSendHandshakeResponse(recipientDid, opts) {
|
|
|
7622
7505
|
if (probeErr instanceof Error && /CLOSED|terminated|already 'active' from a previous ACCEPT|original initiator/i.test(probeErr.message)) {
|
|
7623
7506
|
throw probeErr;
|
|
7624
7507
|
}
|
|
7625
|
-
progress(opts.json,
|
|
7508
|
+
progress(opts.json, import_chalk31.default.dim(`(idempotency probe failed; proceeding anyway: ${probeErr.message})`));
|
|
7626
7509
|
}
|
|
7627
7510
|
}
|
|
7628
7511
|
const content = { decision };
|
|
@@ -7634,25 +7517,25 @@ async function runSendHandshakeResponse(recipientDid, opts) {
|
|
|
7634
7517
|
const body = { type: "handshake_response", content };
|
|
7635
7518
|
const nextSequence = (sender.lastSenderSequence ?? 0) + 1;
|
|
7636
7519
|
const protectedBlock = {
|
|
7637
|
-
protocol_version:
|
|
7638
|
-
purpose:
|
|
7639
|
-
message_id: (0,
|
|
7520
|
+
protocol_version: import_sdk29.CURRENT_PROTOCOL_VERSION,
|
|
7521
|
+
purpose: import_sdk29.Purpose.ENVELOPE,
|
|
7522
|
+
message_id: (0, import_sdk29.uuidV4)(),
|
|
7640
7523
|
sender_did: sender.did,
|
|
7641
7524
|
recipient_did: recipientDid,
|
|
7642
7525
|
relationship_id: null,
|
|
7643
7526
|
sender_sequence: nextSequence,
|
|
7644
|
-
sender_nonce: (0,
|
|
7645
|
-
timestamp: (0,
|
|
7646
|
-
expires_at: (0,
|
|
7527
|
+
sender_nonce: (0, import_sdk29.senderNonce)(),
|
|
7528
|
+
timestamp: (0, import_sdk29.rfc3339)(),
|
|
7529
|
+
expires_at: (0, import_sdk29.expiresAt)(ttlSeconds),
|
|
7647
7530
|
delivery_id: null
|
|
7648
7531
|
};
|
|
7649
|
-
const envelope = (0,
|
|
7532
|
+
const envelope = (0, import_sdk29.signEnvelope)({
|
|
7650
7533
|
protected: protectedBlock,
|
|
7651
7534
|
body,
|
|
7652
7535
|
identitySecretKey: signer.identitySecretKey
|
|
7653
7536
|
});
|
|
7654
7537
|
if (opts.verbose) {
|
|
7655
|
-
console.log(
|
|
7538
|
+
console.log(import_chalk31.default.bold("\nEnvelope (pre-send):"));
|
|
7656
7539
|
console.log(formatJson(envelope));
|
|
7657
7540
|
}
|
|
7658
7541
|
const result = await api.ingest(envelope);
|
|
@@ -7673,23 +7556,23 @@ async function runSendHandshakeResponse(recipientDid, opts) {
|
|
|
7673
7556
|
});
|
|
7674
7557
|
return;
|
|
7675
7558
|
}
|
|
7676
|
-
console.log(
|
|
7677
|
-
console.log(`${
|
|
7678
|
-
console.log(`${
|
|
7679
|
-
console.log(`${
|
|
7680
|
-
console.log(`${
|
|
7681
|
-
console.log(`${
|
|
7682
|
-
console.log(`${
|
|
7559
|
+
console.log(import_chalk31.default.green("\nDelivered."));
|
|
7560
|
+
console.log(`${import_chalk31.default.bold("Event id")}: ${import_chalk31.default.cyan(result.eventId)}`);
|
|
7561
|
+
console.log(`${import_chalk31.default.bold("Relationship id")}: ${import_chalk31.default.cyan(result.relationshipId)}`);
|
|
7562
|
+
console.log(`${import_chalk31.default.bold("Chain index")}: ${import_chalk31.default.cyan(String(result.relationshipEventIndex))}`);
|
|
7563
|
+
console.log(`${import_chalk31.default.bold("Server timestamp")}: ${import_chalk31.default.cyan(result.serverTimestamp)}`);
|
|
7564
|
+
console.log(`${import_chalk31.default.bold("Signed message hash")}: ${import_chalk31.default.cyan(result.signedMessageHash)}`);
|
|
7565
|
+
console.log(`${import_chalk31.default.bold("Server event hash")}: ${import_chalk31.default.cyan(result.serverEventHash)}`);
|
|
7683
7566
|
if (result.prevServerEventHash) {
|
|
7684
|
-
console.log(`${
|
|
7567
|
+
console.log(`${import_chalk31.default.bold("Prev server event hash")}: ${import_chalk31.default.cyan(result.prevServerEventHash)}`);
|
|
7685
7568
|
} else {
|
|
7686
|
-
console.log(`${
|
|
7569
|
+
console.log(`${import_chalk31.default.bold("Prev server event hash")}: ${import_chalk31.default.dim("(null \u2014 first event of this relationship)")}`);
|
|
7687
7570
|
}
|
|
7688
7571
|
if (opts.verbose) {
|
|
7689
|
-
console.log(
|
|
7572
|
+
console.log(import_chalk31.default.bold("\nFull server response:"));
|
|
7690
7573
|
console.log(formatJson(result));
|
|
7691
7574
|
}
|
|
7692
|
-
console.log(
|
|
7575
|
+
console.log(import_chalk31.default.dim(`
|
|
7693
7576
|
Local sender_sequence advanced to ${nextSequence}.`));
|
|
7694
7577
|
}
|
|
7695
7578
|
function parseDecision(raw) {
|
|
@@ -7711,8 +7594,8 @@ function parseTtl4(raw) {
|
|
|
7711
7594
|
}
|
|
7712
7595
|
function classifyIdempotencyOutcome(decision, existing) {
|
|
7713
7596
|
if (!existing) return { kind: "proceed" };
|
|
7714
|
-
if (existing.state ===
|
|
7715
|
-
if (decision ===
|
|
7597
|
+
if (existing.state === import_sdk29.RelationshipStates.ACTIVE) {
|
|
7598
|
+
if (decision === import_sdk29.HandshakeDecisions.DECLINE) {
|
|
7716
7599
|
return {
|
|
7717
7600
|
kind: "error",
|
|
7718
7601
|
message: `send-handshake-response: relationship ${existing.relationshipId} is already 'active' from a previous ACCEPT. A decline cannot reverse that \u2014 the active relationship is now under FSM control. If you want to terminate, close the relationship explicitly; pass --force to ignore this check and send the decline (which the server will reject with DOM_INVALID_TRANSITION).`
|
|
@@ -7720,7 +7603,7 @@ function classifyIdempotencyOutcome(decision, existing) {
|
|
|
7720
7603
|
}
|
|
7721
7604
|
return { kind: "short-circuit" };
|
|
7722
7605
|
}
|
|
7723
|
-
if (existing.state ===
|
|
7606
|
+
if (existing.state === import_sdk29.RelationshipStates.CLOSED) {
|
|
7724
7607
|
return {
|
|
7725
7608
|
kind: "error",
|
|
7726
7609
|
message: `send-handshake-response: relationship ${existing.relationshipId} is CLOSED. Cannot respond to handshake on a terminated relationship \u2014 start a fresh handshake instead.`
|
|
@@ -7740,20 +7623,20 @@ async function findExistingRelationship(api, signer, senderDid, recipientDid) {
|
|
|
7740
7623
|
}
|
|
7741
7624
|
|
|
7742
7625
|
// src/commands/watch.ts
|
|
7743
|
-
var
|
|
7626
|
+
var import_chalk32 = __toESM(require("chalk"));
|
|
7744
7627
|
init_api();
|
|
7745
7628
|
function registerWatchCommand(root) {
|
|
7746
|
-
root.command("watch").description("Live tail filtered to a single relationship (SSE). Server-side $match; only envelopes belonging to <rel-id> are streamed.").argument("<relationship-id>", "Relationship UUID to watch").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--verbose", "After each envelope, print the full JSON with a per-row label including eventId + serverEventHash", false).option("--json", "Machine-readable: one NDJSON object per line. Pipe-safe into `jq -c`.", false).option("--full-ids", "Print DIDs + serverEventHash in full (no truncation).", false).action(async (relationshipId, opts) => {
|
|
7629
|
+
root.command("watch").description("Live tail filtered to a single relationship (SSE). Server-side $match; only envelopes belonging to <rel-id> are streamed.").argument("<relationship-id>", "Relationship UUID to watch").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--verbose", "After each envelope, print the full JSON with a per-row label including eventId + serverEventHash", false).option("--json", "Machine-readable: one NDJSON object per line. Pipe-safe into `jq -c`.", false).option("--full-ids", "Print DIDs + serverEventHash in full (no truncation).", false).action(async (relationshipId, opts) => {
|
|
7747
7630
|
await runWatch(relationshipId, opts);
|
|
7748
7631
|
});
|
|
7749
7632
|
}
|
|
7750
7633
|
async function runWatch(relationshipId, opts) {
|
|
7751
|
-
const local = resolveSenderAgent("watch", opts.server, opts.fromDid);
|
|
7634
|
+
const local = resolveSenderAgent("watch", opts.server, opts.fromDid, opts.from);
|
|
7752
7635
|
const api = new ArpApiClient(opts.server);
|
|
7753
7636
|
if (!opts.json) {
|
|
7754
|
-
console.log(
|
|
7755
|
-
console.log(
|
|
7756
|
-
console.log(
|
|
7637
|
+
console.log(import_chalk32.default.dim(`Server: ${api.serverUrl}`));
|
|
7638
|
+
console.log(import_chalk32.default.dim(`Signer: ${local.did}`));
|
|
7639
|
+
console.log(import_chalk32.default.dim(`Watching: ${relationshipId}`));
|
|
7757
7640
|
}
|
|
7758
7641
|
const controller = new AbortController();
|
|
7759
7642
|
let userAborted = false;
|
|
@@ -7772,7 +7655,7 @@ async function runWatch(relationshipId, opts) {
|
|
|
7772
7655
|
}
|
|
7773
7656
|
if (event.type === "heartbeat") continue;
|
|
7774
7657
|
if (event.type === "connected") {
|
|
7775
|
-
console.log(
|
|
7658
|
+
console.log(import_chalk32.default.green(`\u25CF stream open \u2014 watching ${relationshipId}`));
|
|
7776
7659
|
continue;
|
|
7777
7660
|
}
|
|
7778
7661
|
if (event.type === "envelope") {
|
|
@@ -7786,7 +7669,7 @@ async function runWatch(relationshipId, opts) {
|
|
|
7786
7669
|
}
|
|
7787
7670
|
continue;
|
|
7788
7671
|
}
|
|
7789
|
-
console.log(
|
|
7672
|
+
console.log(import_chalk32.default.dim(`(unknown event: ${event.type})`));
|
|
7790
7673
|
}
|
|
7791
7674
|
if (!userAborted) {
|
|
7792
7675
|
throw new Error(`watch ${relationshipId}: stream ended unexpectedly (server may have restarted, or the change stream errored). Re-run to reconnect.`);
|
|
@@ -7794,7 +7677,7 @@ async function runWatch(relationshipId, opts) {
|
|
|
7794
7677
|
} catch (err) {
|
|
7795
7678
|
const name = err.name;
|
|
7796
7679
|
if (name === "AbortError" || userAborted) {
|
|
7797
|
-
if (!opts.json) console.log(
|
|
7680
|
+
if (!opts.json) console.log(import_chalk32.default.dim("\nstream closed."));
|
|
7798
7681
|
return;
|
|
7799
7682
|
}
|
|
7800
7683
|
throw err;
|
|
@@ -7808,21 +7691,21 @@ function formatWatchLine(ev, selfDid, opts = {}) {
|
|
|
7808
7691
|
const type = ev.type.padEnd(20);
|
|
7809
7692
|
const direction = directionLabel2(ev, selfDid, opts);
|
|
7810
7693
|
const hash = opts.fullIds ? ev.serverEventHash : hashHead4(ev.serverEventHash);
|
|
7811
|
-
return `${
|
|
7694
|
+
return `${import_chalk32.default.dim(`[${ts}]`)} ${type} ${direction} ${import_chalk32.default.cyan(hash)}`;
|
|
7812
7695
|
}
|
|
7813
7696
|
function directionLabel2(ev, selfDid, opts = {}) {
|
|
7814
7697
|
const senderHead = opts.fullIds ? ev.senderDid : didHead4(ev.senderDid);
|
|
7815
7698
|
const recipientHead = opts.fullIds ? ev.recipientDid : didHead4(ev.recipientDid);
|
|
7816
|
-
if (ev.senderDid === selfDid) return `${
|
|
7817
|
-
if (ev.recipientDid === selfDid) return `${
|
|
7818
|
-
return `${
|
|
7699
|
+
if (ev.senderDid === selfDid) return `${import_chalk32.default.bold("me")} \u2192 ${import_chalk32.default.dim(recipientHead)}`;
|
|
7700
|
+
if (ev.recipientDid === selfDid) return `${import_chalk32.default.dim(senderHead)} \u2192 ${import_chalk32.default.bold("me")}`;
|
|
7701
|
+
return `${import_chalk32.default.dim(senderHead)} \u2192 ${import_chalk32.default.dim(recipientHead)}`;
|
|
7819
7702
|
}
|
|
7820
7703
|
function didHead4(did) {
|
|
7821
7704
|
if (did.length <= 20) return did;
|
|
7822
7705
|
return `${did.slice(0, 20)}...`;
|
|
7823
7706
|
}
|
|
7824
7707
|
function hashHead4(hash) {
|
|
7825
|
-
if (!hash) return
|
|
7708
|
+
if (!hash) return import_chalk32.default.dim("(none)");
|
|
7826
7709
|
if (hash.length <= 14) return hash;
|
|
7827
7710
|
return `${hash.slice(0, 14)}...`;
|
|
7828
7711
|
}
|
|
@@ -7834,12 +7717,12 @@ function formatClock(iso) {
|
|
|
7834
7717
|
}
|
|
7835
7718
|
|
|
7836
7719
|
// src/commands/whoami.ts
|
|
7837
|
-
var
|
|
7720
|
+
var import_chalk33 = __toESM(require("chalk"));
|
|
7838
7721
|
init_api();
|
|
7839
7722
|
function registerWhoamiCommand(root) {
|
|
7840
7723
|
root.command("whoami").description(
|
|
7841
7724
|
"Identify the local agent: print DID + settlement pubkey + identity pubkey (with --local), and/or fetch the server profile via signed GET /agents/:did. When <did> is omitted, uses the same sole-agent resolution as other signed commands."
|
|
7842
|
-
).argument("[did]", "Agent DID (did:arp:...) \u2014 omit when there is exactly ONE local agent (sole-agent fallback)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Explicit sender DID \u2014 same precedence as the positional arg, surfaced for symmetry with other commands").option(
|
|
7725
|
+
).argument("[did]", "Agent DID (did:arp:...) \u2014 omit when there is exactly ONE local agent (sole-agent fallback)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Explicit sender DID \u2014 same precedence as the positional arg, surfaced for symmetry with other commands").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
7843
7726
|
"--local",
|
|
7844
7727
|
// Persona scripts want the local settlement pubkey for
|
|
7845
7728
|
// `--payer-settlement-pubkey` / on-chain ops without a
|
|
@@ -7851,7 +7734,8 @@ function registerWhoamiCommand(root) {
|
|
|
7851
7734
|
).option("--json", "JSON output (jq-pipeable). Combines local + server data when --local is unset, or just local when --local is set.", false).action(async (didArg, opts, cmd) => {
|
|
7852
7735
|
try {
|
|
7853
7736
|
const explicitDid = didArg ?? opts.fromDid;
|
|
7854
|
-
const
|
|
7737
|
+
const explicitFrom = opts.from;
|
|
7738
|
+
const local = resolveSenderAgent("whoami", opts.server, explicitDid, explicitFrom);
|
|
7855
7739
|
const api = new ArpApiClient(opts.server);
|
|
7856
7740
|
const credential = readCredential(api.serverUrl);
|
|
7857
7741
|
const localJson = {
|
|
@@ -7864,12 +7748,12 @@ function registerWhoamiCommand(root) {
|
|
|
7864
7748
|
if (opts.json) {
|
|
7865
7749
|
console.log(formatJson({ ...localJson, account: credential ? { wallet: credential.wallet } : null }));
|
|
7866
7750
|
} else {
|
|
7867
|
-
console.log(
|
|
7868
|
-
console.log(` DID: ${
|
|
7869
|
-
console.log(` Settlement pubkey: ${
|
|
7870
|
-
console.log(` Identity pubkey: ${
|
|
7751
|
+
console.log(import_chalk33.default.bold("Local agent:"));
|
|
7752
|
+
console.log(` DID: ${import_chalk33.default.cyan(local.did)}`);
|
|
7753
|
+
console.log(` Settlement pubkey: ${import_chalk33.default.cyan(local.settlementPublicKeyB58)}`);
|
|
7754
|
+
console.log(` Identity pubkey: ${import_chalk33.default.cyan(local.identityPublicKeyB58)}`);
|
|
7871
7755
|
if (local.name) console.log(` Name: ${local.name}`);
|
|
7872
|
-
console.log(` Account: ${credential ?
|
|
7756
|
+
console.log(` Account: ${credential ? import_chalk33.default.cyan(credential.wallet) : import_chalk33.default.dim("not logged in (heyarp login)")}`);
|
|
7873
7757
|
}
|
|
7874
7758
|
return;
|
|
7875
7759
|
}
|
|
@@ -7887,19 +7771,19 @@ function registerWhoamiCommand(root) {
|
|
|
7887
7771
|
if (opts.json) {
|
|
7888
7772
|
console.log(formatJson({ local: localJson, account, server: agent }));
|
|
7889
7773
|
} else {
|
|
7890
|
-
console.log(
|
|
7891
|
-
console.log(
|
|
7892
|
-
console.log(` DID: ${
|
|
7893
|
-
console.log(` Settlement pubkey: ${
|
|
7894
|
-
console.log(` Identity pubkey: ${
|
|
7895
|
-
console.log(
|
|
7774
|
+
console.log(import_chalk33.default.dim(`Server: ${api.serverUrl}`));
|
|
7775
|
+
console.log(import_chalk33.default.bold("\nLocal agent:"));
|
|
7776
|
+
console.log(` DID: ${import_chalk33.default.cyan(local.did)}`);
|
|
7777
|
+
console.log(` Settlement pubkey: ${import_chalk33.default.cyan(local.settlementPublicKeyB58)}`);
|
|
7778
|
+
console.log(` Identity pubkey: ${import_chalk33.default.cyan(local.identityPublicKeyB58)}`);
|
|
7779
|
+
console.log(import_chalk33.default.bold("\nAccount:"));
|
|
7896
7780
|
if (account) {
|
|
7897
|
-
console.log(` Wallet: ${
|
|
7781
|
+
console.log(` Wallet: ${import_chalk33.default.cyan(account.wallet)}`);
|
|
7898
7782
|
console.log(` Agents registered: ${account.agentCount}`);
|
|
7899
7783
|
} else {
|
|
7900
|
-
console.log(` ${
|
|
7784
|
+
console.log(` ${import_chalk33.default.dim("not logged in (heyarp login)")}`);
|
|
7901
7785
|
}
|
|
7902
|
-
console.log(
|
|
7786
|
+
console.log(import_chalk33.default.bold("\nServer profile:"));
|
|
7903
7787
|
console.log(formatJson(agent));
|
|
7904
7788
|
}
|
|
7905
7789
|
} catch (err) {
|
|
@@ -7909,9 +7793,49 @@ function registerWhoamiCommand(root) {
|
|
|
7909
7793
|
});
|
|
7910
7794
|
}
|
|
7911
7795
|
|
|
7796
|
+
// src/commands/whois.ts
|
|
7797
|
+
var import_sdk30 = require("@heyanon-arp/sdk");
|
|
7798
|
+
var import_chalk34 = __toESM(require("chalk"));
|
|
7799
|
+
init_api();
|
|
7800
|
+
function registerWhoisCommand(root) {
|
|
7801
|
+
root.command("whois").description("Resolve an agent name (handle) or DID to its public profile \u2014 DID, description, reputation, liveness.").argument("<name-or-did>", "Agent name (handle) or DID (did:arp:...)").option("--server <url>", "Override ARP server base URL").option("--json", "Emit the full composed profile (DiscoveryProfile) as a single JSON object on stdout.", false).action(async (input, opts) => {
|
|
7802
|
+
const api = new ArpApiClient(opts.server);
|
|
7803
|
+
progress(opts.json, import_chalk34.default.dim(`Server: ${api.serverUrl}`));
|
|
7804
|
+
const profile = await resolveProfile(api, input);
|
|
7805
|
+
if (opts.json) {
|
|
7806
|
+
jsonOut(profile);
|
|
7807
|
+
return;
|
|
7808
|
+
}
|
|
7809
|
+
printProfile(profile);
|
|
7810
|
+
});
|
|
7811
|
+
}
|
|
7812
|
+
async function resolveProfile(api, input) {
|
|
7813
|
+
if (input.startsWith("did:arp:")) {
|
|
7814
|
+
if (!(0, import_sdk30.isValidDid)(input)) {
|
|
7815
|
+
throw new Error(`whois: '${input}' starts with did:arp: but is not a valid DID (base58btc-encoded 32-byte Ed25519 pubkey).`);
|
|
7816
|
+
}
|
|
7817
|
+
return api.discoverProfile(input);
|
|
7818
|
+
}
|
|
7819
|
+
const name = (0, import_sdk30.normalizeName)(input);
|
|
7820
|
+
if (!(0, import_sdk30.isValidAgentName)(name)) {
|
|
7821
|
+
throw new Error(`whois: '${input}' is neither a DID (did:arp:...) nor a valid agent name (lowercase a-z0-9_, 3-32 chars).`);
|
|
7822
|
+
}
|
|
7823
|
+
return api.discoverByName(name);
|
|
7824
|
+
}
|
|
7825
|
+
function printProfile(p) {
|
|
7826
|
+
console.log(`${import_chalk34.default.bold("Name")}: ${import_chalk34.default.cyan(p.name ?? "(unnamed)")}`);
|
|
7827
|
+
console.log(`${import_chalk34.default.bold("DID")}: ${import_chalk34.default.cyan(p.did)}`);
|
|
7828
|
+
if (p.description) console.log(`${import_chalk34.default.bold("Description")}: ${p.description}`);
|
|
7829
|
+
if (p.tags.length > 0) console.log(`${import_chalk34.default.bold("Tags")}: ${p.tags.join(", ")}`);
|
|
7830
|
+
console.log(`${import_chalk34.default.bold("Registered")}: ${p.registeredAt}`);
|
|
7831
|
+
const rep = p.reputation;
|
|
7832
|
+
console.log(`${import_chalk34.default.bold("Reputation")}: composite ${rep.scores.composite}/100${rep.computed ? "" : import_chalk34.default.dim(" (cold-start \u2014 no settled cycles yet)")}`);
|
|
7833
|
+
console.log(`${import_chalk34.default.bold("Online")}: ${p.liveness.online ? import_chalk34.default.green("yes") : import_chalk34.default.dim("no")}`);
|
|
7834
|
+
}
|
|
7835
|
+
|
|
7912
7836
|
// src/commands/work.ts
|
|
7913
|
-
var
|
|
7914
|
-
var
|
|
7837
|
+
var import_sdk31 = require("@heyanon-arp/sdk");
|
|
7838
|
+
var import_chalk35 = __toESM(require("chalk"));
|
|
7915
7839
|
init_api();
|
|
7916
7840
|
function registerWorkCommands(root) {
|
|
7917
7841
|
const cmd = root.command("work").description("Work envelopes inside an ACCEPTED delegation: request / respond");
|
|
@@ -7919,13 +7843,13 @@ function registerWorkCommands(root) {
|
|
|
7919
7843
|
registerRespond(cmd);
|
|
7920
7844
|
}
|
|
7921
7845
|
function registerRequest(parent) {
|
|
7922
|
-
parent.command("request").description("Send a work_request to <recipient-did> under <delegation-id> (must be ACCEPTED).").argument("<recipient
|
|
7846
|
+
parent.command("request").description("Send a work_request to <recipient-did> under <delegation-id> (must be ACCEPTED).").argument("<recipient>", "Recipient \u2014 agent name (handle) or DID (the payee \u2014 the OTHER side of the delegation pair)").argument("<delegation-id>", "Parent delegation id (UUID, must be ACCEPTED)").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--request-id <id>", "Override the auto-generated request id (must be unique within the delegation)").option(
|
|
7923
7847
|
"--params <json>",
|
|
7924
7848
|
"JSON object payload as a literal string. Defaults to {}. Mutually exclusive with --params-file. Brittle against shell quoting \u2014 prefer --params-file for non-trivial bodies."
|
|
7925
7849
|
).option(
|
|
7926
7850
|
"--params-file <path>",
|
|
7927
7851
|
"Read the JSON payload from a file. Mutually exclusive with --params. Use this for any payload large or quote-heavy enough that `--params '{...}'` would fight your shell."
|
|
7928
|
-
).option("--ttl <seconds>", `Envelope TTL in seconds (max ${
|
|
7852
|
+
).option("--ttl <seconds>", `Envelope TTL in seconds (max ${import_sdk31.MAX_ENVELOPE_TTL_SECONDS} = 24h)`, "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
7929
7853
|
"--json",
|
|
7930
7854
|
'Machine-readable mode \u2014 emit a single JSON object on stdout ({ok, action:"work_request", requestId, delegationId, eventId, relationshipId, relationshipEventIndex, serverTimestamp, serverEventHash}). Prelude + reply hints move to stderr; on failure stderr carries `{code, message}`. Mutually exclusive with --verbose.',
|
|
7931
7855
|
false
|
|
@@ -7939,24 +7863,24 @@ async function runRequest(recipientDid, delegationId, opts) {
|
|
|
7939
7863
|
"work request: --verbose and --json are mutually exclusive. --json emits the structured server response; --verbose adds dumps that would break `--json | jq`."
|
|
7940
7864
|
);
|
|
7941
7865
|
}
|
|
7942
|
-
|
|
7866
|
+
recipientDid = await resolveRecipient(opts.server, "work request", recipientDid, { json: opts.json });
|
|
7943
7867
|
delegationId = requireUuidNormalised3("work request", delegationId, "<delegation-id>");
|
|
7944
7868
|
const ttlSeconds = parseTtl5("work request", opts.ttl);
|
|
7945
7869
|
const params = parseParamsInput("work request", opts);
|
|
7946
7870
|
const requestId = parseRequestId("work request", opts.requestId);
|
|
7947
7871
|
const api = new ArpApiClient(opts.server);
|
|
7948
|
-
const sender = resolveSenderAgent("work request", opts.server, opts.fromDid);
|
|
7872
|
+
const sender = resolveSenderAgent("work request", opts.server, opts.fromDid, opts.from);
|
|
7949
7873
|
const content = {
|
|
7950
7874
|
delegation_id: delegationId,
|
|
7951
7875
|
request_id: requestId,
|
|
7952
7876
|
params
|
|
7953
7877
|
};
|
|
7954
7878
|
const body = { type: "work_request", content };
|
|
7955
|
-
progress(opts.json,
|
|
7956
|
-
progress(opts.json,
|
|
7957
|
-
progress(opts.json,
|
|
7958
|
-
progress(opts.json,
|
|
7959
|
-
progress(opts.json,
|
|
7879
|
+
progress(opts.json, import_chalk35.default.dim(`Server: ${api.serverUrl}`));
|
|
7880
|
+
progress(opts.json, import_chalk35.default.dim(`Sender: ${sender.did}`));
|
|
7881
|
+
progress(opts.json, import_chalk35.default.dim(`Recipient: ${recipientDid}`));
|
|
7882
|
+
progress(opts.json, import_chalk35.default.dim(`Delegation: ${delegationId}`));
|
|
7883
|
+
progress(opts.json, import_chalk35.default.dim(`Request id: ${requestId}`));
|
|
7960
7884
|
const result = await sendWorkEnvelope({ api, sender, recipientDid, body, ttlSeconds, verbose: opts.verbose, server: opts.server });
|
|
7961
7885
|
if (opts.json) {
|
|
7962
7886
|
jsonOut({
|
|
@@ -7973,14 +7897,14 @@ async function runRequest(recipientDid, delegationId, opts) {
|
|
|
7973
7897
|
});
|
|
7974
7898
|
} else {
|
|
7975
7899
|
printIngestResult3(result);
|
|
7976
|
-
console.log(
|
|
7900
|
+
console.log(import_chalk35.default.dim(`
|
|
7977
7901
|
The payee can reply with:`));
|
|
7978
|
-
console.log(
|
|
7979
|
-
console.log(
|
|
7902
|
+
console.log(import_chalk35.default.dim(` heyarp work respond ${result.relationshipId} ${delegationId} ${requestId} --output '<json>'`));
|
|
7903
|
+
console.log(import_chalk35.default.dim(` heyarp work respond ${result.relationshipId} ${delegationId} ${requestId} --error CODE:message`));
|
|
7980
7904
|
}
|
|
7981
7905
|
}
|
|
7982
7906
|
function registerRespond(parent) {
|
|
7983
|
-
parent.command("respond").description("Send a work_response under <relationship-id> for <delegation-id> / <request-id>. Payee-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Parent delegation id (UUID)").argument("<request-id>", "Request id supplied on the work_request").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--output <json>", "Success payload as a JSON object literal. Mutually exclusive with --error and --output-file.").option(
|
|
7907
|
+
parent.command("respond").description("Send a work_response under <relationship-id> for <delegation-id> / <request-id>. Payee-only.").argument("<relationship-id>", "Relationship UUID").argument("<delegation-id>", "Parent delegation id (UUID)").argument("<request-id>", "Request id supplied on the work_request").option("--server <url>", "Override ARP server base URL").option("--from-did <did>", "Sender DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option("--output <json>", "Success payload as a JSON object literal. Mutually exclusive with --error and --output-file.").option(
|
|
7984
7908
|
"--output-file <path>",
|
|
7985
7909
|
"Read the success payload from a file. Mutually exclusive with --output and --error. Use this for any payload large or quote-heavy enough to fight your shell."
|
|
7986
7910
|
).option("--error <code:message>", "Failure payload as `CODE:message`. Mutually exclusive with --output / --output-file.").option("--ttl <seconds>", "Envelope TTL in seconds", "3600").option("--verbose", "Print the full envelope before sending and the full server response. Mutually exclusive with --json.", false).option(
|
|
@@ -8002,7 +7926,7 @@ async function runRespond(relationshipId, delegationId, requestId, opts) {
|
|
|
8002
7926
|
const ttlSeconds = parseTtl5("work respond", opts.ttl);
|
|
8003
7927
|
const responsePayload = parseResponsePayload("work respond", opts);
|
|
8004
7928
|
const api = new ArpApiClient(opts.server);
|
|
8005
|
-
const sender = resolveSenderAgent("work respond", opts.server, opts.fromDid);
|
|
7929
|
+
const sender = resolveSenderAgent("work respond", opts.server, opts.fromDid, opts.from);
|
|
8006
7930
|
const signer = makeSigner(sender);
|
|
8007
7931
|
const recipientDid = await resolveResponseRecipient("work respond", api, signer, { relationshipId, delegationId, requestId, selfDid: sender.did });
|
|
8008
7932
|
const content = {
|
|
@@ -8011,13 +7935,13 @@ async function runRespond(relationshipId, delegationId, requestId, opts) {
|
|
|
8011
7935
|
...responsePayload
|
|
8012
7936
|
};
|
|
8013
7937
|
const body = { type: "work_response", content };
|
|
8014
|
-
progress(opts.json,
|
|
8015
|
-
progress(opts.json,
|
|
8016
|
-
progress(opts.json,
|
|
8017
|
-
progress(opts.json,
|
|
8018
|
-
progress(opts.json,
|
|
8019
|
-
progress(opts.json,
|
|
8020
|
-
progress(opts.json,
|
|
7938
|
+
progress(opts.json, import_chalk35.default.dim(`Server: ${api.serverUrl}`));
|
|
7939
|
+
progress(opts.json, import_chalk35.default.dim(`Sender: ${sender.did}`));
|
|
7940
|
+
progress(opts.json, import_chalk35.default.dim(`Recipient: ${recipientDid}`));
|
|
7941
|
+
progress(opts.json, import_chalk35.default.dim(`Relationship: ${relationshipId}`));
|
|
7942
|
+
progress(opts.json, import_chalk35.default.dim(`Delegation: ${delegationId}`));
|
|
7943
|
+
progress(opts.json, import_chalk35.default.dim(`Request id: ${requestId}`));
|
|
7944
|
+
progress(opts.json, import_chalk35.default.dim(`Outcome: ${responsePayload.output ? "success" : "error"}`));
|
|
8021
7945
|
const result = await sendWorkEnvelope({ api, sender, recipientDid, body, ttlSeconds, verbose: opts.verbose, server: opts.server });
|
|
8022
7946
|
if (opts.json) {
|
|
8023
7947
|
jsonOut({
|
|
@@ -8039,26 +7963,26 @@ async function runRespond(relationshipId, delegationId, requestId, opts) {
|
|
|
8039
7963
|
async function sendWorkEnvelope(args) {
|
|
8040
7964
|
const nextSequence = (args.sender.lastSenderSequence ?? 0) + 1;
|
|
8041
7965
|
const protectedBlock = {
|
|
8042
|
-
protocol_version:
|
|
8043
|
-
purpose:
|
|
8044
|
-
message_id: (0,
|
|
7966
|
+
protocol_version: import_sdk31.CURRENT_PROTOCOL_VERSION,
|
|
7967
|
+
purpose: import_sdk31.Purpose.ENVELOPE,
|
|
7968
|
+
message_id: (0, import_sdk31.uuidV4)(),
|
|
8045
7969
|
sender_did: args.sender.did,
|
|
8046
7970
|
recipient_did: args.recipientDid,
|
|
8047
7971
|
relationship_id: null,
|
|
8048
7972
|
sender_sequence: nextSequence,
|
|
8049
|
-
sender_nonce: (0,
|
|
8050
|
-
timestamp: (0,
|
|
8051
|
-
expires_at: (0,
|
|
7973
|
+
sender_nonce: (0, import_sdk31.senderNonce)(),
|
|
7974
|
+
timestamp: (0, import_sdk31.rfc3339)(),
|
|
7975
|
+
expires_at: (0, import_sdk31.expiresAt)(args.ttlSeconds),
|
|
8052
7976
|
delivery_id: null
|
|
8053
7977
|
};
|
|
8054
7978
|
const signer = makeSigner(args.sender);
|
|
8055
|
-
const envelope = (0,
|
|
7979
|
+
const envelope = (0, import_sdk31.signEnvelope)({
|
|
8056
7980
|
protected: protectedBlock,
|
|
8057
7981
|
body: args.body,
|
|
8058
7982
|
identitySecretKey: signer.identitySecretKey
|
|
8059
7983
|
});
|
|
8060
7984
|
if (args.verbose) {
|
|
8061
|
-
console.log(
|
|
7985
|
+
console.log(import_chalk35.default.bold("\nEnvelope (pre-send):"));
|
|
8062
7986
|
console.log(formatJson(envelope));
|
|
8063
7987
|
}
|
|
8064
7988
|
try {
|
|
@@ -8066,7 +7990,7 @@ async function sendWorkEnvelope(args) {
|
|
|
8066
7990
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
8067
7991
|
return result;
|
|
8068
7992
|
} catch (err) {
|
|
8069
|
-
if (err instanceof ApiError && (0,
|
|
7993
|
+
if (err instanceof ApiError && (0, import_sdk31.isPostCommitErrorCode)(err.payload.code)) {
|
|
8070
7994
|
updateAgentLocal(args.server, args.sender.did, { lastSenderSequence: nextSequence });
|
|
8071
7995
|
}
|
|
8072
7996
|
throw err;
|
|
@@ -8078,7 +8002,7 @@ async function resolveResponseRecipient(cmdName, api, signer, args) {
|
|
|
8078
8002
|
const page = await api.listWorkLogs(args.relationshipId, signer, { delegationId: args.delegationId, limit: 100, after });
|
|
8079
8003
|
const row = page.find((w) => w.requestId === args.requestId);
|
|
8080
8004
|
if (row) {
|
|
8081
|
-
if (row.state !==
|
|
8005
|
+
if (row.state !== import_sdk31.WorkLogStates.REQUESTED) {
|
|
8082
8006
|
throw new Error(
|
|
8083
8007
|
`${cmdName}: work_request ${args.requestId} for delegation ${args.delegationId} is already in state '${row.state}' \u2014 only requests in state 'requested' can be responded to.`
|
|
8084
8008
|
);
|
|
@@ -8098,12 +8022,12 @@ async function resolveResponseRecipient(cmdName, api, signer, args) {
|
|
|
8098
8022
|
);
|
|
8099
8023
|
}
|
|
8100
8024
|
function printIngestResult3(result) {
|
|
8101
|
-
console.log(
|
|
8102
|
-
console.log(`${
|
|
8103
|
-
console.log(`${
|
|
8104
|
-
console.log(`${
|
|
8105
|
-
console.log(`${
|
|
8106
|
-
console.log(`${
|
|
8025
|
+
console.log(import_chalk35.default.green("\nDelivered."));
|
|
8026
|
+
console.log(`${import_chalk35.default.bold("Event id")}: ${import_chalk35.default.cyan(result.eventId)}`);
|
|
8027
|
+
console.log(`${import_chalk35.default.bold("Relationship id")}: ${import_chalk35.default.cyan(result.relationshipId)}`);
|
|
8028
|
+
console.log(`${import_chalk35.default.bold("Chain index")}: ${import_chalk35.default.cyan(String(result.relationshipEventIndex))}`);
|
|
8029
|
+
console.log(`${import_chalk35.default.bold("Server timestamp")}: ${import_chalk35.default.cyan(result.serverTimestamp)}`);
|
|
8030
|
+
console.log(`${import_chalk35.default.bold("Server event hash")}: ${import_chalk35.default.cyan(result.serverEventHash)}`);
|
|
8107
8031
|
}
|
|
8108
8032
|
function parseJsonObject(cmdName, flagName, raw) {
|
|
8109
8033
|
let parsed;
|
|
@@ -8195,7 +8119,7 @@ function parseTtl5(cmdName, raw) {
|
|
|
8195
8119
|
}
|
|
8196
8120
|
function parseRequestId(cmdName, raw) {
|
|
8197
8121
|
if (raw === void 0 || raw === "") {
|
|
8198
|
-
return (0,
|
|
8122
|
+
return (0, import_sdk31.uuidV4)();
|
|
8199
8123
|
}
|
|
8200
8124
|
if (raw.length === 0) {
|
|
8201
8125
|
throw new Error(`${cmdName}: --request-id must be a non-empty string`);
|
|
@@ -8209,19 +8133,14 @@ function requireUuidNormalised3(cmdName, raw, label) {
|
|
|
8209
8133
|
function requireUuid4(cmdName, raw, label) {
|
|
8210
8134
|
requireUuid(cmdName, raw, label);
|
|
8211
8135
|
}
|
|
8212
|
-
function requireDid3(cmdName, did, label) {
|
|
8213
|
-
if (typeof did !== "string" || !did.startsWith("did:arp:") || did.length <= "did:arp:".length) {
|
|
8214
|
-
throw new Error(`${cmdName}: ${label} must look like 'did:arp:...' (got '${did}')`);
|
|
8215
|
-
}
|
|
8216
|
-
}
|
|
8217
8136
|
|
|
8218
8137
|
// src/commands/work-list.ts
|
|
8219
|
-
var
|
|
8220
|
-
var
|
|
8138
|
+
var import_sdk32 = require("@heyanon-arp/sdk");
|
|
8139
|
+
var import_chalk36 = __toESM(require("chalk"));
|
|
8221
8140
|
init_api();
|
|
8222
|
-
var ALLOWED_STATES3 = new Set(
|
|
8141
|
+
var ALLOWED_STATES3 = new Set(import_sdk32.WORK_LOG_STATES);
|
|
8223
8142
|
function registerWorkListCommand(root) {
|
|
8224
|
-
root.command("work-list").description("List work-log rows for a relationship (one row per (delegationId, requestId), oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (requested|responded)").option("--delegation-id <uuid>", "Narrow to work-logs operating under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option(
|
|
8143
|
+
root.command("work-list").description("List work-log rows for a relationship (one row per (delegationId, requestId), oldest-first)").argument("<relationship-id>", "Relationship UUID").option("--server <url>", "Override ARP server base URL").option("--state <s>", "Filter by exact state (requested|responded)").option("--delegation-id <uuid>", "Narrow to work-logs operating under a specific delegation id").option("--after <id>", "Cursor: pass the previous page's last `id` to fetch the next page").option("--limit <n>", "Max rows to return (1..100)", "20").option("--from-did <did>", "Signer DID \u2014 required only if multiple agents are registered against this server").option("--from <name>", "Signer agent NAME (handle) \u2014 alternative to --from-did, resolved against your local agents").option(
|
|
8225
8144
|
"--verbose",
|
|
8226
8145
|
'After the summary, print a framed "Full work-log payloads (N rows)" block \u2014 each row labelled with full delegationId + requestId and dumped as JSON, including `requestParams` (the work_request payload the worker was asked) and `responseOutput` / `responseError`. Mutually exclusive with --json.',
|
|
8227
8146
|
false
|
|
@@ -8242,11 +8161,11 @@ async function runWorkList(relationshipId, opts) {
|
|
|
8242
8161
|
const limit = parseLimit7(opts.limit);
|
|
8243
8162
|
const state = parseState3(opts.state);
|
|
8244
8163
|
const api = new ArpApiClient(opts.server);
|
|
8245
|
-
const sender = resolveSenderAgent("work-list", opts.server, opts.fromDid);
|
|
8164
|
+
const sender = resolveSenderAgent("work-list", opts.server, opts.fromDid, opts.from);
|
|
8246
8165
|
if (!opts.json) {
|
|
8247
|
-
console.log(
|
|
8248
|
-
console.log(
|
|
8249
|
-
console.log(
|
|
8166
|
+
console.log(import_chalk36.default.dim(`Server: ${api.serverUrl}`));
|
|
8167
|
+
console.log(import_chalk36.default.dim(`Signer: ${sender.did}`));
|
|
8168
|
+
console.log(import_chalk36.default.dim(`Relationship: ${relationshipId}`));
|
|
8250
8169
|
}
|
|
8251
8170
|
const query = { limit };
|
|
8252
8171
|
if (state) query.state = state;
|
|
@@ -8259,7 +8178,7 @@ async function runWorkList(relationshipId, opts) {
|
|
|
8259
8178
|
return;
|
|
8260
8179
|
}
|
|
8261
8180
|
if (rows.length === 0) {
|
|
8262
|
-
console.log(
|
|
8181
|
+
console.log(import_chalk36.default.dim("\n(no work-logs for this relationship)"));
|
|
8263
8182
|
return;
|
|
8264
8183
|
}
|
|
8265
8184
|
console.log("");
|
|
@@ -8276,36 +8195,36 @@ async function runWorkList(relationshipId, opts) {
|
|
|
8276
8195
|
}));
|
|
8277
8196
|
}
|
|
8278
8197
|
const lastId = rows[rows.length - 1].id;
|
|
8279
|
-
console.log(
|
|
8198
|
+
console.log(import_chalk36.default.dim(`
|
|
8280
8199
|
${rows.length} work-log row(s). Paginate with --after ${lastId}.`));
|
|
8281
8200
|
}
|
|
8282
8201
|
function formatWorkLogLine(w, selfDid, opts = {}) {
|
|
8283
8202
|
const delegationPart = opts.fullIds ? w.delegationId : idHead3(w.delegationId);
|
|
8284
8203
|
const requestPart = opts.fullIds ? w.requestId : truncate3(w.requestId, 16);
|
|
8285
|
-
const id =
|
|
8204
|
+
const id = import_chalk36.default.bold(`${delegationPart}/${requestPart}`);
|
|
8286
8205
|
const state = colorState2(w.state).padEnd(stateColumnWidth2());
|
|
8287
8206
|
const peerCallerHead = opts.fullIds ? w.callerDid : didHead5(w.callerDid);
|
|
8288
8207
|
const peerPayeeHead = opts.fullIds ? w.payeeDid : didHead5(w.payeeDid);
|
|
8289
|
-
const direction = w.callerDid === selfDid ? `${
|
|
8208
|
+
const direction = w.callerDid === selfDid ? `${import_chalk36.default.bold("me")} \u2192 ${import_chalk36.default.dim(peerPayeeHead)}` : `${import_chalk36.default.dim(peerCallerHead)} \u2192 ${import_chalk36.default.bold("me")}`;
|
|
8290
8209
|
const outcome = formatOutcome(w);
|
|
8291
8210
|
return `${id} ${state} ${direction} ${outcome}`;
|
|
8292
8211
|
}
|
|
8293
8212
|
function colorState2(s) {
|
|
8294
8213
|
switch (s) {
|
|
8295
|
-
case
|
|
8296
|
-
return
|
|
8297
|
-
case
|
|
8298
|
-
return
|
|
8214
|
+
case import_sdk32.WorkLogStates.REQUESTED:
|
|
8215
|
+
return import_chalk36.default.yellow("requested");
|
|
8216
|
+
case import_sdk32.WorkLogStates.RESPONDED:
|
|
8217
|
+
return import_chalk36.default.green("responded");
|
|
8299
8218
|
}
|
|
8300
8219
|
}
|
|
8301
8220
|
function stateColumnWidth2() {
|
|
8302
8221
|
return 9;
|
|
8303
8222
|
}
|
|
8304
8223
|
function formatOutcome(w) {
|
|
8305
|
-
if (w.state ===
|
|
8306
|
-
if (w.responseError) return
|
|
8307
|
-
if (w.responseOutput) return
|
|
8308
|
-
return
|
|
8224
|
+
if (w.state === import_sdk32.WorkLogStates.REQUESTED) return import_chalk36.default.dim("(in flight)");
|
|
8225
|
+
if (w.responseError) return import_chalk36.default.red(`error ${w.responseError.code}: ${truncate3(w.responseError.message, 32)}`);
|
|
8226
|
+
if (w.responseOutput) return import_chalk36.default.cyan("ok");
|
|
8227
|
+
return import_chalk36.default.dim("(empty response)");
|
|
8309
8228
|
}
|
|
8310
8229
|
function idHead3(id) {
|
|
8311
8230
|
if (id.length <= 12) return id;
|
|
@@ -8412,6 +8331,8 @@ async function main() {
|
|
|
8412
8331
|
registerAssetsCommand(program);
|
|
8413
8332
|
registerEscrowCommands(program);
|
|
8414
8333
|
registerWhoamiCommand(program);
|
|
8334
|
+
registerWhoisCommand(program);
|
|
8335
|
+
registerNameCommand(program);
|
|
8415
8336
|
registerLifecycleCommands(program);
|
|
8416
8337
|
registerSendHandshakeCommand(program);
|
|
8417
8338
|
registerSendHandshakeResponseCommand(program);
|