mycomesh-relay 0.9.11 → 0.9.13
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/package.json +1 -1
- package/src/cli.mjs +50 -4
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -20,8 +20,10 @@ const USAGE = `Usage: mycomesh-relay <command> [options]
|
|
|
20
20
|
register [--deposit UNITS] bind the signer on-chain, fund probes, and announce the Relay (with its
|
|
21
21
|
certificate pin) in the on-chain Relay directory; testnet gas comes from the faucet
|
|
22
22
|
start [--with-keeper] run the Relay on ports 10443 (HTTPS) and 10991 (Provider links)
|
|
23
|
-
status | logs | stop inspect or stop it
|
|
23
|
+
status | logs | stop inspect or stop it (status: Providers linked, settlement queue, gas left)
|
|
24
24
|
earnings | claim the Relay's share of fees and paying it out
|
|
25
|
+
receipts [--retry] receipts not settled yet or rejected, and why; --retry queues again
|
|
26
|
+
every rejected one still inside its deadline
|
|
25
27
|
address print the owner address (fund it with a little ETH on mainnets)
|
|
26
28
|
|
|
27
29
|
Options: --home DIR (default ~/.mycomesh/relay), --image REF, --network FILE,
|
|
@@ -59,6 +61,18 @@ function mycomesh(values, paths, args, extra = []) {
|
|
|
59
61
|
values.image || IMAGE, ...args.map((arg) => (arg === "@network" ? net.inside : arg))]);
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/** The running Relay's /health, from this machine (its certificate is self-signed and pinned on-chain). */
|
|
65
|
+
function localHealth(port) {
|
|
66
|
+
return new Promise((resolvePromise) => {
|
|
67
|
+
const req = request({ host: "127.0.0.1", port: Number(port), path: "/health", rejectUnauthorized: false, timeout: 5000 }, (res) => {
|
|
68
|
+
let body = ""; res.on("data", (chunk) => { body += chunk; });
|
|
69
|
+
res.on("end", () => { try { resolvePromise(JSON.parse(body)); } catch { resolvePromise(null); } });
|
|
70
|
+
});
|
|
71
|
+
req.on("error", () => resolvePromise(null)); req.on("timeout", () => req.destroy());
|
|
72
|
+
req.end();
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
function publicIp() {
|
|
63
77
|
return new Promise((resolvePromise, reject) => {
|
|
64
78
|
request("https://api.ipify.org", (res) => {
|
|
@@ -92,9 +106,10 @@ export async function main(argv = process.argv.slice(2), { stdout = process.stdo
|
|
|
92
106
|
home: { type: "string" }, image: { type: "string" }, network: { type: "string" }, "public-ip": { type: "string" },
|
|
93
107
|
deposit: { type: "string", default: "20000000" }, "http-port": { type: "string", default: "10443" },
|
|
94
108
|
"link-port": { type: "string", default: "10991" }, "with-keeper": { type: "boolean" }, help: { type: "boolean" },
|
|
95
|
-
version: { type: "boolean" },
|
|
109
|
+
version: { type: "boolean" }, retry: { type: "boolean" }, json: { type: "boolean" },
|
|
96
110
|
},
|
|
97
111
|
});
|
|
112
|
+
const human = !values.json && stdout === process.stdout && process.stdout.isTTY;
|
|
98
113
|
const [command = "help"] = positionals;
|
|
99
114
|
if (values.version) {
|
|
100
115
|
stdout.write(`${JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version}\n`);
|
|
@@ -155,7 +170,32 @@ export async function main(argv = process.argv.slice(2), { stdout = process.stdo
|
|
|
155
170
|
const state = spawnSync("docker", ["ps", "-a", "--filter", `name=^${name}$`, "--format", "{{.Status}}"], { encoding: "utf8" }).stdout.trim();
|
|
156
171
|
if (state) stdout.write(`${name}: ${state}\n`);
|
|
157
172
|
}
|
|
158
|
-
|
|
173
|
+
const health = await localHealth(config.http_port || values["http-port"]);
|
|
174
|
+
if (!health) {
|
|
175
|
+
stdout.write(`${spawnSync("docker", ["logs", "--tail", "5", RELAY], { encoding: "utf8" }).stdout || ""}`);
|
|
176
|
+
return 2;
|
|
177
|
+
}
|
|
178
|
+
const queue = health.queue || {};
|
|
179
|
+
stdout.write(`Providers linked: ${health.providers}\n`
|
|
180
|
+
+ `receipts: ${queue.queued || 0} waiting to settle, ${queue.settled || 0} in escrow, ${queue.released || 0} paid out, `
|
|
181
|
+
+ `${queue.rejected || 0} rejected${queue.rejected ? " (mycomesh-relay receipts)" : ""}\n`);
|
|
182
|
+
const gas = health.submitter;
|
|
183
|
+
if (gas?.address) stdout.write(`settlement gas: ${gas.balance_eth} ETH in ${gas.address}${gas.low ? " LOW: fund it, or receipts stop settling" : ""}\n`);
|
|
184
|
+
if (health.settlement_worker?.error) stdout.write(`settlement worker: ${health.settlement_worker.error}\n`);
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
if (command === "receipts") {
|
|
188
|
+
const raw = mycomesh(values, paths, ["relay", "receipts", "--network", "@network", "--data-dir", "/data/relay",
|
|
189
|
+
...(values.retry ? ["--retry"] : [])]);
|
|
190
|
+
if (!human) { stdout.write(`${raw}\n`); return 0; }
|
|
191
|
+
const report = JSON.parse(raw);
|
|
192
|
+
stdout.write(`${JSON.stringify(report.counts)}\n`);
|
|
193
|
+
for (const r of report.receipts.slice(0, 30)) {
|
|
194
|
+
stdout.write(`${r.state.padEnd(8)} ${(r.fee / 1e6).toFixed(6)} tUSDC ${new Date(r.updated_at * 1000).toLocaleString()} `
|
|
195
|
+
+ `${r.still_settleable ? "can still settle" : "expired"} ${(r.error || "").slice(0, 100)}\n`);
|
|
196
|
+
}
|
|
197
|
+
if (report.rejected_expired_fees) stdout.write(`lost to expiry: ${(report.rejected_expired_fees / 1e6).toFixed(6)} tUSDC\n`);
|
|
198
|
+
if (report.retried.length) stdout.write(`queued again: ${report.retried.length}\n`);
|
|
159
199
|
return 0;
|
|
160
200
|
}
|
|
161
201
|
if (command === "logs") { docker(["logs", "-f", "--tail", "100", RELAY], { capture: false }); return 0; }
|
|
@@ -165,7 +205,13 @@ export async function main(argv = process.argv.slice(2), { stdout = process.stdo
|
|
|
165
205
|
return 0;
|
|
166
206
|
}
|
|
167
207
|
if (command === "earnings") {
|
|
168
|
-
|
|
208
|
+
const raw = mycomesh(values, paths, ["relay", "earnings", "--network", "@network", "--owner", config.owner]);
|
|
209
|
+
if (!human) { stdout.write(`${raw}\n`); return 0; }
|
|
210
|
+
const e = JSON.parse(raw);
|
|
211
|
+
const relay = e.myco?.roles?.relay;
|
|
212
|
+
stdout.write(`claimable now ${(e.claimable / 1e6).toFixed(6)} tUSDC (the Relay's 5%, paid as receipts are released)\n`
|
|
213
|
+
+ (relay ? `MYCO claimable ${(Number(BigInt(relay.claimable_wei) / 10n ** 14n) / 1e4).toFixed(4)} MYCO\n` : "")
|
|
214
|
+
+ `owner gas ${(Number(e.eth_wei) / 1e18).toFixed(5)} ETH (pays settlement, release and claims)\n`);
|
|
169
215
|
return 0;
|
|
170
216
|
}
|
|
171
217
|
if (command === "claim") {
|