@obbyx/cli 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +24 -2
- package/dist/cli.d.ts +24 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +117 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/address.d.ts +3 -0
- package/dist/commands/address.d.ts.map +1 -0
- package/dist/commands/address.js +13 -0
- package/dist/commands/address.js.map +1 -0
- package/dist/commands/balance.d.ts +3 -0
- package/dist/commands/balance.d.ts.map +1 -0
- package/dist/commands/balance.js +30 -0
- package/dist/commands/balance.js.map +1 -0
- package/dist/commands/channel-cli.d.ts +11 -0
- package/dist/commands/channel-cli.d.ts.map +1 -0
- package/dist/commands/channel-cli.js +77 -0
- package/dist/commands/channel-cli.js.map +1 -0
- package/dist/commands/channel.d.ts +11 -0
- package/dist/commands/channel.d.ts.map +1 -0
- package/dist/commands/channel.js +77 -0
- package/dist/commands/channel.js.map +1 -0
- package/dist/commands/decode.d.ts +5 -0
- package/dist/commands/decode.d.ts.map +1 -0
- package/dist/commands/decode.js +17 -0
- package/dist/commands/decode.js.map +1 -0
- package/dist/commands/doctor-command.d.ts +5 -0
- package/dist/commands/doctor-command.d.ts.map +1 -0
- package/dist/commands/doctor-command.js +17 -0
- package/dist/commands/doctor-command.js.map +1 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +17 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/faucet.d.ts +5 -0
- package/dist/commands/faucet.d.ts.map +1 -0
- package/dist/commands/faucet.js +42 -0
- package/dist/commands/faucet.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +26 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/logs-command.d.ts +12 -0
- package/dist/commands/logs-command.d.ts.map +1 -0
- package/dist/commands/logs-command.js +32 -0
- package/dist/commands/logs-command.js.map +1 -0
- package/dist/commands/logs.d.ts +12 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +32 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/pay.d.ts +14 -0
- package/dist/commands/pay.d.ts.map +1 -0
- package/dist/commands/pay.js +115 -0
- package/dist/commands/pay.js.map +1 -0
- package/dist/commands/types.d.ts +27 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/faucet/device.d.ts +74 -0
- package/dist/faucet/device.d.ts.map +1 -0
- package/dist/faucet/device.js +222 -0
- package/dist/faucet/device.js.map +1 -0
- package/dist/faucet/faucet.d.ts +40 -0
- package/dist/faucet/faucet.d.ts.map +1 -0
- package/dist/faucet/faucet.js +111 -0
- package/dist/faucet/faucet.js.map +1 -0
- package/dist/lib/channels.d.ts +24 -0
- package/dist/lib/channels.d.ts.map +1 -0
- package/dist/lib/channels.js +111 -0
- package/dist/lib/channels.js.map +1 -0
- package/dist/lib/doctor.d.ts +7 -0
- package/dist/lib/doctor.d.ts.map +1 -0
- package/dist/lib/doctor.js +97 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/logs.d.ts +16 -0
- package/dist/lib/logs.d.ts.map +1 -0
- package/dist/lib/logs.js +64 -0
- package/dist/lib/logs.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +11 -0
- package/dist/main.js.map +1 -0
- package/dist/runtime.d.ts +21 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +86 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +52 -3
- package/src/cli.ts +139 -0
- package/src/commands/address.ts +14 -0
- package/src/commands/balance.ts +35 -0
- package/src/commands/channel.ts +96 -0
- package/src/commands/decode.ts +19 -0
- package/src/commands/doctor.ts +21 -0
- package/src/commands/faucet.ts +48 -0
- package/src/commands/init.ts +28 -0
- package/src/commands/logs.ts +48 -0
- package/src/commands/pay.ts +135 -0
- package/src/commands/types.ts +31 -0
- package/src/faucet/device.ts +330 -0
- package/src/faucet/faucet.ts +141 -0
- package/src/lib/channels.ts +161 -0
- package/src/lib/doctor.ts +133 -0
- package/src/lib/logs.ts +79 -0
- package/src/main.ts +14 -0
- package/src/runtime.ts +123 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import obyte from 'obyte';
|
|
4
|
+
import { toDisplay } from '@obbyx/obyte';
|
|
5
|
+
import { ClientChannelStore, CoinReservations, hubCall } from '@obbyx/x402-obyte';
|
|
6
|
+
import { channelStorePath } from './channels.js';
|
|
7
|
+
import { obbyxHome, walletPath } from '@obbyx/obyte/wallet';
|
|
8
|
+
export async function doctor(network, opts) {
|
|
9
|
+
const results = [];
|
|
10
|
+
const report = (status, what, detail = '') => {
|
|
11
|
+
results.push(status);
|
|
12
|
+
opts.out(`${status === 'ok' ? '✓' : status === 'warn' ? '!' : '✗'} ${what}${detail ? ` — ${detail}` : ''}`);
|
|
13
|
+
};
|
|
14
|
+
// Wallet
|
|
15
|
+
const wallet = walletPath(network);
|
|
16
|
+
let address;
|
|
17
|
+
if (!existsSync(wallet)) {
|
|
18
|
+
report('fail', 'wallet', `missing; run: obbyx init --network ${network.name}`);
|
|
19
|
+
}
|
|
20
|
+
else if ((statSync(wallet).mode & 0o077) !== 0) {
|
|
21
|
+
report('fail', 'wallet', `${wallet} is readable by others; run: chmod 600 ${wallet}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const { readFileSync } = await import('node:fs');
|
|
25
|
+
address = JSON.parse(readFileSync(wallet, 'utf8')).address;
|
|
26
|
+
report('ok', 'wallet', `${address} (${wallet})`);
|
|
27
|
+
}
|
|
28
|
+
// Hub
|
|
29
|
+
const client = new obyte.Client(opts.hub ?? network.defaultHubUrl, { testnet: network.testnet });
|
|
30
|
+
try {
|
|
31
|
+
const started = Date.now();
|
|
32
|
+
const mci = await hubCall(() => client.api.getLastMci(), 10_000);
|
|
33
|
+
if (mci.kind !== 'ok') {
|
|
34
|
+
report('fail', 'hub', `${opts.hub ?? network.defaultHubUrl}: ${mci.error}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
report('ok', 'hub', `${opts.hub ?? network.defaultHubUrl}, last MCI ${mci.value}, ${Date.now() - started} ms`);
|
|
38
|
+
if (address !== undefined) {
|
|
39
|
+
const b = await hubCall(() => client.api.getBalances([address]), 10_000);
|
|
40
|
+
if (b.kind === 'ok') {
|
|
41
|
+
const base = b.value[address]?.['base'];
|
|
42
|
+
const stable = BigInt(base?.stable ?? 0);
|
|
43
|
+
const pending = BigInt(base?.pending ?? 0);
|
|
44
|
+
report(stable === 0n ? (network.testnet ? 'warn' : 'fail') : 'ok', 'balance', `${toDisplay(stable, 9)} GBYTE stable, ${toDisplay(pending, 9)} pending` +
|
|
45
|
+
(stable === 0n && network.testnet ? '; run: obbyx faucet' : ''));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
report('warn', 'balance', b.error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
client.close();
|
|
55
|
+
}
|
|
56
|
+
// Local payment state
|
|
57
|
+
const coinsPath = join(obbyxHome(), `coins-${network.name}.db`);
|
|
58
|
+
if (existsSync(coinsPath)) {
|
|
59
|
+
const reservations = new CoinReservations(coinsPath);
|
|
60
|
+
const units = reservations.boundUnits(network.caip2);
|
|
61
|
+
reservations.close();
|
|
62
|
+
report(units.length === 0 ? 'ok' : 'warn', 'coin reservations', units.length === 0
|
|
63
|
+
? 'none'
|
|
64
|
+
: `${units.length} unpublished payment unit(s) hold inputs; they are released once seen on the ledger or after the publication window`);
|
|
65
|
+
}
|
|
66
|
+
const channelsPath = channelStorePath(network);
|
|
67
|
+
if (existsSync(channelsPath)) {
|
|
68
|
+
const channels = new ClientChannelStore(channelsPath);
|
|
69
|
+
const list = channels.list().filter((c) => c.network === network.caip2);
|
|
70
|
+
channels.close();
|
|
71
|
+
const pending = list.filter((c) => c.pending !== null);
|
|
72
|
+
report(pending.length === 0 ? 'ok' : 'warn', 'channels', `${list.length} channel(s)` +
|
|
73
|
+
(pending.length
|
|
74
|
+
? `, ${pending.length} with a voucher of unknown outcome (retry that request with --payment)`
|
|
75
|
+
: ''));
|
|
76
|
+
}
|
|
77
|
+
// Facilitator (optional)
|
|
78
|
+
if (opts.facilitator !== undefined) {
|
|
79
|
+
try {
|
|
80
|
+
const res = await fetch(new URL('/supported', opts.facilitator), {
|
|
81
|
+
signal: AbortSignal.timeout(10_000),
|
|
82
|
+
});
|
|
83
|
+
const supported = (await res.json());
|
|
84
|
+
const kinds = (supported.kinds ?? [])
|
|
85
|
+
.filter((k) => k.network === network.caip2)
|
|
86
|
+
.map((k) => k.scheme);
|
|
87
|
+
report(kinds.length > 0 ? 'ok' : 'fail', 'facilitator', kinds.length > 0
|
|
88
|
+
? `${opts.facilitator}: ${kinds.join(', ')}`
|
|
89
|
+
: `does not serve ${network.caip2}`);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
report('fail', 'facilitator', `${opts.facilitator}: ${err instanceof Error ? err.message : String(err)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return results.includes('fail') ? 1 : 0;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/lib/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `obbyx logs` — follow ONE payment through the JSON logs of the seller
|
|
3
|
+
* middleware, the facilitator and the watcher (they share correlation fields:
|
|
4
|
+
* requestId, binding, proofId, aa, seq). Reads files or stdin.
|
|
5
|
+
*/
|
|
6
|
+
export interface LogFilter {
|
|
7
|
+
readonly binding?: string;
|
|
8
|
+
readonly proof?: string;
|
|
9
|
+
readonly aa?: string;
|
|
10
|
+
readonly request?: string;
|
|
11
|
+
readonly level?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function matches(entry: Record<string, unknown>, f: LogFilter): boolean;
|
|
14
|
+
export declare function format(entry: Record<string, unknown>): string;
|
|
15
|
+
export declare function logs(files: readonly string[], filter: LogFilter, out: (s: string) => void): Promise<number>;
|
|
16
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/lib/logs.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAiBD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,SAAS,GAAG,OAAO,CAY7E;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQ7D;AAED,wBAAsB,IAAI,CACxB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACvB,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
package/dist/lib/logs.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createReadStream } from 'node:fs';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
const LEVELS = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
|
|
4
|
+
const SHOWN = [
|
|
5
|
+
'binding',
|
|
6
|
+
'proofId',
|
|
7
|
+
'aa',
|
|
8
|
+
'seq',
|
|
9
|
+
'reason',
|
|
10
|
+
'from',
|
|
11
|
+
'to',
|
|
12
|
+
'transaction',
|
|
13
|
+
'amountSpent',
|
|
14
|
+
'status',
|
|
15
|
+
'err',
|
|
16
|
+
];
|
|
17
|
+
export function matches(entry, f) {
|
|
18
|
+
if (f.binding !== undefined && entry['binding'] !== f.binding)
|
|
19
|
+
return false;
|
|
20
|
+
if (f.proof !== undefined && entry['proofId'] !== f.proof && entry['unit'] !== f.proof)
|
|
21
|
+
return false;
|
|
22
|
+
if (f.aa !== undefined && entry['aa'] !== f.aa)
|
|
23
|
+
return false;
|
|
24
|
+
if (f.request !== undefined && entry['requestId'] !== f.request && entry['reqId'] !== f.request)
|
|
25
|
+
return false;
|
|
26
|
+
if (f.level !== undefined) {
|
|
27
|
+
const min = LEVELS.indexOf(f.level);
|
|
28
|
+
if (min >= 0 && LEVELS.indexOf(String(entry['level'])) < min)
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
export function format(entry) {
|
|
34
|
+
const time = String(entry['time'] ?? '').slice(11, 23);
|
|
35
|
+
const extra = SHOWN.filter((k) => entry[k] !== undefined)
|
|
36
|
+
.map((k) => `${k}=${typeof entry[k] === 'object' ? JSON.stringify(entry[k]) : String(entry[k])}`)
|
|
37
|
+
.join(' ');
|
|
38
|
+
return `${time} ${String(entry['level'] ?? '').padEnd(5)} ${String(entry['service'] ?? '-')}/${String(entry['module'] ?? '-')}: ${String(entry['msg'] ?? '')}${extra ? ` ${extra}` : ''}`;
|
|
39
|
+
}
|
|
40
|
+
export async function logs(files, filter, out) {
|
|
41
|
+
const sources = files.length > 0 ? files : ['-'];
|
|
42
|
+
const found = [];
|
|
43
|
+
for (const file of sources) {
|
|
44
|
+
const input = file === '-' ? process.stdin : createReadStream(file, 'utf8');
|
|
45
|
+
for await (const line of createInterface({ input, crlfDelay: Infinity })) {
|
|
46
|
+
if (!line.startsWith('{'))
|
|
47
|
+
continue;
|
|
48
|
+
try {
|
|
49
|
+
const entry = JSON.parse(line);
|
|
50
|
+
if (matches(entry, filter))
|
|
51
|
+
found.push(entry);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// not a JSON log line
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Several components' logs merged into one timeline.
|
|
59
|
+
found.sort((a, b) => String(a['time'] ?? '').localeCompare(String(b['time'] ?? '')));
|
|
60
|
+
for (const entry of found)
|
|
61
|
+
out(format(entry));
|
|
62
|
+
return found.length > 0 ? 0 : 1;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/lib/logs.ts"],"names":[],"mappings":"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"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { hideBin } from 'yargs/helpers';
|
|
3
|
+
import { runCli } from './cli.js';
|
|
4
|
+
runCli(hideBin(process.argv), {
|
|
5
|
+
out: (line = '') => process.stdout.write(`${line}\n`),
|
|
6
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
7
|
+
}).then((code) => process.exit(code), (e) => {
|
|
8
|
+
process.stderr.write(`error: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;IAC5B,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;IACrD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;CACjD,CAAC,CAAC,IAAI,CACL,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAC5B,CAAC,CAAU,EAAE,EAAE;IACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import obyte from 'obyte';
|
|
2
|
+
import { type ObyteNetwork } from '@obbyx/obyte';
|
|
3
|
+
import { type Logger } from '@obbyx/obyte/logger';
|
|
4
|
+
import { ReservingComposer } from '@obbyx/x402-obyte';
|
|
5
|
+
/** Helpers shared by the commands: network/hub, logger, argument parsing, output. */
|
|
6
|
+
export declare function printPayment(err: (l: string) => void, network: ObyteNetwork, p: {
|
|
7
|
+
success: boolean;
|
|
8
|
+
amount?: string;
|
|
9
|
+
transaction: string;
|
|
10
|
+
errorReason?: string;
|
|
11
|
+
extra?: unknown;
|
|
12
|
+
}): void;
|
|
13
|
+
export declare function cliLogger(): Logger;
|
|
14
|
+
export declare function bytesArg(value: string, name: string): bigint;
|
|
15
|
+
export declare function seconds(value: string, name: string): number;
|
|
16
|
+
/** Reserving coin picker for this wallet (inputs of unpublished units are never reused). */
|
|
17
|
+
export declare function reservingComposer(client: obyte.Client, network: ObyteNetwork, address: string, logger: Logger): ReservingComposer;
|
|
18
|
+
export declare function resolveNetwork(name: string): ObyteNetwork;
|
|
19
|
+
export declare function connect(network: ObyteNetwork, hub: string | undefined): obyte.Client;
|
|
20
|
+
export declare function decodeAny(value: string): unknown;
|
|
21
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,EAGL,KAAK,YAAY,EAIlB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAoB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,qFAAqF;AACrF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EACxB,OAAO,EAAE,YAAY,EACrB,CAAC,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACA,IAAI,CAoBN;AAED,wBAAgB,SAAS,IAAI,MAAM,CAKlC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,iBAAiB,CAQnB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAOzD;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAEpF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAoBhD"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import obyte from 'obyte';
|
|
3
|
+
import { decodePaymentRequiredHeader, decodePaymentResponseHeader, decodePaymentSignatureHeader, } from '@x402/core/http';
|
|
4
|
+
import { OBYTE_NETWORKS, ObbyxError, explorerUnitUrl, getNetwork, toDisplay, } from '@obbyx/obyte';
|
|
5
|
+
import { createLogger } from '@obbyx/obyte/logger';
|
|
6
|
+
import { obbyxHome } from '@obbyx/obyte/wallet';
|
|
7
|
+
import { CoinReservations, ReservingComposer } from '@obbyx/x402-obyte';
|
|
8
|
+
/** Helpers shared by the commands: network/hub, logger, argument parsing, output. */
|
|
9
|
+
export function printPayment(err, network, p) {
|
|
10
|
+
const channel = p.extra;
|
|
11
|
+
if (p.success && channel?.chargedAmount !== undefined) {
|
|
12
|
+
// batch-settlement: an off-chain voucher, no unit per call.
|
|
13
|
+
err(`Paid: ${toDisplay(BigInt(channel.chargedAmount), 9)} GBYTE via channel ${channel.channelState?.channelId ?? ''}` +
|
|
14
|
+
` (total in this period: ${toDisplay(BigInt(channel.channelState?.chargedCumulativeAmount ?? '0'), 9)} GBYTE)`);
|
|
15
|
+
}
|
|
16
|
+
else if (p.success) {
|
|
17
|
+
err(`Paid: ${toDisplay(BigInt(p.amount ?? '0'), 9)} GBYTE, unit ${p.transaction}\n ${explorerUnitUrl(network, p.transaction)}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
err(`Payment not completed: ${p.errorReason}${p.transaction ? ` (${p.transaction})` : ''}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function cliLogger() {
|
|
24
|
+
return createLogger({
|
|
25
|
+
level: process.env['LOG_LEVEL'] ?? 'warn',
|
|
26
|
+
pretty: process.stderr.isTTY,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function bytesArg(value, name) {
|
|
30
|
+
if (!/^\d+$/.test(value))
|
|
31
|
+
throw new ObbyxError('usage', `--${name} must be a whole number of bytes`);
|
|
32
|
+
return BigInt(value);
|
|
33
|
+
}
|
|
34
|
+
export function seconds(value, name) {
|
|
35
|
+
const n = Number(value);
|
|
36
|
+
if (!Number.isInteger(n) || n <= 0 || n > 86_400) {
|
|
37
|
+
throw new ObbyxError('usage', `--${name} must be a whole number of seconds (1..86400)`);
|
|
38
|
+
}
|
|
39
|
+
return n;
|
|
40
|
+
}
|
|
41
|
+
/** Reserving coin picker for this wallet (inputs of unpublished units are never reused). */
|
|
42
|
+
export function reservingComposer(client, network, address, logger) {
|
|
43
|
+
return new ReservingComposer({
|
|
44
|
+
client,
|
|
45
|
+
network: network.caip2,
|
|
46
|
+
address,
|
|
47
|
+
reservations: new CoinReservations(join(obbyxHome(), `coins-${network.name}.db`)),
|
|
48
|
+
logger,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export function resolveNetwork(name) {
|
|
52
|
+
if (name === 'testnet' || name === 'livenet')
|
|
53
|
+
return OBYTE_NETWORKS[name];
|
|
54
|
+
try {
|
|
55
|
+
return getNetwork(name);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new ObbyxError('usage', `Unknown --network "${name}" (use testnet or livenet)`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function connect(network, hub) {
|
|
62
|
+
return new obyte.Client(hub ?? network.defaultHubUrl, { testnet: network.testnet });
|
|
63
|
+
}
|
|
64
|
+
export function decodeAny(value) {
|
|
65
|
+
for (const [kind, decode] of [
|
|
66
|
+
['PAYMENT-SIGNATURE', decodePaymentSignatureHeader],
|
|
67
|
+
['PAYMENT-REQUIRED', decodePaymentRequiredHeader],
|
|
68
|
+
['PAYMENT-RESPONSE', decodePaymentResponseHeader],
|
|
69
|
+
]) {
|
|
70
|
+
try {
|
|
71
|
+
const decoded = decode(value);
|
|
72
|
+
const looksRight = kind === 'PAYMENT-SIGNATURE'
|
|
73
|
+
? 'payload' in decoded && 'accepted' in decoded
|
|
74
|
+
: kind === 'PAYMENT-REQUIRED'
|
|
75
|
+
? 'accepts' in decoded
|
|
76
|
+
: 'success' in decoded;
|
|
77
|
+
if (looksRight)
|
|
78
|
+
return { header: kind, value: decoded };
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// try next
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
throw new ObbyxError('decode_failed', 'Not a recognizable x402 header');
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obbyx/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "obbyx command line: Obyte wallet, testnet faucet, paying x402 APIs, payment channels, diagnostics",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"x402",
|
|
7
|
+
"obyte",
|
|
8
|
+
"cli",
|
|
9
|
+
"payments",
|
|
10
|
+
"wallet"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Alexander Ponomarev",
|
|
14
|
+
"homepage": "https://github.com/Taump/obbyx/tree/master/packages/cli#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/Taump/obbyx.git",
|
|
18
|
+
"directory": "packages/cli"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Taump/obbyx/issues"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=24"
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"obbyx": "./dist/main.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"src",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@obbyx/obyte": "^0.1.0",
|
|
41
|
+
"@obbyx/sdk": "^0.1.0",
|
|
42
|
+
"@obbyx/x402-obyte": "^0.1.0",
|
|
43
|
+
"@x402/core": "^2.29.0",
|
|
44
|
+
"obyte": "0.2.1",
|
|
45
|
+
"yargs": "^18.2.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/yargs": "^17.0.35"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc -p tsconfig.build.json",
|
|
52
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
53
|
+
"dev": "tsx --conditions=@obbyx/source src/main.ts"
|
|
54
|
+
}
|
|
6
55
|
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import yargs, { type Argv, type CommandModule } from 'yargs';
|
|
2
|
+
import { ObbyxError } from '@obbyx/obyte';
|
|
3
|
+
import { addressCommand } from './commands/address.js';
|
|
4
|
+
import { balanceCommand } from './commands/balance.js';
|
|
5
|
+
import { channelCommands } from './commands/channel.js';
|
|
6
|
+
import { decodeCommand } from './commands/decode.js';
|
|
7
|
+
import { doctorCommand } from './commands/doctor.js';
|
|
8
|
+
import { faucetCommand } from './commands/faucet.js';
|
|
9
|
+
import { initCommand } from './commands/init.js';
|
|
10
|
+
import { logsCommand } from './commands/logs.js';
|
|
11
|
+
import { payCommand } from './commands/pay.js';
|
|
12
|
+
import type { AnyCmd, CliIo, CommandContext } from './commands/types.js';
|
|
13
|
+
|
|
14
|
+
export type { CliIo } from './commands/types.js';
|
|
15
|
+
export { decodeAny, resolveNetwork } from './runtime.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The `obbyx` command line, on yargs. Every command lives in `commands/` as a
|
|
19
|
+
* definition (name, options, handler); this module only assembles them. The
|
|
20
|
+
* CLI reference in the docs is generated from the same definitions
|
|
21
|
+
* (`renderHelp`, `commandPaths`).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Commands store their exit code here (yargs handlers cannot return one). */
|
|
25
|
+
interface RunState {
|
|
26
|
+
code: number;
|
|
27
|
+
io: CliIo;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const EPILOG = `Environment:
|
|
31
|
+
OBBYX_HOME wallet directory (default ~/.obbyx)
|
|
32
|
+
LOG_LEVEL logging to stderr (default warn)
|
|
33
|
+
|
|
34
|
+
Exit codes: 0 ok, 1 error/usage, 2 refused (HTTP error, faucet refusal), 3 pending (retry later)`;
|
|
35
|
+
|
|
36
|
+
function commands(state: RunState): { top: AnyCmd[]; channel: AnyCmd[] } {
|
|
37
|
+
const ctx: CommandContext = {
|
|
38
|
+
out: state.io.out,
|
|
39
|
+
err: state.io.err,
|
|
40
|
+
done: (code) => {
|
|
41
|
+
state.code = code;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
top: [
|
|
46
|
+
initCommand(ctx),
|
|
47
|
+
addressCommand(ctx),
|
|
48
|
+
balanceCommand(ctx),
|
|
49
|
+
faucetCommand(ctx),
|
|
50
|
+
payCommand(ctx),
|
|
51
|
+
doctorCommand(ctx),
|
|
52
|
+
logsCommand(ctx),
|
|
53
|
+
decodeCommand(ctx),
|
|
54
|
+
] as AnyCmd[],
|
|
55
|
+
channel: channelCommands(ctx) as AnyCmd[],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Builds the yargs parser. `width` fixes the help width (docs generation). */
|
|
60
|
+
export function buildCli(argv: readonly string[], state: RunState, width?: number): Argv {
|
|
61
|
+
const defs = commands(state);
|
|
62
|
+
let cli: Argv = yargs([...argv])
|
|
63
|
+
.scriptName('obbyx')
|
|
64
|
+
.usage('obbyx — x402 payments on Obyte\n\nUsage: $0 <command> [options]')
|
|
65
|
+
.option('network', {
|
|
66
|
+
type: 'string',
|
|
67
|
+
default: 'testnet',
|
|
68
|
+
global: true,
|
|
69
|
+
choices: ['testnet', 'livenet', 'obyte:testnet', 'obyte:livenet'],
|
|
70
|
+
describe: 'Obyte network',
|
|
71
|
+
})
|
|
72
|
+
.option('hub', { type: 'string', global: true, describe: 'Obyte hub WebSocket URL' });
|
|
73
|
+
for (const c of defs.top) cli = cli.command(c as unknown as CommandModule);
|
|
74
|
+
cli = cli
|
|
75
|
+
.command('channel', 'Payment channels: open, list, status, deposit, close, confirm', (y) => {
|
|
76
|
+
let ch = y;
|
|
77
|
+
for (const c of defs.channel) ch = ch.command(c as unknown as CommandModule);
|
|
78
|
+
return ch.demandCommand(1, 'Choose a channel command').strict();
|
|
79
|
+
})
|
|
80
|
+
.demandCommand(1, 'Choose a command')
|
|
81
|
+
.recommendCommands()
|
|
82
|
+
.strict()
|
|
83
|
+
.epilog(EPILOG)
|
|
84
|
+
.alias('h', 'help')
|
|
85
|
+
.version(false)
|
|
86
|
+
.exitProcess(false)
|
|
87
|
+
.showHelpOnFail(false)
|
|
88
|
+
.wrap(width ?? Math.min(100, process.stdout.columns ?? 100))
|
|
89
|
+
.fail((msg, e) => {
|
|
90
|
+
throw (
|
|
91
|
+
e ??
|
|
92
|
+
new ObbyxError('usage', msg.startsWith('Did you mean') ? `Unknown command. ${msg}` : msg)
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
return cli;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Runs the CLI; returns the process exit code. */
|
|
99
|
+
export async function runCli(argv: readonly string[], io: CliIo): Promise<number> {
|
|
100
|
+
const state: RunState = { code: 0, io };
|
|
101
|
+
try {
|
|
102
|
+
let helpOutput = '';
|
|
103
|
+
await buildCli(argv, state).parseAsync([...argv], {}, (_e, _a, output) => {
|
|
104
|
+
helpOutput = output;
|
|
105
|
+
});
|
|
106
|
+
if (helpOutput) io.out(helpOutput);
|
|
107
|
+
return state.code;
|
|
108
|
+
} catch (e) {
|
|
109
|
+
io.err(`error: ${e instanceof Error ? e.message : String(e)}`);
|
|
110
|
+
if (e instanceof ObbyxError && e.code === 'usage') io.err('Run `obbyx --help` for usage.');
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Help text of a command path (e.g. `['channel', 'open']`), for the generated CLI reference. */
|
|
116
|
+
export async function renderHelp(path: readonly string[], width = 100): Promise<string> {
|
|
117
|
+
const state: RunState = { code: 0, io: { out: () => undefined, err: () => undefined } };
|
|
118
|
+
let text = '';
|
|
119
|
+
await buildCli([...path, '--help'], state, width).parseAsync(
|
|
120
|
+
[...path, '--help'],
|
|
121
|
+
{},
|
|
122
|
+
(_e, _a, output) => {
|
|
123
|
+
text = output;
|
|
124
|
+
},
|
|
125
|
+
);
|
|
126
|
+
return text;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Command paths for the reference, in display order (from the same definitions). */
|
|
130
|
+
export function commandPaths(): string[][] {
|
|
131
|
+
const defs = commands({ code: 0, io: { out: () => undefined, err: () => undefined } });
|
|
132
|
+
const name = (c: AnyCmd) => String(c.command).split(' ')[0] ?? '';
|
|
133
|
+
return [
|
|
134
|
+
[],
|
|
135
|
+
...defs.top.map((c) => [name(c)]),
|
|
136
|
+
['channel'],
|
|
137
|
+
...defs.channel.map((c) => ['channel', name(c)]),
|
|
138
|
+
];
|
|
139
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { loadWallet } from '@obbyx/obyte/wallet';
|
|
2
|
+
import { resolveNetwork } from '../runtime.js';
|
|
3
|
+
import type { CommandContext, Cmd } from './types.js';
|
|
4
|
+
|
|
5
|
+
export function addressCommand({ out, done }: CommandContext): Cmd {
|
|
6
|
+
return {
|
|
7
|
+
command: 'address',
|
|
8
|
+
describe: 'Show your address',
|
|
9
|
+
handler: (a) => {
|
|
10
|
+
out(loadWallet(resolveNetwork(a.network)).address);
|
|
11
|
+
done(0);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { toDisplay } from '@obbyx/obyte';
|
|
2
|
+
import { loadWallet } from '@obbyx/obyte/wallet';
|
|
3
|
+
import { connect, resolveNetwork } from '../runtime.js';
|
|
4
|
+
import type { CommandContext, Cmd } from './types.js';
|
|
5
|
+
|
|
6
|
+
export function balanceCommand({ out, done }: CommandContext): Cmd {
|
|
7
|
+
return {
|
|
8
|
+
command: 'balance',
|
|
9
|
+
describe: 'Show your balance',
|
|
10
|
+
handler: async (a) => {
|
|
11
|
+
const network = resolveNetwork(a.network);
|
|
12
|
+
const wallet = loadWallet(network);
|
|
13
|
+
const client = connect(network, a.hub);
|
|
14
|
+
try {
|
|
15
|
+
const balances = (await client.api.getBalances([wallet.address])) as Record<
|
|
16
|
+
string,
|
|
17
|
+
Record<string, { stable: number; pending: number }>
|
|
18
|
+
>;
|
|
19
|
+
const mine = balances[wallet.address] ?? {};
|
|
20
|
+
const bytes = mine['base'] ?? { stable: 0, pending: 0 };
|
|
21
|
+
out(`${wallet.address} on ${network.caip2}`);
|
|
22
|
+
out(
|
|
23
|
+
` GBYTE: ${toDisplay(BigInt(bytes.stable), 9)} stable, ${toDisplay(BigInt(bytes.pending), 9)} pending`,
|
|
24
|
+
);
|
|
25
|
+
for (const [asset, b] of Object.entries(mine)) {
|
|
26
|
+
if (asset !== 'base')
|
|
27
|
+
out(` ${asset}: ${b.stable} stable, ${b.pending} pending (atomic units)`);
|
|
28
|
+
}
|
|
29
|
+
} finally {
|
|
30
|
+
client.close();
|
|
31
|
+
}
|
|
32
|
+
done(0);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|