arc402-cli 0.3.4 → 0.4.1
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/commands/accept.d.ts.map +1 -1
- package/dist/commands/accept.js +17 -7
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/agent-handshake.d.ts.map +1 -1
- package/dist/commands/agent-handshake.js +9 -4
- package/dist/commands/agent-handshake.js.map +1 -1
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +14 -8
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/agreements.d.ts.map +1 -1
- package/dist/commands/agreements.js +51 -26
- package/dist/commands/agreements.js.map +1 -1
- package/dist/commands/arbitrator.d.ts.map +1 -1
- package/dist/commands/arbitrator.js +77 -20
- package/dist/commands/arbitrator.js.map +1 -1
- package/dist/commands/arena-handshake.d.ts.map +1 -1
- package/dist/commands/arena-handshake.js +14 -11
- package/dist/commands/arena-handshake.js.map +1 -1
- package/dist/commands/arena.d.ts.map +1 -1
- package/dist/commands/arena.js +4 -3
- package/dist/commands/arena.js.map +1 -1
- package/dist/commands/cancel.d.ts.map +1 -1
- package/dist/commands/cancel.js +20 -10
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/channel.d.ts.map +1 -1
- package/dist/commands/channel.js +27 -17
- package/dist/commands/channel.js.map +1 -1
- package/dist/commands/coldstart.d.ts.map +1 -1
- package/dist/commands/coldstart.js +33 -22
- package/dist/commands/coldstart.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +34 -17
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +44 -37
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/deliver.d.ts.map +1 -1
- package/dist/commands/deliver.js +16 -3
- package/dist/commands/deliver.js.map +1 -1
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +2 -0
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/dispute.d.ts.map +1 -1
- package/dist/commands/dispute.js +11 -10
- package/dist/commands/dispute.js.map +1 -1
- package/dist/commands/endpoint.d.ts.map +1 -1
- package/dist/commands/endpoint.js +4 -3
- package/dist/commands/endpoint.js.map +1 -1
- package/dist/commands/feed.d.ts.map +1 -1
- package/dist/commands/feed.js.map +1 -1
- package/dist/commands/hire.d.ts.map +1 -1
- package/dist/commands/hire.js +15 -2
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +29 -29
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/negotiate.d.ts.map +1 -1
- package/dist/commands/negotiate.js +8 -7
- package/dist/commands/negotiate.js.map +1 -1
- package/dist/commands/openshell.d.ts.map +1 -1
- package/dist/commands/openshell.js +6 -5
- package/dist/commands/openshell.js.map +1 -1
- package/dist/commands/owner.d.ts.map +1 -1
- package/dist/commands/owner.js +7 -2
- package/dist/commands/owner.js.map +1 -1
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +22 -10
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/relay.d.ts.map +1 -1
- package/dist/commands/relay.js +6 -5
- package/dist/commands/relay.js.map +1 -1
- package/dist/commands/remediate.d.ts.map +1 -1
- package/dist/commands/remediate.js +3 -2
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/reputation.d.ts.map +1 -1
- package/dist/commands/reputation.js +12 -5
- package/dist/commands/reputation.js.map +1 -1
- package/dist/commands/trust.d.ts.map +1 -1
- package/dist/commands/trust.js +16 -1
- package/dist/commands/trust.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +6 -4
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +217 -170
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/watch.d.ts +3 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +23 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/watchtower.d.ts.map +1 -1
- package/dist/commands/watchtower.js +30 -13
- package/dist/commands/watchtower.js.map +1 -1
- package/dist/commands/workroom.d.ts.map +1 -1
- package/dist/commands/workroom.js +123 -95
- package/dist/commands/workroom.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -2
- package/dist/config.js.map +1 -1
- package/dist/index.js +73 -38
- package/dist/index.js.map +1 -1
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +4 -2
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/tree.d.ts +7 -0
- package/dist/ui/tree.d.ts.map +1 -0
- package/dist/ui/tree.js +13 -0
- package/dist/ui/tree.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/accept.ts +19 -10
- package/src/commands/agent-handshake.ts +9 -4
- package/src/commands/agent.ts +15 -6
- package/src/commands/agreements.ts +51 -25
- package/src/commands/arbitrator.ts +71 -20
- package/src/commands/arena-handshake.ts +15 -8
- package/src/commands/arena.ts +4 -3
- package/src/commands/cancel.ts +19 -10
- package/src/commands/channel.ts +27 -17
- package/src/commands/coldstart.ts +29 -20
- package/src/commands/config.ts +34 -17
- package/src/commands/daemon.ts +45 -38
- package/src/commands/deliver.ts +16 -3
- package/src/commands/discover.ts +2 -0
- package/src/commands/dispute.ts +12 -10
- package/src/commands/endpoint.ts +4 -3
- package/src/commands/feed.ts +1 -0
- package/src/commands/hire.ts +17 -2
- package/src/commands/migrate.ts +28 -26
- package/src/commands/negotiate.ts +8 -7
- package/src/commands/openshell.ts +7 -5
- package/src/commands/owner.ts +7 -2
- package/src/commands/policy.ts +21 -10
- package/src/commands/relay.ts +6 -5
- package/src/commands/remediate.ts +4 -2
- package/src/commands/reputation.ts +13 -5
- package/src/commands/trust.ts +13 -1
- package/src/commands/verify.ts +7 -4
- package/src/commands/wallet.ts +218 -170
- package/src/commands/watch.ts +23 -0
- package/src/commands/watchtower.ts +29 -13
- package/src/commands/workroom.ts +121 -95
- package/src/config.ts +16 -2
- package/src/index.ts +43 -3
- package/src/ui/banner.ts +5 -2
- package/src/ui/tree.ts +16 -0
|
@@ -7,6 +7,9 @@ import { getClient } from "../client";
|
|
|
7
7
|
import { agreementStatusLabel, formatDate, printTable, truncateAddress } from "../utils/format";
|
|
8
8
|
import { formatDeadline } from "../utils/time";
|
|
9
9
|
import { hashString } from "../utils/hash";
|
|
10
|
+
import { c } from "../ui/colors";
|
|
11
|
+
import { renderTree } from "../ui/tree";
|
|
12
|
+
import { formatAddress } from "../ui/format";
|
|
10
13
|
|
|
11
14
|
// ─── AgreementTree minimal ABI ────────────────────────────────────────────────
|
|
12
15
|
|
|
@@ -61,11 +64,23 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
61
64
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, provider);
|
|
62
65
|
const agreement = await client.getAgreement(BigInt(id));
|
|
63
66
|
if (opts.json) return console.log(JSON.stringify(agreement, (_k, value) => typeof value === "bigint" ? value.toString() : value, 2));
|
|
64
|
-
console.log(
|
|
67
|
+
console.log('\n ' + c.mark + c.white(` Agreement #${agreement.id}`));
|
|
68
|
+
renderTree([
|
|
69
|
+
{ label: 'Client', value: formatAddress(agreement.client) },
|
|
70
|
+
{ label: 'Provider', value: formatAddress(agreement.provider) },
|
|
71
|
+
{ label: 'Status', value: agreementStatusLabel(agreement.status) },
|
|
72
|
+
{ label: 'Created', value: formatDate(Number(agreement.createdAt)) },
|
|
73
|
+
{ label: 'Deadline', value: formatDate(Number(agreement.deadline)) },
|
|
74
|
+
{ label: 'Verify end', value: Number(agreement.verifyWindowEnd) ? formatDate(Number(agreement.verifyWindowEnd)) : 'n/a' },
|
|
75
|
+
{ label: 'Hash', value: String(agreement.committedHash), last: true },
|
|
76
|
+
]);
|
|
65
77
|
if ([AgreementStatus.REVISION_REQUESTED, AgreementStatus.REVISED, AgreementStatus.PARTIAL_SETTLEMENT, AgreementStatus.ESCALATED_TO_HUMAN, AgreementStatus.DISPUTED, AgreementStatus.ESCALATED_TO_ARBITRATION].includes(agreement.status)) {
|
|
66
78
|
const remediation = await client.getRemediationCase(agreement.id);
|
|
67
79
|
const dispute = await client.getDisputeCase(agreement.id);
|
|
68
|
-
|
|
80
|
+
renderTree([
|
|
81
|
+
{ label: 'Remediation', value: `active=${remediation.active} cycles=${remediation.cycleCount}` },
|
|
82
|
+
{ label: 'Dispute', value: `outcome=${dispute.outcome}`, last: true },
|
|
83
|
+
]);
|
|
69
84
|
}
|
|
70
85
|
});
|
|
71
86
|
|
|
@@ -90,9 +105,12 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
90
105
|
if (opts.json) {
|
|
91
106
|
console.log(JSON.stringify({ txHash: receipt.hash, parentId: opts.parent, childId: opts.child }));
|
|
92
107
|
} else {
|
|
93
|
-
console.log(
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
console.log('\n ' + c.mark + c.white(' Sub-agreement registered'));
|
|
109
|
+
renderTree([
|
|
110
|
+
{ label: 'Parent', value: `#${opts.parent}` },
|
|
111
|
+
{ label: 'Child', value: `#${opts.child}` },
|
|
112
|
+
{ label: 'Tx', value: receipt.hash, last: true },
|
|
113
|
+
]);
|
|
96
114
|
}
|
|
97
115
|
});
|
|
98
116
|
|
|
@@ -130,11 +148,13 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
130
148
|
return;
|
|
131
149
|
}
|
|
132
150
|
|
|
133
|
-
console.log(`Agreement Tree — node #${agreementId}`);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
console.log('\n ' + c.mark + c.white(` Agreement Tree — node #${agreementId}`));
|
|
152
|
+
renderTree([
|
|
153
|
+
{ label: 'Root', value: `#${result.root}` },
|
|
154
|
+
{ label: 'Depth', value: String(result.depth) },
|
|
155
|
+
{ label: 'Path', value: result.path.map((p) => "#" + p).join(" → ") },
|
|
156
|
+
{ label: 'Children', value: result.children.length > 0 ? result.children.map((ch) => "#" + ch).join(", ") : "(none)", last: true },
|
|
157
|
+
]);
|
|
138
158
|
});
|
|
139
159
|
|
|
140
160
|
// ── arc402 agreements-tree-status <id> ───────────────────────────────────────
|
|
@@ -168,10 +188,12 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
168
188
|
return;
|
|
169
189
|
}
|
|
170
190
|
|
|
171
|
-
console.log(`Agreement #${agreementId} tree status
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
191
|
+
console.log('\n ' + c.mark + c.white(` Agreement #${agreementId} — tree status`));
|
|
192
|
+
renderTree([
|
|
193
|
+
{ label: 'Sub-agrmts', value: String(result.childCount) },
|
|
194
|
+
{ label: 'All settled', value: result.allChildrenSettled ? 'YES' : 'NO' },
|
|
195
|
+
{ label: 'Ready', value: result.readyToDeliver ? 'YES — ready to deliver to parent' : 'NO', last: true },
|
|
196
|
+
]);
|
|
175
197
|
});
|
|
176
198
|
|
|
177
199
|
// ── arc402 agreements-create-tree ────────────────────────────────────────────
|
|
@@ -255,7 +277,7 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
255
277
|
const rootDeadline = Number(opts.deadline);
|
|
256
278
|
const rootHash = hashString(opts.task);
|
|
257
279
|
|
|
258
|
-
if (!opts.json) console.log(
|
|
280
|
+
if (!opts.json) console.log('\n ' + c.mark + c.white(` Proposing root agreement to ${opts.provider}...`));
|
|
259
281
|
const rootTx = await saContract.propose(
|
|
260
282
|
opts.provider, opts.serviceType, opts.task,
|
|
261
283
|
rootPrice, ethers.ZeroAddress, rootDeadline, rootHash,
|
|
@@ -274,11 +296,11 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
274
296
|
}
|
|
275
297
|
if (rootAgreementId === undefined) throw new Error("Could not parse root AgreementProposed event");
|
|
276
298
|
|
|
277
|
-
if (!opts.json) console.log(`
|
|
299
|
+
if (!opts.json) console.log(' ' + c.success + c.white(` Root agreement ID: #${rootAgreementId}`));
|
|
278
300
|
|
|
279
301
|
const childAgreementIds: bigint[] = [];
|
|
280
302
|
for (const sub of subSpecs) {
|
|
281
|
-
if (!opts.json) console.log(` Proposing sub-agreement to ${sub.provider}...`);
|
|
303
|
+
if (!opts.json) console.log(' ' + c.dim(` Proposing sub-agreement to ${sub.provider}...`));
|
|
282
304
|
const subHash = hashString(sub.task);
|
|
283
305
|
const subTx = await saContract.propose(
|
|
284
306
|
sub.provider, sub.serviceType, sub.task,
|
|
@@ -294,7 +316,7 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
294
316
|
} catch { /* skip */ }
|
|
295
317
|
}
|
|
296
318
|
if (childId === undefined) throw new Error(`Could not parse AgreementProposed for sub-agreement to ${sub.provider}`);
|
|
297
|
-
if (!opts.json) console.log(`
|
|
319
|
+
if (!opts.json) console.log(' ' + c.success + c.white(` Sub-agreement #${childId} — registering in tree...`));
|
|
298
320
|
await (await treeContract.registerSubAgreement(rootAgreementId, childId)).wait();
|
|
299
321
|
childAgreementIds.push(childId);
|
|
300
322
|
}
|
|
@@ -308,13 +330,17 @@ export function registerAgreementsCommands(program: Command): void {
|
|
|
308
330
|
if (opts.json) {
|
|
309
331
|
console.log(JSON.stringify(result, null, 2));
|
|
310
332
|
} else {
|
|
311
|
-
console.log(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
333
|
+
console.log('\n ' + c.mark + c.white(' Agreement tree created'));
|
|
334
|
+
renderTree([
|
|
335
|
+
{ label: 'Root', value: `#${result.rootAgreementId}` },
|
|
336
|
+
{
|
|
337
|
+
label: 'Children',
|
|
338
|
+
value: result.childAgreementIds.length > 0
|
|
339
|
+
? result.childAgreementIds.map((id) => "#" + id).join(", ")
|
|
340
|
+
: "(none — sub-agreements can be added with agreements-sub-register)",
|
|
341
|
+
last: true,
|
|
342
|
+
},
|
|
343
|
+
]);
|
|
318
344
|
}
|
|
319
345
|
});
|
|
320
346
|
|
|
@@ -2,6 +2,9 @@ import { Command } from "commander";
|
|
|
2
2
|
import { DisputeArbitrationClient } from "@arc402/sdk";
|
|
3
3
|
import { loadConfig } from "../config";
|
|
4
4
|
import { getClient, requireSigner } from "../client";
|
|
5
|
+
import { c } from "../ui/colors";
|
|
6
|
+
import { startSpinner } from "../ui/spinner";
|
|
7
|
+
import { renderTree } from "../ui/tree";
|
|
5
8
|
|
|
6
9
|
export function registerArbitratorCommand(program: Command): void {
|
|
7
10
|
const arbitrator = program
|
|
@@ -23,16 +26,22 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
23
26
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, provider);
|
|
24
27
|
|
|
25
28
|
const eligible = await client.isEligibleArbitrator(arbitratorAddress);
|
|
26
|
-
console.log(
|
|
29
|
+
console.log('\n ' + c.mark + c.white(' Arbitrator status'));
|
|
30
|
+
renderTree([
|
|
31
|
+
{ label: 'Address', value: arbitratorAddress },
|
|
32
|
+
{ label: 'Eligible', value: eligible ? 'yes' : 'no', last: !agreementId },
|
|
33
|
+
]);
|
|
27
34
|
|
|
28
35
|
if (agreementId) {
|
|
29
36
|
const bondState = await client.getArbitratorBondState(arbitratorAddress, BigInt(agreementId));
|
|
30
|
-
console.log(`Bond state
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
console.log('\n ' + c.mark + c.white(` Bond state — agreement #${agreementId}`));
|
|
38
|
+
renderTree([
|
|
39
|
+
{ label: 'Amount', value: `${bondState.bondAmount.toString()} tokens` },
|
|
40
|
+
{ label: 'Locked', value: String(bondState.locked) },
|
|
41
|
+
{ label: 'Slashed', value: String(bondState.slashed) },
|
|
42
|
+
{ label: 'Returned', value: String(bondState.returned) },
|
|
43
|
+
{ label: 'Locked at', value: new Date(Number(bondState.lockedAt) * 1000).toISOString(), last: true },
|
|
44
|
+
]);
|
|
36
45
|
}
|
|
37
46
|
});
|
|
38
47
|
|
|
@@ -48,11 +57,18 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
48
57
|
|
|
49
58
|
const bondAmount = BigInt(opts.bond);
|
|
50
59
|
if (bondAmount === 0n) {
|
|
51
|
-
console.warn(
|
|
60
|
+
console.warn(' ' + c.warning + c.white(' Bond amount is 0. For ERC-20 agreements, pre-approve the DisputeArbitration contract.'));
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
64
|
+
try {
|
|
65
|
+
await client.acceptAssignment(BigInt(agreementId), bondAmount);
|
|
66
|
+
spinner.succeed();
|
|
67
|
+
} catch (err) {
|
|
68
|
+
spinner.fail();
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
console.log(' ' + c.success + c.white(` Assignment accepted — agreement #${agreementId}`));
|
|
56
72
|
});
|
|
57
73
|
|
|
58
74
|
bond
|
|
@@ -63,8 +79,15 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
63
79
|
if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
|
|
64
80
|
const { signer } = await requireSigner(config);
|
|
65
81
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
83
|
+
try {
|
|
84
|
+
await client.triggerFallback(BigInt(agreementId));
|
|
85
|
+
spinner.succeed();
|
|
86
|
+
} catch (err) {
|
|
87
|
+
spinner.fail();
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
console.log(' ' + c.success + c.white(` Fallback triggered — agreement #${agreementId}`));
|
|
68
91
|
});
|
|
69
92
|
|
|
70
93
|
// Rate subcommands — nest under 'rate'
|
|
@@ -82,8 +105,15 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
82
105
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
|
|
83
106
|
|
|
84
107
|
const rateVal = BigInt(usdPerToken);
|
|
85
|
-
|
|
86
|
-
|
|
108
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
109
|
+
try {
|
|
110
|
+
await client.setTokenUsdRate(tokenAddress, rateVal);
|
|
111
|
+
spinner.succeed();
|
|
112
|
+
} catch (err) {
|
|
113
|
+
spinner.fail();
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
console.log(' ' + c.success + c.white(` Token rate set: ${tokenAddress} = ${rateVal.toString()} USD/token`));
|
|
87
117
|
});
|
|
88
118
|
|
|
89
119
|
// Admin: slash arbitrator (manual rules violation)
|
|
@@ -95,8 +125,15 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
95
125
|
if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
|
|
96
126
|
const { signer } = await requireSigner(config);
|
|
97
127
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
129
|
+
try {
|
|
130
|
+
await client.slashArbitrator(BigInt(agreementId), arbitratorAddress, reason);
|
|
131
|
+
spinner.succeed();
|
|
132
|
+
} catch (err) {
|
|
133
|
+
spinner.fail();
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
console.log(' ' + c.success + c.white(` Slashed ${arbitratorAddress}`));
|
|
100
137
|
});
|
|
101
138
|
|
|
102
139
|
arbitrator
|
|
@@ -107,8 +144,15 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
107
144
|
if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
|
|
108
145
|
const { signer } = await requireSigner(config);
|
|
109
146
|
const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
|
|
110
|
-
|
|
111
|
-
|
|
147
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
148
|
+
try {
|
|
149
|
+
await client.reclaimExpiredBond(BigInt(agreementId));
|
|
150
|
+
spinner.succeed();
|
|
151
|
+
} catch (err) {
|
|
152
|
+
spinner.fail();
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
console.log(' ' + c.success + c.white(` Bond reclaimed — agreement #${agreementId}`));
|
|
112
156
|
});
|
|
113
157
|
|
|
114
158
|
arbitrator
|
|
@@ -123,7 +167,14 @@ export function registerArbitratorCommand(program: Command): void {
|
|
|
123
167
|
if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
|
|
124
168
|
const { signer } = await requireSigner(config);
|
|
125
169
|
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
126
|
-
|
|
127
|
-
|
|
170
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
171
|
+
try {
|
|
172
|
+
await client.resolveFromArbitration(BigInt(agreementId), opts.recipient, BigInt(opts.providerAmount), BigInt(opts.clientAmount));
|
|
173
|
+
spinner.succeed();
|
|
174
|
+
} catch (err) {
|
|
175
|
+
spinner.fail();
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
console.log(' ' + c.success + c.white(` Resolved from arbitration — agreement #${agreementId}`));
|
|
128
179
|
});
|
|
129
180
|
}
|
|
@@ -3,6 +3,9 @@ import { ethers } from "ethers";
|
|
|
3
3
|
import { loadConfig, getUsdcAddress } from "../config";
|
|
4
4
|
import { requireSigner } from "../client";
|
|
5
5
|
import { AGENT_REGISTRY_ABI } from "../abis";
|
|
6
|
+
import { startSpinner } from "../ui/spinner";
|
|
7
|
+
import { renderTree } from "../ui/tree";
|
|
8
|
+
import { c } from "../ui/colors";
|
|
6
9
|
|
|
7
10
|
const DEFAULT_REGISTRY_ADDRESS = "0xD5c2851B00090c92Ba7F4723FB548bb30C9B6865";
|
|
8
11
|
|
|
@@ -122,6 +125,7 @@ export function registerArenaHandshakeCommands(program: Command): void {
|
|
|
122
125
|
|
|
123
126
|
const handshake = new ethers.Contract(config.handshakeAddress, HANDSHAKE_ABI, signer);
|
|
124
127
|
|
|
128
|
+
const hsSpinner = startSpinner(`Sending ${opts.type} handshake...`);
|
|
125
129
|
let tx;
|
|
126
130
|
if (opts.usdc) {
|
|
127
131
|
// USDC handshake
|
|
@@ -133,6 +137,7 @@ export function registerArenaHandshakeCommands(program: Command): void {
|
|
|
133
137
|
const value = opts.tip ? ethers.parseEther(opts.tip) : 0n;
|
|
134
138
|
tx = await handshake.sendHandshake(agentAddress, hsType, opts.note, { value });
|
|
135
139
|
}
|
|
140
|
+
hsSpinner.succeed("Handshake sent");
|
|
136
141
|
|
|
137
142
|
// Notify recipient's HTTP endpoint (non-blocking)
|
|
138
143
|
const registryAddress = config.agentRegistryV2Address ?? config.agentRegistryAddress ?? DEFAULT_REGISTRY_ADDRESS;
|
|
@@ -150,14 +155,16 @@ export function registerArenaHandshakeCommands(program: Command): void {
|
|
|
150
155
|
if (opts.json) {
|
|
151
156
|
console.log(JSON.stringify({ tx: tx.hash, from: myAddress, to: agentAddress, type: opts.type, note: opts.note }));
|
|
152
157
|
} else {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
const treeItems = [
|
|
159
|
+
{ label: "From", value: myAddress },
|
|
160
|
+
{ label: "To", value: agentAddress },
|
|
161
|
+
{ label: "Type", value: opts.type },
|
|
162
|
+
...(opts.note ? [{ label: "Note", value: opts.note as string }] : []),
|
|
163
|
+
...(opts.tip ? [{ label: "Tip", value: `${opts.tip as string} ETH` }] : []),
|
|
164
|
+
...(opts.usdc ? [{ label: "Tip", value: `${opts.usdc as string} USDC` }] : []),
|
|
165
|
+
{ label: "Tx", value: tx.hash as string, last: true },
|
|
166
|
+
];
|
|
167
|
+
renderTree(treeItems);
|
|
161
168
|
}
|
|
162
169
|
});
|
|
163
170
|
|
package/src/commands/arena.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { runFeed, FeedOptions } from "./feed";
|
|
4
|
+
import { c } from "../ui/colors";
|
|
4
5
|
|
|
5
6
|
const SUBGRAPH_URL = "https://api.studio.thegraph.com/query/1744310/arc-402/v0.2.0";
|
|
6
7
|
|
|
@@ -45,7 +46,7 @@ export function registerArenaCommands(program: Command): void {
|
|
|
45
46
|
if (opts.json) {
|
|
46
47
|
console.log(JSON.stringify({ error: msg }));
|
|
47
48
|
} else {
|
|
48
|
-
console.error(
|
|
49
|
+
console.error(' ' + c.warning + c.white(` ${msg}`));
|
|
49
50
|
}
|
|
50
51
|
process.exit(1);
|
|
51
52
|
}
|
|
@@ -90,7 +91,7 @@ export function registerArenaCommands(program: Command): void {
|
|
|
90
91
|
if (opts.json) {
|
|
91
92
|
console.log(JSON.stringify({ error: "Subgraph unavailable", details: msg }));
|
|
92
93
|
} else {
|
|
93
|
-
console.error(
|
|
94
|
+
console.error(' ' + c.failure + c.white(` Subgraph unavailable: ${msg}`));
|
|
94
95
|
}
|
|
95
96
|
process.exit(1);
|
|
96
97
|
}
|
|
@@ -113,7 +114,7 @@ export function registerArenaCommands(program: Command): void {
|
|
|
113
114
|
if ((opts as FeedOptions).json) {
|
|
114
115
|
console.log(JSON.stringify({ error: "Subgraph unavailable", details: msg }));
|
|
115
116
|
} else {
|
|
116
|
-
console.error(
|
|
117
|
+
console.error(' ' + c.failure + c.white(` Subgraph unavailable: ${msg}`));
|
|
117
118
|
}
|
|
118
119
|
process.exit(1);
|
|
119
120
|
}
|
package/src/commands/cancel.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { loadConfig } from "../config";
|
|
|
4
4
|
import { requireSigner } from "../client";
|
|
5
5
|
import { printSenderInfo, executeContractWriteViaWallet } from "../wallet-router";
|
|
6
6
|
import { SERVICE_AGREEMENT_ABI } from "../abis";
|
|
7
|
+
import { c } from "../ui/colors";
|
|
8
|
+
import { startSpinner } from "../ui/spinner";
|
|
7
9
|
|
|
8
10
|
export function registerCancelCommand(program: Command): void {
|
|
9
11
|
program.command("cancel <id>").description("Cancel a proposed agreement; use --expired for post-deadline recovery paths").option("--expired", "Call expiredCancel()", false).action(async (id, opts) => {
|
|
@@ -11,16 +13,23 @@ export function registerCancelCommand(program: Command): void {
|
|
|
11
13
|
if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
|
|
12
14
|
const { signer } = await requireSigner(config);
|
|
13
15
|
printSenderInfo(config);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
const spinner = startSpinner("Submitting transaction...");
|
|
17
|
+
try {
|
|
18
|
+
if (config.walletContractAddress) {
|
|
19
|
+
const fn = opts.expired ? "expiredCancel" : "cancel";
|
|
20
|
+
await executeContractWriteViaWallet(
|
|
21
|
+
config.walletContractAddress, signer, config.serviceAgreementAddress,
|
|
22
|
+
SERVICE_AGREEMENT_ABI, fn, [BigInt(id)],
|
|
23
|
+
);
|
|
24
|
+
} else {
|
|
25
|
+
const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
|
|
26
|
+
if (opts.expired) await client.expiredCancel(BigInt(id)); else await client.cancel(BigInt(id));
|
|
27
|
+
}
|
|
28
|
+
spinner.succeed();
|
|
29
|
+
} catch (err) {
|
|
30
|
+
spinner.fail();
|
|
31
|
+
throw err;
|
|
23
32
|
}
|
|
24
|
-
console.log(`
|
|
33
|
+
console.log(' ' + c.success + c.white(` Cancelled — agreement #${id}`));
|
|
25
34
|
});
|
|
26
35
|
}
|
package/src/commands/channel.ts
CHANGED
|
@@ -6,6 +6,10 @@ import type { ChannelState } from "@arc402/sdk";
|
|
|
6
6
|
import * as fs from "fs";
|
|
7
7
|
import * as path from "path";
|
|
8
8
|
import * as os from "os";
|
|
9
|
+
import { c } from '../ui/colors';
|
|
10
|
+
import { startSpinner } from '../ui/spinner';
|
|
11
|
+
import { renderTree } from '../ui/tree';
|
|
12
|
+
import { formatAddress } from '../ui/format';
|
|
9
13
|
|
|
10
14
|
const CHANNEL_STATES_DIR = path.join(os.homedir(), ".arc402", "channel-states");
|
|
11
15
|
|
|
@@ -33,6 +37,7 @@ export function registerChannelCommands(program: Command): void {
|
|
|
33
37
|
if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
|
|
34
38
|
const { signer } = await requireSigner(config);
|
|
35
39
|
const client = new ChannelClient(config.serviceAgreementAddress, signer);
|
|
40
|
+
const spinner = startSpinner('Opening session channel…');
|
|
36
41
|
const result = await client.openSessionChannel(
|
|
37
42
|
provider,
|
|
38
43
|
opts.token,
|
|
@@ -41,10 +46,14 @@ export function registerChannelCommands(program: Command): void {
|
|
|
41
46
|
Number(opts.deadline)
|
|
42
47
|
);
|
|
43
48
|
if (opts.json || program.opts().json) {
|
|
49
|
+
spinner.stop();
|
|
44
50
|
console.log(JSON.stringify(result, null, 2));
|
|
45
51
|
} else {
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
spinner.succeed(' Opened — channel ' + result.channelId);
|
|
53
|
+
renderTree([
|
|
54
|
+
{ label: 'Channel', value: result.channelId },
|
|
55
|
+
{ label: 'Tx', value: result.txHash, last: true },
|
|
56
|
+
]);
|
|
48
57
|
}
|
|
49
58
|
});
|
|
50
59
|
|
|
@@ -60,14 +69,15 @@ export function registerChannelCommands(program: Command): void {
|
|
|
60
69
|
if (opts.json || program.opts().json) {
|
|
61
70
|
console.log(JSON.stringify(ch, (_k, v) => typeof v === "bigint" ? v.toString() : v, 2));
|
|
62
71
|
} else {
|
|
63
|
-
console.log(`
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
console.log('\n ' + c.mark + c.white(` Channel ${channelId}`));
|
|
73
|
+
renderTree([
|
|
74
|
+
{ label: 'Status', value: ch.status },
|
|
75
|
+
{ label: 'Client', value: formatAddress(ch.client) },
|
|
76
|
+
{ label: 'Provider', value: formatAddress(ch.provider) },
|
|
77
|
+
{ label: 'Deposit', value: ch.depositAmount.toString() },
|
|
78
|
+
{ label: 'Settled', value: ch.settledAmount.toString() },
|
|
79
|
+
{ label: 'Seq', value: ch.lastSequenceNumber.toString(), last: true },
|
|
80
|
+
]);
|
|
71
81
|
}
|
|
72
82
|
});
|
|
73
83
|
|
|
@@ -107,8 +117,8 @@ export function registerChannelCommands(program: Command): void {
|
|
|
107
117
|
if (opts.json || program.opts().json) {
|
|
108
118
|
console.log(JSON.stringify(result, null, 2));
|
|
109
119
|
} else {
|
|
110
|
-
console.log(`
|
|
111
|
-
console.log(
|
|
120
|
+
console.log(' ' + c.success + c.white(` Close submitted — ${result.txHash}`));
|
|
121
|
+
console.log(' ' + c.dim('Challenge window open (24h)'));
|
|
112
122
|
}
|
|
113
123
|
});
|
|
114
124
|
|
|
@@ -126,7 +136,7 @@ export function registerChannelCommands(program: Command): void {
|
|
|
126
136
|
if (opts.json || program.opts().json) {
|
|
127
137
|
console.log(JSON.stringify(result, null, 2));
|
|
128
138
|
} else {
|
|
129
|
-
console.log(`
|
|
139
|
+
console.log(' ' + c.success + c.white(` Challenge submitted — ${result.txHash}`));
|
|
130
140
|
}
|
|
131
141
|
});
|
|
132
142
|
|
|
@@ -142,7 +152,7 @@ export function registerChannelCommands(program: Command): void {
|
|
|
142
152
|
if (opts.json || program.opts().json) {
|
|
143
153
|
console.log(JSON.stringify(result, null, 2));
|
|
144
154
|
} else {
|
|
145
|
-
console.log(`
|
|
155
|
+
console.log(' ' + c.success + c.white(` Finalised — ${result.txHash}`));
|
|
146
156
|
}
|
|
147
157
|
});
|
|
148
158
|
|
|
@@ -158,7 +168,7 @@ export function registerChannelCommands(program: Command): void {
|
|
|
158
168
|
if (opts.json || program.opts().json) {
|
|
159
169
|
console.log(JSON.stringify(result, null, 2));
|
|
160
170
|
} else {
|
|
161
|
-
console.log(`
|
|
171
|
+
console.log(' ' + c.success + c.white(` Reclaimed — ${result.txHash}`));
|
|
162
172
|
}
|
|
163
173
|
});
|
|
164
174
|
|
|
@@ -201,8 +211,8 @@ export function registerChannelCommands(program: Command): void {
|
|
|
201
211
|
if (opts.json || program.opts().json) {
|
|
202
212
|
console.log(JSON.stringify({ stored: true, channelId, path: dest }));
|
|
203
213
|
} else {
|
|
204
|
-
console.log(`State stored
|
|
205
|
-
console.log(`
|
|
214
|
+
console.log(' ' + c.success + c.white(` State stored — ${dest}`));
|
|
215
|
+
console.log(' ' + c.dim(`seq: ${state.sequenceNumber}`));
|
|
206
216
|
}
|
|
207
217
|
});
|
|
208
218
|
}
|
|
@@ -2,6 +2,9 @@ import { Command } from "commander";
|
|
|
2
2
|
import { ethers } from "ethers";
|
|
3
3
|
import { loadConfig } from "../config";
|
|
4
4
|
import { getClient, requireSigner } from "../client";
|
|
5
|
+
import { c } from '../ui/colors';
|
|
6
|
+
import { startSpinner } from '../ui/spinner';
|
|
7
|
+
import { renderTree } from '../ui/tree';
|
|
5
8
|
|
|
6
9
|
const VOUCHING_REGISTRY_ABI = [
|
|
7
10
|
"function vouch(address newAgent, uint256 stakeAmount) external payable",
|
|
@@ -42,6 +45,7 @@ export function registerColdStartCommands(program: Command): void {
|
|
|
42
45
|
const stakeAmount = opts.stake ? BigInt(opts.stake) : 0n;
|
|
43
46
|
const contract = new ethers.Contract(config.vouchingRegistryAddress, VOUCHING_REGISTRY_ABI, signer);
|
|
44
47
|
|
|
48
|
+
const spinner = startSpinner(`Vouching for ${address}…`);
|
|
45
49
|
const tx = await contract.vouch(address, stakeAmount);
|
|
46
50
|
const receipt = await tx.wait();
|
|
47
51
|
|
|
@@ -53,11 +57,14 @@ export function registerColdStartCommands(program: Command): void {
|
|
|
53
57
|
boostGranted: boost.toString(),
|
|
54
58
|
txHash: receipt.hash,
|
|
55
59
|
};
|
|
56
|
-
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
if (opts.json) { spinner.stop(); return console.log(JSON.stringify(payload, null, 2)); }
|
|
61
|
+
spinner.succeed(` Vouched — ${address}`);
|
|
62
|
+
renderTree([
|
|
63
|
+
{ label: 'New Agent', value: address },
|
|
64
|
+
{ label: 'Stake', value: stakeAmount > 0n ? `${ethers.formatEther(stakeAmount)} ETH` : '0' },
|
|
65
|
+
{ label: 'Boost', value: `+${boost} trust points` },
|
|
66
|
+
{ label: 'Tx', value: receipt.hash, last: true },
|
|
67
|
+
]);
|
|
61
68
|
});
|
|
62
69
|
|
|
63
70
|
// ─── bond ──────────────────────────────────────────────────────────────────
|
|
@@ -88,14 +95,18 @@ export function registerColdStartCommands(program: Command): void {
|
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
const amount = opts.amount ? BigInt(opts.amount) : BOND_DEFAULT_AMOUNT;
|
|
98
|
+
const bondSpinner = startSpinner('Posting bond…');
|
|
91
99
|
const tx = await contract.postBond({ value: amount });
|
|
92
100
|
const receipt = await tx.wait();
|
|
93
101
|
|
|
94
102
|
const payload = { bonded: true, amount: amount.toString(), txHash: receipt.hash };
|
|
95
|
-
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
if (opts.json) { bondSpinner.stop(); return console.log(JSON.stringify(payload, null, 2)); }
|
|
104
|
+
bondSpinner.succeed(` Bond posted — ${ethers.formatEther(amount)} ETH`);
|
|
105
|
+
renderTree([
|
|
106
|
+
{ label: 'Amount', value: `${ethers.formatEther(amount)} ETH` },
|
|
107
|
+
{ label: 'Tx', value: receipt.hash },
|
|
108
|
+
{ label: 'Note', value: 'Claimable after 90 days of clean operation', last: true },
|
|
109
|
+
]);
|
|
99
110
|
});
|
|
100
111
|
|
|
101
112
|
// arc402 bond status <address>
|
|
@@ -121,8 +132,8 @@ export function registerColdStartCommands(program: Command): void {
|
|
|
121
132
|
} catch {
|
|
122
133
|
const payload = { address, bonded: false };
|
|
123
134
|
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
124
|
-
console.log(`
|
|
125
|
-
|
|
135
|
+
console.log('\n ' + c.mark + c.white(` Bond Status — ${address}`));
|
|
136
|
+
renderTree([{ label: 'Status', value: 'No active bond', last: true }]);
|
|
126
137
|
return;
|
|
127
138
|
}
|
|
128
139
|
|
|
@@ -140,17 +151,15 @@ export function registerColdStartCommands(program: Command): void {
|
|
|
140
151
|
daysRemaining,
|
|
141
152
|
};
|
|
142
153
|
if (opts.json) return console.log(JSON.stringify(payload, null, 2));
|
|
143
|
-
console.log(`
|
|
154
|
+
console.log('\n ' + c.mark + c.white(` Bond Status — ${address}`));
|
|
144
155
|
if (!active) {
|
|
145
|
-
|
|
156
|
+
renderTree([{ label: 'Status', value: 'No active bond', last: true }]);
|
|
146
157
|
return;
|
|
147
158
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
console.log(` claimable: now`);
|
|
154
|
-
}
|
|
159
|
+
renderTree([
|
|
160
|
+
{ label: 'Amount', value: `${ethers.formatEther(amount)} ETH` },
|
|
161
|
+
{ label: 'Posted', value: new Date(Number(postedAt) * 1000).toISOString() },
|
|
162
|
+
{ label: 'Claimable', value: daysRemaining > 0 ? `in ${daysRemaining} days` : 'now', last: true },
|
|
163
|
+
]);
|
|
155
164
|
});
|
|
156
165
|
}
|