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.
Files changed (145) hide show
  1. package/dist/commands/accept.d.ts.map +1 -1
  2. package/dist/commands/accept.js +17 -7
  3. package/dist/commands/accept.js.map +1 -1
  4. package/dist/commands/agent-handshake.d.ts.map +1 -1
  5. package/dist/commands/agent-handshake.js +9 -4
  6. package/dist/commands/agent-handshake.js.map +1 -1
  7. package/dist/commands/agent.d.ts.map +1 -1
  8. package/dist/commands/agent.js +14 -8
  9. package/dist/commands/agent.js.map +1 -1
  10. package/dist/commands/agreements.d.ts.map +1 -1
  11. package/dist/commands/agreements.js +51 -26
  12. package/dist/commands/agreements.js.map +1 -1
  13. package/dist/commands/arbitrator.d.ts.map +1 -1
  14. package/dist/commands/arbitrator.js +77 -20
  15. package/dist/commands/arbitrator.js.map +1 -1
  16. package/dist/commands/arena-handshake.d.ts.map +1 -1
  17. package/dist/commands/arena-handshake.js +14 -11
  18. package/dist/commands/arena-handshake.js.map +1 -1
  19. package/dist/commands/arena.d.ts.map +1 -1
  20. package/dist/commands/arena.js +4 -3
  21. package/dist/commands/arena.js.map +1 -1
  22. package/dist/commands/cancel.d.ts.map +1 -1
  23. package/dist/commands/cancel.js +20 -10
  24. package/dist/commands/cancel.js.map +1 -1
  25. package/dist/commands/channel.d.ts.map +1 -1
  26. package/dist/commands/channel.js +27 -17
  27. package/dist/commands/channel.js.map +1 -1
  28. package/dist/commands/coldstart.d.ts.map +1 -1
  29. package/dist/commands/coldstart.js +33 -22
  30. package/dist/commands/coldstart.js.map +1 -1
  31. package/dist/commands/config.d.ts.map +1 -1
  32. package/dist/commands/config.js +34 -17
  33. package/dist/commands/config.js.map +1 -1
  34. package/dist/commands/daemon.d.ts.map +1 -1
  35. package/dist/commands/daemon.js +44 -37
  36. package/dist/commands/daemon.js.map +1 -1
  37. package/dist/commands/deliver.d.ts.map +1 -1
  38. package/dist/commands/deliver.js +16 -3
  39. package/dist/commands/deliver.js.map +1 -1
  40. package/dist/commands/discover.d.ts.map +1 -1
  41. package/dist/commands/discover.js +2 -0
  42. package/dist/commands/discover.js.map +1 -1
  43. package/dist/commands/dispute.d.ts.map +1 -1
  44. package/dist/commands/dispute.js +11 -10
  45. package/dist/commands/dispute.js.map +1 -1
  46. package/dist/commands/endpoint.d.ts.map +1 -1
  47. package/dist/commands/endpoint.js +4 -3
  48. package/dist/commands/endpoint.js.map +1 -1
  49. package/dist/commands/feed.d.ts.map +1 -1
  50. package/dist/commands/feed.js.map +1 -1
  51. package/dist/commands/hire.d.ts.map +1 -1
  52. package/dist/commands/hire.js +15 -2
  53. package/dist/commands/hire.js.map +1 -1
  54. package/dist/commands/migrate.d.ts.map +1 -1
  55. package/dist/commands/migrate.js +29 -29
  56. package/dist/commands/migrate.js.map +1 -1
  57. package/dist/commands/negotiate.d.ts.map +1 -1
  58. package/dist/commands/negotiate.js +8 -7
  59. package/dist/commands/negotiate.js.map +1 -1
  60. package/dist/commands/openshell.d.ts.map +1 -1
  61. package/dist/commands/openshell.js +6 -5
  62. package/dist/commands/openshell.js.map +1 -1
  63. package/dist/commands/owner.d.ts.map +1 -1
  64. package/dist/commands/owner.js +7 -2
  65. package/dist/commands/owner.js.map +1 -1
  66. package/dist/commands/policy.d.ts.map +1 -1
  67. package/dist/commands/policy.js +22 -10
  68. package/dist/commands/policy.js.map +1 -1
  69. package/dist/commands/relay.d.ts.map +1 -1
  70. package/dist/commands/relay.js +6 -5
  71. package/dist/commands/relay.js.map +1 -1
  72. package/dist/commands/remediate.d.ts.map +1 -1
  73. package/dist/commands/remediate.js +3 -2
  74. package/dist/commands/remediate.js.map +1 -1
  75. package/dist/commands/reputation.d.ts.map +1 -1
  76. package/dist/commands/reputation.js +12 -5
  77. package/dist/commands/reputation.js.map +1 -1
  78. package/dist/commands/trust.d.ts.map +1 -1
  79. package/dist/commands/trust.js +16 -1
  80. package/dist/commands/trust.js.map +1 -1
  81. package/dist/commands/verify.d.ts.map +1 -1
  82. package/dist/commands/verify.js +6 -4
  83. package/dist/commands/verify.js.map +1 -1
  84. package/dist/commands/wallet.d.ts.map +1 -1
  85. package/dist/commands/wallet.js +217 -170
  86. package/dist/commands/wallet.js.map +1 -1
  87. package/dist/commands/watch.d.ts +3 -0
  88. package/dist/commands/watch.d.ts.map +1 -0
  89. package/dist/commands/watch.js +23 -0
  90. package/dist/commands/watch.js.map +1 -0
  91. package/dist/commands/watchtower.d.ts.map +1 -1
  92. package/dist/commands/watchtower.js +30 -13
  93. package/dist/commands/watchtower.js.map +1 -1
  94. package/dist/commands/workroom.d.ts.map +1 -1
  95. package/dist/commands/workroom.js +123 -95
  96. package/dist/commands/workroom.js.map +1 -1
  97. package/dist/config.d.ts.map +1 -1
  98. package/dist/config.js +16 -2
  99. package/dist/config.js.map +1 -1
  100. package/dist/index.js +73 -38
  101. package/dist/index.js.map +1 -1
  102. package/dist/ui/banner.d.ts.map +1 -1
  103. package/dist/ui/banner.js +4 -2
  104. package/dist/ui/banner.js.map +1 -1
  105. package/dist/ui/tree.d.ts +7 -0
  106. package/dist/ui/tree.d.ts.map +1 -0
  107. package/dist/ui/tree.js +13 -0
  108. package/dist/ui/tree.js.map +1 -0
  109. package/package.json +1 -1
  110. package/src/commands/accept.ts +19 -10
  111. package/src/commands/agent-handshake.ts +9 -4
  112. package/src/commands/agent.ts +15 -6
  113. package/src/commands/agreements.ts +51 -25
  114. package/src/commands/arbitrator.ts +71 -20
  115. package/src/commands/arena-handshake.ts +15 -8
  116. package/src/commands/arena.ts +4 -3
  117. package/src/commands/cancel.ts +19 -10
  118. package/src/commands/channel.ts +27 -17
  119. package/src/commands/coldstart.ts +29 -20
  120. package/src/commands/config.ts +34 -17
  121. package/src/commands/daemon.ts +45 -38
  122. package/src/commands/deliver.ts +16 -3
  123. package/src/commands/discover.ts +2 -0
  124. package/src/commands/dispute.ts +12 -10
  125. package/src/commands/endpoint.ts +4 -3
  126. package/src/commands/feed.ts +1 -0
  127. package/src/commands/hire.ts +17 -2
  128. package/src/commands/migrate.ts +28 -26
  129. package/src/commands/negotiate.ts +8 -7
  130. package/src/commands/openshell.ts +7 -5
  131. package/src/commands/owner.ts +7 -2
  132. package/src/commands/policy.ts +21 -10
  133. package/src/commands/relay.ts +6 -5
  134. package/src/commands/remediate.ts +4 -2
  135. package/src/commands/reputation.ts +13 -5
  136. package/src/commands/trust.ts +13 -1
  137. package/src/commands/verify.ts +7 -4
  138. package/src/commands/wallet.ts +218 -170
  139. package/src/commands/watch.ts +23 -0
  140. package/src/commands/watchtower.ts +29 -13
  141. package/src/commands/workroom.ts +121 -95
  142. package/src/config.ts +16 -2
  143. package/src/index.ts +43 -3
  144. package/src/ui/banner.ts +5 -2
  145. package/src/ui/tree.ts +16 -0
@@ -3,6 +3,8 @@ import * as fs from "fs";
3
3
  import * as path from "path";
4
4
  import * as os from "os";
5
5
  import * as YAML from "yaml";
6
+ import { c } from '../ui/colors';
7
+ import { startSpinner } from '../ui/spinner';
6
8
  import {
7
9
  ARC402_DIR,
8
10
  DEFAULT_RUNTIME_REMOTE_ROOT,
@@ -757,7 +759,7 @@ If you update the local CLI build and want the sandbox to pick it up immediately
757
759
  synced_at: new Date().toISOString(),
758
760
  },
759
761
  });
760
- console.log(`✓ Runtime synced to ${provisioned.remoteRoot}`);
762
+ console.log(' ' + c.success + c.white(` Runtime synced to ${provisioned.remoteRoot}`));
761
763
  } catch (err) {
762
764
  console.error(`Runtime sync failed: ${err instanceof Error ? err.message : String(err)}`);
763
765
  process.exit(1);
@@ -972,7 +974,7 @@ If you update the local CLI build and want the sandbox to pick it up immediately
972
974
  const key = peerPolicyKey(cleanedHost);
973
975
  const result = ensurePolicyEntry(policy, key, buildPolicyEntry(`peer-agent:${cleanedHost}`, cleanedHost));
974
976
  applyAndPersistPolicy(policy);
975
- console.log(`✓ Peer agent host ${cleanedHost} ${result} under ${key}`);
977
+ console.log(' ' + c.success + c.white(` Peer agent host ${cleanedHost} ${result} under ${key}`));
976
978
  console.log(" This only affects sandbox outbound access. It does not claim or expose a public endpoint.");
977
979
  });
978
980
 
@@ -989,7 +991,7 @@ If you update the local CLI build and want the sandbox to pick it up immediately
989
991
  process.exit(1);
990
992
  }
991
993
  applyAndPersistPolicy(policy);
992
- console.log(`✓ Peer agent host ${cleanedHost} removed (${key})`);
994
+ console.log(' ' + c.success + c.white(` Peer agent host ${cleanedHost} removed (${key})`));
993
995
  });
994
996
 
995
997
  peerCmd
@@ -1018,7 +1020,7 @@ If you update the local CLI build and want the sandbox to pick it up immediately
1018
1020
  const key = customPolicyKey(name);
1019
1021
  const result = ensurePolicyEntry(policy, key, buildPolicyEntry(name, host, [...NODE_BINARIES, ...PYTHON_BINARIES]));
1020
1022
  applyAndPersistPolicy(policy);
1021
- console.log(`✓ ${host} ${result} as ${key}`);
1023
+ console.log(' ' + c.success + c.white(` ${host} ${result} as ${key}`));
1022
1024
  console.log(" Prefer `arc402 openshell policy peer add <host>` for peer agents or `preset <name>` for launch-safe expansion packs.");
1023
1025
  });
1024
1026
 
@@ -1048,6 +1050,6 @@ If you update the local CLI build and want the sandbox to pick it up immediately
1048
1050
  delete policy.network_policies[key];
1049
1051
 
1050
1052
  applyAndPersistPolicy(policy);
1051
- console.log(`✓ ${removedHost} removed from daemon sandbox policy (hot-reloaded)`);
1053
+ console.log(' ' + c.success + c.white(` ${removedHost} removed from daemon sandbox policy (hot-reloaded)`));
1052
1054
  });
1053
1055
  }
@@ -2,6 +2,9 @@ import { Command } from "commander";
2
2
  import { DisputeArbitrationClient } from "@arc402/sdk";
3
3
  import { loadConfig } from "../config";
4
4
  import { requireSigner } from "../client";
5
+ import { c } from '../ui/colors';
6
+ import { startSpinner } from '../ui/spinner';
7
+ import { formatAddress } from '../ui/format';
5
8
 
6
9
  export function registerOwnerCommands(program: Command): void {
7
10
  const owner = program.command("owner").description("Protocol ownership management (DisputeArbitration two-step transfer)");
@@ -13,8 +16,9 @@ export function registerOwnerCommands(program: Command): void {
13
16
  if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
14
17
  const { signer } = await requireSigner(config);
15
18
  const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
19
+ const spinner = startSpinner('Proposing ownership transfer…');
16
20
  await client.proposeOwner(newOwner);
17
- console.log(`ownership transfer proposed to ${newOwner} new owner must call: arc402 owner accept-transfer`);
21
+ spinner.succeed(c.success + c.white(' Ownership transfer proposed to ' + formatAddress(newOwner)));
18
22
  });
19
23
 
20
24
  owner.command("accept-transfer")
@@ -24,7 +28,8 @@ export function registerOwnerCommands(program: Command): void {
24
28
  if (!config.disputeArbitrationAddress) throw new Error("disputeArbitrationAddress missing in config");
25
29
  const { signer } = await requireSigner(config);
26
30
  const client = new DisputeArbitrationClient(config.disputeArbitrationAddress, signer);
31
+ const spinner = startSpinner('Accepting ownership…');
27
32
  await client.acceptOwnership();
28
- console.log("ownership transfer accepted you are now the owner of DisputeArbitration");
33
+ spinner.succeed(c.success + c.white(' Ownership accepted'));
29
34
  });
30
35
  }
@@ -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 { formatAddress } from '../ui/format';
5
8
 
6
9
  const POLICY_ENGINE_EXTENDED_ABI = [
7
10
  "function addToBlocklist(address wallet, address provider) external",
@@ -42,11 +45,11 @@ blocklist
42
45
  const already = await contract.isBlocked(wallet, address);
43
46
  if (already) {
44
47
  if (opts.json) return console.log(JSON.stringify({ address, blocked: true, alreadyBlocked: true }));
45
- return console.log(`${address} is already blocked`);
48
+ return console.log(' ' + c.dim('Already blocked: ' + formatAddress(address)));
46
49
  }
47
50
  await (await contract.addToBlocklist(wallet, address)).wait();
48
51
  if (opts.json) return console.log(JSON.stringify({ address, blocked: true }));
49
- console.log(`Added ${address} to blocklist`);
52
+ console.log(' ' + c.success + c.white(' Blocked: ' + formatAddress(address)));
50
53
  });
51
54
 
52
55
  blocklist
@@ -64,11 +67,11 @@ blocklist
64
67
  const isBlockedNow = await contract.isBlocked(wallet, address);
65
68
  if (!isBlockedNow) {
66
69
  if (opts.json) return console.log(JSON.stringify({ address, blocked: false, notBlocked: true }));
67
- return console.log(`${address} is not on your blocklist`);
70
+ return console.log(' ' + c.dim('Not on blocklist: ' + formatAddress(address)));
68
71
  }
69
72
  await (await contract.removeFromBlocklist(wallet, address)).wait();
70
73
  if (opts.json) return console.log(JSON.stringify({ address, blocked: false }));
71
- console.log(`Removed ${address} from blocklist`);
74
+ console.log(' ' + c.success + c.white(' Unblocked: ' + formatAddress(address)));
72
75
  });
73
76
 
74
77
  blocklist
@@ -86,7 +89,11 @@ blocklist
86
89
  const contract = getPolicyEngine(config.policyEngineAddress, provider);
87
90
  const blocked = await contract.isBlocked(wallet, address);
88
91
  if (opts.json) return console.log(JSON.stringify({ address, blocked }));
89
- console.log(blocked ? `${address} is BLOCKED` : `${address} is not blocked`);
92
+ if (blocked) {
93
+ console.log(' ' + c.warning + c.white(' ' + formatAddress(address) + ' is BLOCKED'));
94
+ } else {
95
+ console.log(' ' + c.success + c.white(' ' + formatAddress(address) + ' is not blocked'));
96
+ }
90
97
  });
91
98
 
92
99
  blocklist
@@ -144,11 +151,11 @@ shortlist
144
151
  const alreadyPreferred = await contract.isPreferred(wallet, opts.capability, address);
145
152
  if (alreadyPreferred) {
146
153
  if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: true, alreadyPreferred: true }));
147
- return console.log(`${address} is already shortlisted for ${opts.capability}`);
154
+ return console.log(' ' + c.dim('Already shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
148
155
  }
149
156
  await (await contract.addPreferred(wallet, opts.capability, address)).wait();
150
157
  if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: true }));
151
- console.log(`Added ${address} to shortlist for ${opts.capability}`);
158
+ console.log(' ' + c.success + c.white(' Shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
152
159
  });
153
160
 
154
161
  shortlist
@@ -167,11 +174,11 @@ shortlist
167
174
  const isPreferredNow = await contract.isPreferred(wallet, opts.capability, address);
168
175
  if (!isPreferredNow) {
169
176
  if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: false, notPreferred: true }));
170
- return console.log(`${address} is not shortlisted for ${opts.capability}`);
177
+ return console.log(' ' + c.dim('Not shortlisted: ' + formatAddress(address) + ' for ' + opts.capability));
171
178
  }
172
179
  await (await contract.removePreferred(wallet, opts.capability, address)).wait();
173
180
  if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred: false }));
174
- console.log(`Removed ${address} from shortlist for ${opts.capability}`);
181
+ console.log(' ' + c.success + c.white(' Removed from shortlist: ' + formatAddress(address) + ' for ' + opts.capability));
175
182
  });
176
183
 
177
184
  shortlist
@@ -190,7 +197,11 @@ shortlist
190
197
  const contract = getPolicyEngine(config.policyEngineAddress, provider);
191
198
  const preferred = await contract.isPreferred(wallet, opts.capability, address);
192
199
  if (opts.json) return console.log(JSON.stringify({ address, capability: opts.capability, preferred }));
193
- console.log(preferred ? `${address} is shortlisted for ${opts.capability}` : `${address} is NOT shortlisted for ${opts.capability}`);
200
+ if (preferred) {
201
+ console.log(' ' + c.success + c.white(' ' + formatAddress(address) + ' is shortlisted for ' + opts.capability));
202
+ } else {
203
+ console.log(' ' + c.warning + c.white(' ' + formatAddress(address) + ' is NOT shortlisted for ' + opts.capability));
204
+ }
194
205
  });
195
206
 
196
207
  shortlist
@@ -5,6 +5,7 @@ import * as os from "os";
5
5
  import * as http from "http";
6
6
  import * as https from "https";
7
7
  import { spawn } from "child_process";
8
+ import { c } from '../ui/colors';
8
9
 
9
10
  const PID_FILE = path.join(os.homedir(), ".arc402", "relay.pid");
10
11
 
@@ -126,7 +127,7 @@ export function registerRelayCommands(program: Command): void {
126
127
  console.log(JSON.stringify(result.data));
127
128
  } else {
128
129
  const d = result.data as { messageId?: string };
129
- console.log(`Sent. messageId: ${d.messageId}`);
130
+ console.log(' ' + c.success + c.white(' Sent — messageId: ' + d.messageId));
130
131
  }
131
132
  });
132
133
 
@@ -158,7 +159,7 @@ export function registerRelayCommands(program: Command): void {
158
159
  }
159
160
 
160
161
  if (messages.length === 0) {
161
- console.log("No messages.");
162
+ console.log(' ' + c.dim('No messages.'));
162
163
  return;
163
164
  }
164
165
 
@@ -216,7 +217,7 @@ export function registerRelayCommands(program: Command): void {
216
217
  if (opts.json) {
217
218
  console.log(JSON.stringify({ started: true, pid: child.pid, pidFile: PID_FILE }));
218
219
  } else {
219
- console.log(`Daemon started (PID ${child.pid}). PID file: ${PID_FILE}`);
220
+ console.log(' ' + c.success + c.white(' Daemon started (PID ' + child.pid + ')'));
220
221
  }
221
222
  });
222
223
 
@@ -229,7 +230,7 @@ export function registerRelayCommands(program: Command): void {
229
230
  if (opts.json) {
230
231
  console.log(JSON.stringify({ stopped: false, reason: "no pid file" }));
231
232
  } else {
232
- console.log("No running daemon found (no PID file).");
233
+ console.log(' ' + c.dim('No running daemon found.'));
233
234
  }
234
235
  return;
235
236
  }
@@ -241,7 +242,7 @@ export function registerRelayCommands(program: Command): void {
241
242
  if (opts.json) {
242
243
  console.log(JSON.stringify({ stopped: true, pid }));
243
244
  } else {
244
- console.log(`Daemon stopped (PID ${pid}).`);
245
+ console.log(' ' + c.success + c.white(' Daemon stopped (PID ' + pid + ')'));
245
246
  }
246
247
  } catch (err: unknown) {
247
248
  const msg = err instanceof Error ? err.message : String(err);
@@ -3,17 +3,19 @@ import { ProviderResponseType, ServiceAgreementClient } from "@arc402/sdk";
3
3
  import { loadConfig } from "../config";
4
4
  import { getClient, requireSigner } from "../client";
5
5
  import { hashFile, hashString } from "../utils/hash";
6
+ import { c } from '../ui/colors';
7
+ import { startSpinner } from '../ui/spinner';
6
8
 
7
9
  export function registerRemediateCommands(program: Command): void {
8
10
  const remediate = program.command("remediate").description("Negotiated remediation before formal dispute");
9
11
  remediate.command("request <id>").requiredOption("--text <feedback>").option("--uri <uri>", "Structured feedback URI", "").option("--file <path>").option("--previous <hash>", "Previous transcript hash", "0x0000000000000000000000000000000000000000000000000000000000000000").action(async (id, opts) => {
10
12
  const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { signer } = await requireSigner(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
11
- const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.requestRevision(BigInt(id), hash, opts.uri, opts.previous); console.log(`revision requested for ${id} transcriptSeed=${hash}`);
13
+ const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.requestRevision(BigInt(id), hash, opts.uri, opts.previous); console.log(' ' + c.success + c.white(' Revision requested agreement #' + id));
12
14
  });
13
15
  remediate.command("respond <id>").requiredOption("--type <type>", "revise|defend|counter|partial-settlement|human-review|escalate").requiredOption("--text <response>").option("--uri <uri>", "Structured response URI", "").option("--file <path>").option("--previous <hash>", "Previous transcript hash", "0x0000000000000000000000000000000000000000000000000000000000000000").option("--provider-payout <amount>", "Wei/token units for partial settlement", "0").action(async (id, opts) => {
14
16
  const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { signer } = await requireSigner(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
15
17
  const map: Record<string, ProviderResponseType> = { revise: ProviderResponseType.REVISE, defend: ProviderResponseType.DEFEND, counter: ProviderResponseType.COUNTER, 'partial-settlement': ProviderResponseType.PARTIAL_SETTLEMENT, 'human-review': ProviderResponseType.REQUEST_HUMAN_REVIEW, escalate: ProviderResponseType.ESCALATE };
16
- const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.respondToRevision(BigInt(id), map[String(opts.type)], hash, opts.uri, opts.previous, BigInt(opts.providerPayout)); console.log(`revision response recorded for ${id}`);
18
+ const hash = opts.file ? hashFile(opts.file) : hashString(opts.text); await client.respondToRevision(BigInt(id), map[String(opts.type)], hash, opts.uri, opts.previous, BigInt(opts.providerPayout)); console.log(' ' + c.success + c.white(' Response recorded agreement #' + id));
17
19
  });
18
20
  remediate.command("status <id>").option("--json").action(async (id, opts) => {
19
21
  const config = loadConfig(); if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config"); const { provider } = await getClient(config); const client = new ServiceAgreementClient(config.serviceAgreementAddress, provider);
@@ -3,6 +3,10 @@ import { ReputationOracleClient, ReputationSignalType } from "@arc402/sdk";
3
3
  import { ethers } from "ethers";
4
4
  import { loadConfig } from "../config";
5
5
  import { getClient, requireSigner } from "../client";
6
+ import { c } from '../ui/colors';
7
+ import { startSpinner } from '../ui/spinner';
8
+ import { renderTree } from '../ui/tree';
9
+ import { formatAddress } from '../ui/format';
6
10
 
7
11
  const reputation = new Command("reputation").description("Network-wide reputation signals");
8
12
 
@@ -21,7 +25,7 @@ reputation
21
25
  const oracle = new ReputationOracleClient(config.reputationOracleAddress, signer);
22
26
  await oracle.publishSignal(address, ReputationSignalType.WARN, ethers.ZeroHash, opts.reason);
23
27
  if (opts.json) return console.log(JSON.stringify({ address, signal: "WARN", reason: opts.reason }, null, 2));
24
- console.log(`WARN signal published against ${address}: "${opts.reason}"`);
28
+ console.log(' ' + c.warning + c.white(' WARN published against ' + formatAddress(address)));
25
29
  });
26
30
 
27
31
  reputation
@@ -39,7 +43,7 @@ reputation
39
43
  const oracle = new ReputationOracleClient(config.reputationOracleAddress, signer);
40
44
  await oracle.publishSignal(address, ReputationSignalType.BLOCK, ethers.ZeroHash, opts.reason);
41
45
  if (opts.json) return console.log(JSON.stringify({ address, signal: "BLOCK", reason: opts.reason }, null, 2));
42
- console.log(`BLOCK signal published against ${address}: "${opts.reason}"`);
46
+ console.log(' ' + c.failure + c.white(' BLOCK published against ' + formatAddress(address)));
43
47
  });
44
48
 
45
49
  reputation
@@ -63,9 +67,13 @@ reputation
63
67
  weightedScore: rep.weightedScore.toString(),
64
68
  };
65
69
  if (opts.json) return console.log(JSON.stringify(payload, null, 2));
66
- console.log(`address=${address}`);
67
- console.log(`endorsements=${rep.endorsements} warnings=${rep.warnings} blocks=${rep.blocks}`);
68
- console.log(`weightedScore=${rep.weightedScore}`);
70
+ console.log('\n ' + c.mark + c.white(' Reputation — ' + formatAddress(address)));
71
+ renderTree([
72
+ { label: 'Endorsements', value: rep.endorsements.toString() },
73
+ { label: 'Warnings', value: rep.warnings.toString() },
74
+ { label: 'Blocks', value: rep.blocks.toString() },
75
+ { label: 'Score', value: rep.weightedScore.toString(), last: true },
76
+ ]);
69
77
  });
70
78
 
71
79
  export default reputation;
@@ -3,6 +3,9 @@ import { ReputationOracleClient, SponsorshipAttestationClient, TrustClient } fro
3
3
  import { loadConfig } from "../config";
4
4
  import { getClient } from "../client";
5
5
  import { getTrustTier, identityTierLabel } from "../utils/format";
6
+ import { c } from '../ui/colors';
7
+ import { renderTree } from '../ui/tree';
8
+ import { formatAddress } from '../ui/format';
6
9
 
7
10
  export function registerTrustCommand(program: Command): void {
8
11
  program.command("trust <address>").description("Look up trust plus secondary sponsorship/reputation signals for an address").option("--json").action(async (address, opts) => {
@@ -10,6 +13,15 @@ export function registerTrustCommand(program: Command): void {
10
13
  const score = await trust.getScore(address); const sponsorship = config.sponsorshipAttestationAddress ? new SponsorshipAttestationClient(config.sponsorshipAttestationAddress, provider) : null; const reputation = config.reputationOracleAddress ? new ReputationOracleClient(config.reputationOracleAddress, provider) : null;
11
14
  const highestTier = sponsorship ? await sponsorship.getHighestTier(address) : undefined; const rep = reputation ? await reputation.getReputation(address) : undefined;
12
15
  if (opts.json) return console.log(JSON.stringify({ address, score, highestTier, reputation: rep }, (_k, value) => typeof value === 'bigint' ? value.toString() : value, 2));
13
- console.log(`score=${score.score} tier=${getTrustTier(score.score)} next=${score.nextLevelAt}${highestTier !== undefined ? ` sponsorship=${identityTierLabel(highestTier)}` : ''}${rep ? ` reputation=${rep.weightedScore}` : ''}`);
16
+ console.log('\n ' + c.mark + c.white(' Trust ' + formatAddress(address)));
17
+ const trustTreeItems: { label: string; value: string; last?: boolean }[] = [
18
+ { label: 'Score', value: String(score.score) },
19
+ { label: 'Tier', value: getTrustTier(score.score) },
20
+ { label: 'Next level', value: String(score.nextLevelAt) },
21
+ ];
22
+ if (highestTier !== undefined) trustTreeItems.push({ label: 'Sponsorship', value: identityTierLabel(highestTier) });
23
+ if (rep) trustTreeItems.push({ label: 'Reputation', value: String(rep.weightedScore), last: true });
24
+ else trustTreeItems[trustTreeItems.length - 1].last = true;
25
+ renderTree(trustTreeItems);
14
26
  });
15
27
  }
@@ -5,6 +5,8 @@ import { loadConfig } from "../config";
5
5
  import { getClient, requireSigner } from "../client";
6
6
  import { printSenderInfo, executeContractWriteViaWallet } from "../wallet-router";
7
7
  import { SERVICE_AGREEMENT_ABI } from "../abis";
8
+ import { c } from '../ui/colors';
9
+ import { startSpinner } from '../ui/spinner';
8
10
 
9
11
  // Agreement status values from the contract
10
12
  const AGREEMENT_STATUS_NAMES: Record<number, string> = {
@@ -29,6 +31,7 @@ export function registerVerifyCommand(program: Command): void {
29
31
  if (!config.serviceAgreementAddress) throw new Error("serviceAgreementAddress missing in config");
30
32
  const { signer } = await requireSigner(config);
31
33
  printSenderInfo(config);
34
+ const spinner = startSpinner('Submitting…');
32
35
 
33
36
  // Pre-flight: check agreement is in PENDING_VERIFICATION status (J2-04)
34
37
  if (!opts.auto) {
@@ -62,12 +65,12 @@ export function registerVerifyCommand(program: Command): void {
62
65
  SERVICE_AGREEMENT_ABI, "autoRelease", [BigInt(id)],
63
66
  );
64
67
  if (opts.json) return console.log(JSON.stringify({ agreementId: id, action: "autoRelease", txHash: tx.hash }));
65
- console.log(`autoRelease submitted for agreement #${id}. tx=${tx.hash}`);
68
+ spinner.succeed('Auto-released agreement #' + id + ' — tx ' + tx.hash.slice(0, 10) + '...');
66
69
  } else {
67
70
  const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
68
71
  const tx = await client.autoRelease(BigInt(id));
69
72
  if (opts.json) return console.log(JSON.stringify({ agreementId: id, action: "autoRelease", txHash: tx.hash }));
70
- console.log(`autoRelease submitted for agreement #${id}. tx=${tx.hash}`);
73
+ spinner.succeed('Auto-released agreement #' + id + ' — tx ' + tx.hash.slice(0, 10) + '...');
71
74
  }
72
75
  } else {
73
76
  if (config.walletContractAddress) {
@@ -76,12 +79,12 @@ export function registerVerifyCommand(program: Command): void {
76
79
  SERVICE_AGREEMENT_ABI, "verifyDeliverable", [BigInt(id)],
77
80
  );
78
81
  if (opts.json) return console.log(JSON.stringify({ agreementId: id, action: "verifyDeliverable", txHash: tx.hash }));
79
- console.log(`Agreement #${id} verified — escrow released. tx=${tx.hash}`);
82
+ spinner.succeed('Verified — agreement #' + id + ' — escrow released');
80
83
  } else {
81
84
  const client = new ServiceAgreementClient(config.serviceAgreementAddress, signer);
82
85
  const tx = await client.verifyDeliverable(BigInt(id));
83
86
  if (opts.json) return console.log(JSON.stringify({ agreementId: id, action: "verifyDeliverable", txHash: tx.hash }));
84
- console.log(`Agreement #${id} verified — escrow released. tx=${tx.hash}`);
87
+ spinner.succeed('Verified — agreement #' + id + ' — escrow released');
85
88
  }
86
89
  }
87
90
  });