@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.
Files changed (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +24 -2
  3. package/dist/cli.d.ts +24 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +117 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/address.d.ts +3 -0
  8. package/dist/commands/address.d.ts.map +1 -0
  9. package/dist/commands/address.js +13 -0
  10. package/dist/commands/address.js.map +1 -0
  11. package/dist/commands/balance.d.ts +3 -0
  12. package/dist/commands/balance.d.ts.map +1 -0
  13. package/dist/commands/balance.js +30 -0
  14. package/dist/commands/balance.js.map +1 -0
  15. package/dist/commands/channel-cli.d.ts +11 -0
  16. package/dist/commands/channel-cli.d.ts.map +1 -0
  17. package/dist/commands/channel-cli.js +77 -0
  18. package/dist/commands/channel-cli.js.map +1 -0
  19. package/dist/commands/channel.d.ts +11 -0
  20. package/dist/commands/channel.d.ts.map +1 -0
  21. package/dist/commands/channel.js +77 -0
  22. package/dist/commands/channel.js.map +1 -0
  23. package/dist/commands/decode.d.ts +5 -0
  24. package/dist/commands/decode.d.ts.map +1 -0
  25. package/dist/commands/decode.js +17 -0
  26. package/dist/commands/decode.js.map +1 -0
  27. package/dist/commands/doctor-command.d.ts +5 -0
  28. package/dist/commands/doctor-command.d.ts.map +1 -0
  29. package/dist/commands/doctor-command.js +17 -0
  30. package/dist/commands/doctor-command.js.map +1 -0
  31. package/dist/commands/doctor.d.ts +5 -0
  32. package/dist/commands/doctor.d.ts.map +1 -0
  33. package/dist/commands/doctor.js +17 -0
  34. package/dist/commands/doctor.js.map +1 -0
  35. package/dist/commands/faucet.d.ts +5 -0
  36. package/dist/commands/faucet.d.ts.map +1 -0
  37. package/dist/commands/faucet.js +42 -0
  38. package/dist/commands/faucet.js.map +1 -0
  39. package/dist/commands/init.d.ts +5 -0
  40. package/dist/commands/init.d.ts.map +1 -0
  41. package/dist/commands/init.js +26 -0
  42. package/dist/commands/init.js.map +1 -0
  43. package/dist/commands/logs-command.d.ts +12 -0
  44. package/dist/commands/logs-command.d.ts.map +1 -0
  45. package/dist/commands/logs-command.js +32 -0
  46. package/dist/commands/logs-command.js.map +1 -0
  47. package/dist/commands/logs.d.ts +12 -0
  48. package/dist/commands/logs.d.ts.map +1 -0
  49. package/dist/commands/logs.js +32 -0
  50. package/dist/commands/logs.js.map +1 -0
  51. package/dist/commands/pay.d.ts +14 -0
  52. package/dist/commands/pay.d.ts.map +1 -0
  53. package/dist/commands/pay.js +115 -0
  54. package/dist/commands/pay.js.map +1 -0
  55. package/dist/commands/types.d.ts +27 -0
  56. package/dist/commands/types.d.ts.map +1 -0
  57. package/dist/commands/types.js +2 -0
  58. package/dist/commands/types.js.map +1 -0
  59. package/dist/faucet/device.d.ts +74 -0
  60. package/dist/faucet/device.d.ts.map +1 -0
  61. package/dist/faucet/device.js +222 -0
  62. package/dist/faucet/device.js.map +1 -0
  63. package/dist/faucet/faucet.d.ts +40 -0
  64. package/dist/faucet/faucet.d.ts.map +1 -0
  65. package/dist/faucet/faucet.js +111 -0
  66. package/dist/faucet/faucet.js.map +1 -0
  67. package/dist/lib/channels.d.ts +24 -0
  68. package/dist/lib/channels.d.ts.map +1 -0
  69. package/dist/lib/channels.js +111 -0
  70. package/dist/lib/channels.js.map +1 -0
  71. package/dist/lib/doctor.d.ts +7 -0
  72. package/dist/lib/doctor.d.ts.map +1 -0
  73. package/dist/lib/doctor.js +97 -0
  74. package/dist/lib/doctor.js.map +1 -0
  75. package/dist/lib/logs.d.ts +16 -0
  76. package/dist/lib/logs.d.ts.map +1 -0
  77. package/dist/lib/logs.js +64 -0
  78. package/dist/lib/logs.js.map +1 -0
  79. package/dist/main.d.ts +3 -0
  80. package/dist/main.d.ts.map +1 -0
  81. package/dist/main.js +11 -0
  82. package/dist/main.js.map +1 -0
  83. package/dist/runtime.d.ts +21 -0
  84. package/dist/runtime.d.ts.map +1 -0
  85. package/dist/runtime.js +86 -0
  86. package/dist/runtime.js.map +1 -0
  87. package/package.json +52 -3
  88. package/src/cli.ts +139 -0
  89. package/src/commands/address.ts +14 -0
  90. package/src/commands/balance.ts +35 -0
  91. package/src/commands/channel.ts +96 -0
  92. package/src/commands/decode.ts +19 -0
  93. package/src/commands/doctor.ts +21 -0
  94. package/src/commands/faucet.ts +48 -0
  95. package/src/commands/init.ts +28 -0
  96. package/src/commands/logs.ts +48 -0
  97. package/src/commands/pay.ts +135 -0
  98. package/src/commands/types.ts +31 -0
  99. package/src/faucet/device.ts +330 -0
  100. package/src/faucet/faucet.ts +141 -0
  101. package/src/lib/channels.ts +161 -0
  102. package/src/lib/doctor.ts +133 -0
  103. package/src/lib/logs.ts +79 -0
  104. package/src/main.ts +14 -0
  105. package/src/runtime.ts +123 -0
@@ -0,0 +1,222 @@
1
+ // Ambient types for obyte.js internals (declaration only, no code).
2
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
3
+ /// <reference path="../../../obyte/src/types/obyte-internal.d.ts" />
4
+ import { createCipheriv, createDecipheriv, createECDH, createHash, randomBytes } from 'node:crypto';
5
+ import obyte from 'obyte';
6
+ import { chashGetChash160, getSourceString, sign, toPublicKey, verify, } from 'obyte/lib/internal.js';
7
+ import { ObbyxError } from '@obbyx/obyte';
8
+ import { startHeartbeat } from '@obbyx/x402-obyte';
9
+ import { moduleLogger } from '@obbyx/obyte/logger';
10
+ export function newDeviceKey() {
11
+ for (;;) {
12
+ const priv = randomBytes(32);
13
+ try {
14
+ return { priv, pub: toPublicKey(priv) };
15
+ }
16
+ catch {
17
+ // invalid scalar, retry
18
+ }
19
+ }
20
+ }
21
+ export function deviceKeyFrom(priv) {
22
+ return { priv, pub: toPublicKey(priv) };
23
+ }
24
+ /** ocore object_hash.getDeviceAddress: '0' + chash160("s\0" + pubkey) (source-string form of a string). */
25
+ export function deviceAddress(pubkey) {
26
+ return `0${chashGetChash160(`s\x00${pubkey}`)}`;
27
+ }
28
+ /** sha256 of the source string with nulls removed and without `signature` (ocore getDeviceMessageHashToSign). */
29
+ export function deviceMessageHashToSign(message) {
30
+ const naked = { ...message };
31
+ delete naked['signature'];
32
+ return createHash('sha256')
33
+ .update(getSourceString(cleanNullsDeep(naked)), 'utf8')
34
+ .digest();
35
+ }
36
+ function cleanNullsDeep(value) {
37
+ if (Array.isArray(value))
38
+ return value.map(cleanNullsDeep);
39
+ if (value !== null && typeof value === 'object') {
40
+ return Object.fromEntries(Object.entries(value)
41
+ .filter(([, v]) => v !== null && v !== undefined)
42
+ .map(([k, v]) => [k, cleanNullsDeep(v)]));
43
+ }
44
+ return value;
45
+ }
46
+ export function signDeviceMessage(message, key) {
47
+ return { ...message, signature: sign(deviceMessageHashToSign(message), key.priv) };
48
+ }
49
+ export function sharedSecret(peerPubkey, priv) {
50
+ const ecdh = createECDH('secp256k1');
51
+ ecdh.setPrivateKey(Buffer.from(priv));
52
+ const x = ecdh.computeSecret(Buffer.from(peerPubkey, 'base64'));
53
+ return createHash('sha256').update(x).digest().subarray(0, 16);
54
+ }
55
+ export function encryptPackage(json, recipientPubkey) {
56
+ const ephemeral = newDeviceKey();
57
+ const iv = randomBytes(12);
58
+ const cipher = createCipheriv('aes-128-gcm', sharedSecret(recipientPubkey, ephemeral.priv), iv);
59
+ const encrypted = Buffer.concat([cipher.update(JSON.stringify(json), 'utf8'), cipher.final()]);
60
+ return {
61
+ encrypted_message: encrypted.toString('base64'),
62
+ iv: iv.toString('base64'),
63
+ authtag: cipher.getAuthTag().toString('base64'),
64
+ dh: { sender_ephemeral_pubkey: ephemeral.pub, recipient_ephemeral_pubkey: recipientPubkey },
65
+ };
66
+ }
67
+ export function decryptPackage(pkg, keys) {
68
+ const key = keys.find((k) => k.pub === pkg.dh.recipient_ephemeral_pubkey);
69
+ if (key === undefined)
70
+ throw new ObbyxError('device_unknown_key', 'Message encrypted to an unknown key');
71
+ const decipher = createDecipheriv('aes-128-gcm', sharedSecret(pkg.dh.sender_ephemeral_pubkey, key.priv), Buffer.from(pkg.iv, 'base64'));
72
+ decipher.setAuthTag(Buffer.from(pkg.authtag, 'base64'));
73
+ const text = Buffer.concat([
74
+ decipher.update(Buffer.from(pkg.encrypted_message, 'base64')),
75
+ decipher.final(),
76
+ ]).toString('utf8');
77
+ const json = JSON.parse(text);
78
+ return json.encrypted_package === undefined ? json : decryptPackage(json.encrypted_package, keys);
79
+ }
80
+ export class DeviceSession {
81
+ client;
82
+ key;
83
+ hubHost;
84
+ address;
85
+ temp;
86
+ listeners = new Set();
87
+ log;
88
+ stopHeartbeat;
89
+ constructor(client, key, hubHost, logger, temp) {
90
+ this.client = client;
91
+ this.key = key;
92
+ this.hubHost = hubHost;
93
+ // The temp key is persisted by the caller (like ocore) so messages queued
94
+ // at the hub for the previous session can still be decrypted.
95
+ this.temp = temp ?? newDeviceKey();
96
+ this.address = deviceAddress(key.pub);
97
+ this.stopHeartbeat = startHeartbeat(client);
98
+ this.log = moduleLogger(logger, 'device', { device: this.address });
99
+ }
100
+ /** Connects to `wss://<hubHost>`, logs in with the permanent key and registers a temp key. */
101
+ static async connect(options) {
102
+ const client = new obyte.Client(`wss://${options.hubHost}`, {
103
+ testnet: options.testnet,
104
+ reconnect: true,
105
+ });
106
+ const session = new DeviceSession(client, options.key, options.hubHost, options.logger, options.tempKey);
107
+ const firstLogin = new Promise((resolve, reject) => {
108
+ const timer = setTimeout(() => reject(new ObbyxError('device_hub_timeout', `Could not log in to ${options.hubHost}`)), options.timeoutMs ?? 15_000);
109
+ // Per obyte.js: subscriptions and hub login live for ONE connection, so
110
+ // everything per-connection is (re)done in onConnect after every reconnect.
111
+ client.onConnect(() => {
112
+ client.subscribe((_err, message) => {
113
+ if (!Array.isArray(message) || message[0] !== 'justsaying')
114
+ return;
115
+ const { subject, body } = message[1];
116
+ if (subject === 'hub/challenge' && typeof body === 'string') {
117
+ session.login(body).then(() => {
118
+ clearTimeout(timer);
119
+ resolve();
120
+ }, (err) => session.log.error({ err }, 'hub login failed'));
121
+ }
122
+ else if (subject === 'hub/message') {
123
+ session.onHubMessage(body);
124
+ }
125
+ });
126
+ });
127
+ });
128
+ try {
129
+ await firstLogin;
130
+ }
131
+ catch (err) {
132
+ session.close();
133
+ throw err;
134
+ }
135
+ return session;
136
+ }
137
+ /** Answers the hub challenge and registers our temp key (every connection). */
138
+ async login(challenge) {
139
+ this.client.justsaying('hub/login', signDeviceMessage({ challenge, pubkey: this.key.pub }, this.key));
140
+ const res = await this.api('tempPubkey', signDeviceMessage({ temp_pubkey: this.temp.pub, pubkey: this.key.pub }, this.key));
141
+ if (res !== 'updated') {
142
+ throw new ObbyxError('device_login_failed', `Hub did not accept the temp key: ${JSON.stringify(res)}`);
143
+ }
144
+ this.log.info({ hub: this.hubHost }, 'logged in to hub');
145
+ }
146
+ onMessage(listener) {
147
+ this.listeners.add(listener);
148
+ return () => this.listeners.delete(listener);
149
+ }
150
+ /** Sends {from, device_hub, subject, body} encrypted to the recipient's temp key. */
151
+ async send(recipientPubkey, subject, body) {
152
+ const temp = (await this.api('getTempPubkey', recipientPubkey));
153
+ if (typeof temp?.['temp_pubkey'] !== 'string' ||
154
+ temp['pubkey'] !== recipientPubkey ||
155
+ typeof temp['signature'] !== 'string' ||
156
+ !verify(deviceMessageHashToSign(temp), temp['signature'], recipientPubkey)) {
157
+ throw new ObbyxError('device_bad_temp_key', 'Recipient temp key is missing or not signed by the recipient');
158
+ }
159
+ const json = { from: this.address, device_hub: this.hubHost, subject, body };
160
+ const message = signDeviceMessage({
161
+ encrypted_package: encryptPackage(json, temp['temp_pubkey']),
162
+ to: deviceAddress(recipientPubkey),
163
+ pubkey: this.key.pub,
164
+ }, this.key);
165
+ const res = await this.api('deliver', message);
166
+ if (res !== 'accepted')
167
+ throw new ObbyxError('device_send_failed', `Hub did not accept the message: ${JSON.stringify(res)}`);
168
+ this.log.debug({ to: deviceAddress(recipientPubkey), subject }, 'message delivered to hub');
169
+ }
170
+ close() {
171
+ this.stopHeartbeat();
172
+ this.client.close();
173
+ }
174
+ async api(method, ...args) {
175
+ try {
176
+ const fn = this.client.api[method];
177
+ if (fn === undefined)
178
+ throw new Error(`obyte.js has no api.${method}`);
179
+ return await fn(...args);
180
+ }
181
+ catch (err) {
182
+ throw new ObbyxError('device_hub_error', `Hub request ${method} failed: ${typeof err === 'string' ? err : String(err)}`);
183
+ }
184
+ }
185
+ onHubMessage(body) {
186
+ const { message_hash: hash, message } = (body ?? {});
187
+ if (typeof hash !== 'string' || message === undefined)
188
+ return;
189
+ const ack = () => this.client.justsaying('hub/delete', hash);
190
+ try {
191
+ const pubkey = message['pubkey'];
192
+ if (message['to'] !== this.address ||
193
+ typeof pubkey !== 'string' ||
194
+ typeof message['signature'] !== 'string' ||
195
+ !verify(deviceMessageHashToSign(message), message['signature'], pubkey)) {
196
+ this.log.warn('dropping a message with a bad signature or recipient');
197
+ return ack();
198
+ }
199
+ const json = decryptPackage(message['encrypted_package'], [
200
+ this.temp,
201
+ this.key,
202
+ ]);
203
+ if (json.from !== deviceAddress(pubkey)) {
204
+ this.log.warn('dropping a message whose sender does not match its signature');
205
+ return ack();
206
+ }
207
+ const incoming = {
208
+ from: json.from,
209
+ fromPubkey: pubkey,
210
+ subject: String(json.subject),
211
+ body: json.body,
212
+ };
213
+ for (const listener of this.listeners)
214
+ listener(incoming);
215
+ }
216
+ catch (err) {
217
+ this.log.warn({ err }, 'failed to process an incoming message');
218
+ }
219
+ ack();
220
+ }
221
+ }
222
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/faucet/device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type ObyteNetwork } from '@obbyx/obyte';
2
+ import { type Logger } from '@obbyx/obyte/logger';
3
+ import { type DeviceKey } from './device.js';
4
+ /**
5
+ * Testnet faucet over the Obyte bot protocol (byteball/obyte-faucet):
6
+ * pair with the "Faucet Bot" listed by the testnet hub, send it our address,
7
+ * read its answer. The bot pays 0.5–1 GBYTE once per 24 h per device.
8
+ */
9
+ export type FaucetStatus = 'sent' | 'rate_limited' | 'rejected' | 'no_answer';
10
+ export interface FaucetResult {
11
+ readonly status: FaucetStatus;
12
+ readonly botMessages: readonly string[];
13
+ readonly bot: string;
14
+ }
15
+ export interface PairingCode {
16
+ readonly pubkey: string;
17
+ readonly hub: string;
18
+ readonly secret: string;
19
+ }
20
+ export declare function parsePairingCode(code: string): PairingCode;
21
+ /** Classifies the faucet bot's replies (texts from byteball/obyte-faucet start.js). */
22
+ export declare function classifyFaucetReply(text: string): FaucetStatus | undefined;
23
+ /**
24
+ * Device keys for the CLI (`$OBBYX_HOME/device-<network>.json`, mode 0600):
25
+ * the permanent key (identity towards bots) and the temp key used for
26
+ * encryption, both kept across sessions like ocore does.
27
+ */
28
+ export declare function loadOrCreateDeviceKeys(network: ObyteNetwork, env?: NodeJS.ProcessEnv): {
29
+ key: DeviceKey;
30
+ temp: DeviceKey;
31
+ };
32
+ export declare function requestFromFaucet(options: {
33
+ network: ObyteNetwork;
34
+ address: string;
35
+ logger: Logger;
36
+ timeoutMs?: number;
37
+ onBotText?: (text: string) => void;
38
+ env?: NodeJS.ProcessEnv;
39
+ }): Promise<FaucetResult>;
40
+ //# sourceMappingURL=faucet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faucet.d.ts","sourceRoot":"","sources":["../../src/faucet/faucet.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,KAAK,SAAS,EAA8C,MAAM,aAAa,CAAC;AAGzF;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAE9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO1D;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,YAAY,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAmBrC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,OAAO,CAAC,YAAY,CAAC,CA2DxB"}
@@ -0,0 +1,111 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import obyte from 'obyte';
5
+ import { ObbyxError } from '@obbyx/obyte';
6
+ import { moduleLogger } from '@obbyx/obyte/logger';
7
+ import { DeviceSession, deviceKeyFrom, newDeviceKey } from './device.js';
8
+ import { obbyxHome } from '@obbyx/obyte/wallet';
9
+ export function parsePairingCode(code) {
10
+ const m = /^([A-Za-z0-9+/]{43}[A-Za-z0-9+/=])@([\w.-]+(?:\/[\w.-]+)*)#(.+)$/.exec(code.trim());
11
+ const [, pubkey, hub, secret] = m ?? [];
12
+ if (pubkey === undefined || hub === undefined || secret === undefined) {
13
+ throw new ObbyxError('bad_pairing_code', `Not a pairing code: ${code}`);
14
+ }
15
+ return { pubkey, hub, secret };
16
+ }
17
+ /** Classifies the faucet bot's replies (texts from byteball/obyte-faucet start.js). */
18
+ export function classifyFaucetReply(text) {
19
+ if (/only once per 24 hours/i.test(text))
20
+ return 'rate_limited';
21
+ if (/valid address|unrecognized command/i.test(text))
22
+ return 'rejected';
23
+ if (/blackbytes/i.test(text))
24
+ return 'sent'; // sent after a successful payout
25
+ return undefined;
26
+ }
27
+ /**
28
+ * Device keys for the CLI (`$OBBYX_HOME/device-<network>.json`, mode 0600):
29
+ * the permanent key (identity towards bots) and the temp key used for
30
+ * encryption, both kept across sessions like ocore does.
31
+ */
32
+ export function loadOrCreateDeviceKeys(network, env = process.env) {
33
+ const path = join(obbyxHome(env), `device-${network.name}.json`);
34
+ const stored = existsSync(path)
35
+ ? JSON.parse(readFileSync(path, 'utf8'))
36
+ : undefined;
37
+ const key = stored ? deviceKeyFrom(Buffer.from(stored.priv, 'base64')) : newDeviceKey();
38
+ const temp = stored?.tempPriv
39
+ ? deviceKeyFrom(Buffer.from(stored.tempPriv, 'base64'))
40
+ : newDeviceKey();
41
+ if (stored?.tempPriv === undefined) {
42
+ mkdirSync(obbyxHome(env), { recursive: true, mode: 0o700 });
43
+ const body = {
44
+ priv: Buffer.from(key.priv).toString('base64'),
45
+ tempPriv: Buffer.from(temp.priv).toString('base64'),
46
+ };
47
+ writeFileSync(path, `${JSON.stringify(body)}\n`, { mode: 0o600 });
48
+ chmodSync(path, 0o600);
49
+ }
50
+ return { key, temp };
51
+ }
52
+ export async function requestFromFaucet(options) {
53
+ if (!options.network.testnet)
54
+ throw new ObbyxError('faucet_testnet_only', 'The faucet is available on testnet only');
55
+ const log = moduleLogger(options.logger, 'faucet');
56
+ // 1. Find the faucet bot in the hub's bot directory.
57
+ const directory = new obyte.Client(options.network.defaultHubUrl, { testnet: true });
58
+ let code;
59
+ let botName;
60
+ try {
61
+ const bots = await directory.api.getBots();
62
+ const bot = bots.find((b) => /faucet/i.test(b.name));
63
+ if (bot === undefined)
64
+ throw new ObbyxError('faucet_not_found', 'No faucet bot listed by the testnet hub');
65
+ code = parsePairingCode(bot.pairing_code);
66
+ botName = bot.name;
67
+ }
68
+ finally {
69
+ directory.close();
70
+ }
71
+ log.info({ bot: botName, hub: code.hub }, 'faucet bot found');
72
+ // 2. Log in to the bot's hub with our device key.
73
+ const { key, temp } = loadOrCreateDeviceKeys(options.network, options.env);
74
+ const session = await DeviceSession.connect({
75
+ hubHost: code.hub,
76
+ testnet: true,
77
+ key,
78
+ tempKey: temp,
79
+ logger: options.logger,
80
+ });
81
+ const texts = [];
82
+ try {
83
+ const result = new Promise((resolve) => {
84
+ const timer = setTimeout(() => resolve('no_answer'), options.timeoutMs ?? 60_000);
85
+ session.onMessage((m) => {
86
+ if (m.fromPubkey !== code.pubkey || m.subject !== 'text' || typeof m.body !== 'string')
87
+ return;
88
+ texts.push(m.body);
89
+ options.onBotText?.(m.body);
90
+ const status = classifyFaucetReply(m.body);
91
+ if (status !== undefined) {
92
+ clearTimeout(timer);
93
+ resolve(status);
94
+ }
95
+ });
96
+ });
97
+ // 3. Pair, then send our address.
98
+ await session.send(code.pubkey, 'pairing', {
99
+ pairing_secret: code.secret,
100
+ device_name: 'obbyx-cli',
101
+ reverse_pairing_secret: randomBytes(9).toString('base64'),
102
+ });
103
+ await session.send(code.pubkey, 'text', options.address);
104
+ log.info({ address: options.address }, 'address sent to the faucet');
105
+ return { status: await result, botMessages: texts, bot: botName };
106
+ }
107
+ finally {
108
+ session.close();
109
+ }
110
+ }
111
+ //# sourceMappingURL=faucet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faucet.js","sourceRoot":"","sources":["../../src/faucet/faucet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type obyte from 'obyte';
2
+ import { type ObyteNetwork } from '@obbyx/obyte';
3
+ import type { Logger } from '@obbyx/obyte/logger';
4
+ import { type ReservingComposer } from '@obbyx/x402-obyte';
5
+ /**
6
+ * `obbyx channel …` — the buyer's AA payment channels (party B).
7
+ * State lives in `$OBBYX_HOME/channels-<network>.db`.
8
+ */
9
+ export declare function channelStorePath(network: ObyteNetwork, env?: NodeJS.ProcessEnv): string;
10
+ export declare function channelCommand(args: {
11
+ sub: string | undefined;
12
+ target: string | undefined;
13
+ deposit?: string;
14
+ amount?: string;
15
+ timeout?: string;
16
+ }, ctx: {
17
+ network: ObyteNetwork;
18
+ client: obyte.Client;
19
+ privateKey: Uint8Array;
20
+ logger: Logger;
21
+ out: (s?: string) => void;
22
+ composer?: ReservingComposer;
23
+ }): Promise<number>;
24
+ //# sourceMappingURL=channels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/lib/channels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAQL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAG3B;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAER;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE;IACJ,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,EACD,GAAG,EAAE;IACH,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B,GACA,OAAO,CAAC,MAAM,CAAC,CAuGjB"}
@@ -0,0 +1,111 @@
1
+ import { join } from 'node:path';
2
+ import { ObbyxError, explorerUnitUrl, fromDisplay, toDisplay, } from '@obbyx/obyte';
3
+ import { ClientChannelStore, closeChannel, confirmClose, deposit, hubCall, openChannel, } from '@obbyx/x402-obyte';
4
+ import { obbyxHome } from '@obbyx/obyte/wallet';
5
+ /**
6
+ * `obbyx channel …` — the buyer's AA payment channels (party B).
7
+ * State lives in `$OBBYX_HOME/channels-<network>.db`.
8
+ */
9
+ export function channelStorePath(network, env = process.env) {
10
+ return join(obbyxHome(env), `channels-${network.name}.db`);
11
+ }
12
+ export async function channelCommand(args, ctx) {
13
+ const store = new ClientChannelStore(channelStorePath(ctx.network));
14
+ const opts = {
15
+ client: ctx.client,
16
+ network: ctx.network,
17
+ privateKey: ctx.privateKey,
18
+ store,
19
+ logger: ctx.logger,
20
+ ...(ctx.composer ? { composer: ctx.composer } : {}),
21
+ };
22
+ const { out } = ctx;
23
+ const gbyte = (v) => `${toDisplay(v, 9)} GBYTE`;
24
+ try {
25
+ switch (args.sub) {
26
+ case 'open': {
27
+ if (args.target === undefined)
28
+ throw new ObbyxError('usage', 'channel open <seller address> --deposit <GBYTE>');
29
+ if (args.deposit === undefined)
30
+ throw new ObbyxError('usage', 'channel open needs --deposit <GBYTE>');
31
+ const timeout = Number(args.timeout ?? 86_400);
32
+ if (!Number.isInteger(timeout) || timeout < 60)
33
+ throw new ObbyxError('usage', '--window must be ≥ 60 seconds');
34
+ const { aa, unit } = await openChannel(opts, {
35
+ payTo: args.target,
36
+ deposit: fromDisplay(args.deposit, 9),
37
+ timeout,
38
+ });
39
+ out(`Channel ${aa} opened to ${args.target}`);
40
+ out(` deposit: ${args.deposit} GBYTE, dispute window: ${timeout} s`);
41
+ out(` unit: ${unit}\n ${explorerUnitUrl(ctx.network, unit)}`);
42
+ out('Usable once the deposit is stable (minutes under load, up to ~2 h when the network is quiet): obbyx channel status ' +
43
+ aa);
44
+ return 0;
45
+ }
46
+ case 'deposit': {
47
+ const ch = need(store, args.target);
48
+ if (args.amount === undefined)
49
+ throw new ObbyxError('usage', 'channel deposit <aa> --amount <GBYTE>');
50
+ const unit = await deposit(opts, ch.aa, fromDisplay(args.amount, 9));
51
+ out(`Deposited ${args.amount} GBYTE to ${ch.aa}: ${unit}`);
52
+ return 0;
53
+ }
54
+ case 'list': {
55
+ const all = store.list().filter((c) => c.network === ctx.network.caip2);
56
+ if (all.length === 0)
57
+ out('No channels. Open one with: obbyx channel open <seller> --deposit <GBYTE>');
58
+ for (const c of all) {
59
+ out(`${c.aa} seller ${c.payTo} period ${c.period} spent ${gbyte(c.committed)}${c.pending ? ' (voucher pending)' : ''}`);
60
+ }
61
+ return 0;
62
+ }
63
+ case 'status': {
64
+ const ch = need(store, args.target);
65
+ const vars = await hubCall(() => ctx.client.api.getAaStateVars({ address: ch.aa }), 15_000);
66
+ if (vars.kind !== 'ok')
67
+ throw new ObbyxError('ledger_unavailable', vars.error);
68
+ const v = vars.value;
69
+ out(`Channel ${ch.aa} → seller ${ch.payTo}`);
70
+ out(` on-chain: period ${v['period'] ?? '-'}, deposit ${gbyte(BigInt(Number(v['balanceB'] ?? 0)))}` +
71
+ (v['close_initiated_by']
72
+ ? `, CLOSING (initiated by ${v['close_initiated_by'] === 'A' ? 'seller' : 'you'})`
73
+ : ''));
74
+ out(` local: period ${ch.period}, spent ${gbyte(ch.committed)}${ch.pending ? `, pending voucher ${ch.pending.amountSpent}` : ''}`);
75
+ if (v['period'] === undefined)
76
+ out(' The deposit is not credited yet (waiting for stability).');
77
+ return 0;
78
+ }
79
+ case 'close': {
80
+ const ch = need(store, args.target);
81
+ if (ch.pending) {
82
+ throw new ObbyxError('payment_pending', 'A voucher has an unknown outcome; retry that request before closing');
83
+ }
84
+ const unit = await closeChannel(opts, ch.aa, ch.period, ch.committed);
85
+ out(`Close requested for period ${ch.period}, declaring ${gbyte(ch.committed)} spent: ${unit}`);
86
+ out(`The seller confirms at once if this is right; otherwise run \`obbyx channel confirm ${ch.aa}\` after ${ch.timeout} s.`);
87
+ return 0;
88
+ }
89
+ case 'confirm': {
90
+ const ch = need(store, args.target);
91
+ const unit = await confirmClose(opts, ch.aa, ch.period);
92
+ out(`Close confirmed for period ${ch.period}: ${unit}`);
93
+ return 0;
94
+ }
95
+ default:
96
+ throw new ObbyxError('usage', 'channel open|deposit|list|status|close|confirm');
97
+ }
98
+ }
99
+ finally {
100
+ store.close();
101
+ }
102
+ }
103
+ function need(store, aa) {
104
+ if (aa === undefined)
105
+ throw new ObbyxError('usage', 'channel address required');
106
+ const ch = store.get(aa);
107
+ if (ch === undefined)
108
+ throw new ObbyxError('no_channel', `Unknown channel ${aa} (see: obbyx channel list)`);
109
+ return ch;
110
+ }
111
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/lib/channels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type ObyteNetwork } from '@obbyx/obyte';
2
+ export declare function doctor(network: ObyteNetwork, opts: {
3
+ hub?: string;
4
+ facilitator?: string;
5
+ out: (s: string) => void;
6
+ }): Promise<number>;
7
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/lib/doctor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,cAAc,CAAC;AAW5D,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GACrE,OAAO,CAAC,MAAM,CAAC,CAmHjB"}