@paybox-sh/sdk 1.0.0 → 2.0.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/dist/cli.js CHANGED
@@ -1,23 +1,688 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PayboxClient,
4
- agentClientId,
5
4
  appBaseFrom,
6
5
  configDir,
7
6
  configFile,
8
7
  didNotHappen,
8
+ encodeToken,
9
9
  loadConfig,
10
10
  loginDevice,
11
11
  openBrowser,
12
+ refreshTokens,
12
13
  saveConfig
13
- } from "./chunk-SMPW2GUM.js";
14
+ } from "./chunk-66FQ2R7G.js";
14
15
 
15
16
  // src/cli.ts
16
17
  import { spawnSync } from "node:child_process";
17
18
  import { readFileSync, rmSync } from "node:fs";
18
19
  import { createRequire } from "node:module";
19
- import { createInterface } from "node:readline/promises";
20
20
  import { Command } from "commander";
21
+
22
+ // src/pairing.ts
23
+ import nacl from "tweetnacl";
24
+
25
+ // node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/utils.js
26
+ function isBytes(a) {
27
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
28
+ }
29
+ function abytes(b, ...lengths) {
30
+ if (!isBytes(b))
31
+ throw new Error("Uint8Array expected");
32
+ if (lengths.length > 0 && !lengths.includes(b.length))
33
+ throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
34
+ }
35
+ function aexists(instance, checkFinished = true) {
36
+ if (instance.destroyed)
37
+ throw new Error("Hash instance has been destroyed");
38
+ if (checkFinished && instance.finished)
39
+ throw new Error("Hash#digest() has already been called");
40
+ }
41
+ function aoutput(out, instance) {
42
+ abytes(out);
43
+ const min = instance.outputLen;
44
+ if (out.length < min) {
45
+ throw new Error("digestInto() expects output buffer of length at least " + min);
46
+ }
47
+ }
48
+ function clean(...arrays) {
49
+ for (let i = 0; i < arrays.length; i++) {
50
+ arrays[i].fill(0);
51
+ }
52
+ }
53
+ function createView(arr) {
54
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
55
+ }
56
+ function rotr(word, shift) {
57
+ return word << 32 - shift | word >>> shift;
58
+ }
59
+ function utf8ToBytes(str) {
60
+ if (typeof str !== "string")
61
+ throw new Error("string expected");
62
+ return new Uint8Array(new TextEncoder().encode(str));
63
+ }
64
+ function toBytes(data) {
65
+ if (typeof data === "string")
66
+ data = utf8ToBytes(data);
67
+ abytes(data);
68
+ return data;
69
+ }
70
+ var Hash = class {
71
+ };
72
+ function createHasher(hashCons) {
73
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
74
+ const tmp = hashCons();
75
+ hashC.outputLen = tmp.outputLen;
76
+ hashC.blockLen = tmp.blockLen;
77
+ hashC.create = () => hashCons();
78
+ return hashC;
79
+ }
80
+
81
+ // node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/_md.js
82
+ function setBigUint64(view, byteOffset, value, isLE) {
83
+ if (typeof view.setBigUint64 === "function")
84
+ return view.setBigUint64(byteOffset, value, isLE);
85
+ const _32n = BigInt(32);
86
+ const _u32_max = BigInt(4294967295);
87
+ const wh = Number(value >> _32n & _u32_max);
88
+ const wl = Number(value & _u32_max);
89
+ const h = isLE ? 4 : 0;
90
+ const l = isLE ? 0 : 4;
91
+ view.setUint32(byteOffset + h, wh, isLE);
92
+ view.setUint32(byteOffset + l, wl, isLE);
93
+ }
94
+ function Chi(a, b, c) {
95
+ return a & b ^ ~a & c;
96
+ }
97
+ function Maj(a, b, c) {
98
+ return a & b ^ a & c ^ b & c;
99
+ }
100
+ var HashMD = class extends Hash {
101
+ constructor(blockLen, outputLen, padOffset, isLE) {
102
+ super();
103
+ this.finished = false;
104
+ this.length = 0;
105
+ this.pos = 0;
106
+ this.destroyed = false;
107
+ this.blockLen = blockLen;
108
+ this.outputLen = outputLen;
109
+ this.padOffset = padOffset;
110
+ this.isLE = isLE;
111
+ this.buffer = new Uint8Array(blockLen);
112
+ this.view = createView(this.buffer);
113
+ }
114
+ update(data) {
115
+ aexists(this);
116
+ data = toBytes(data);
117
+ abytes(data);
118
+ const { view, buffer, blockLen } = this;
119
+ const len = data.length;
120
+ for (let pos = 0; pos < len; ) {
121
+ const take = Math.min(blockLen - this.pos, len - pos);
122
+ if (take === blockLen) {
123
+ const dataView = createView(data);
124
+ for (; blockLen <= len - pos; pos += blockLen)
125
+ this.process(dataView, pos);
126
+ continue;
127
+ }
128
+ buffer.set(data.subarray(pos, pos + take), this.pos);
129
+ this.pos += take;
130
+ pos += take;
131
+ if (this.pos === blockLen) {
132
+ this.process(view, 0);
133
+ this.pos = 0;
134
+ }
135
+ }
136
+ this.length += data.length;
137
+ this.roundClean();
138
+ return this;
139
+ }
140
+ digestInto(out) {
141
+ aexists(this);
142
+ aoutput(out, this);
143
+ this.finished = true;
144
+ const { buffer, view, blockLen, isLE } = this;
145
+ let { pos } = this;
146
+ buffer[pos++] = 128;
147
+ clean(this.buffer.subarray(pos));
148
+ if (this.padOffset > blockLen - pos) {
149
+ this.process(view, 0);
150
+ pos = 0;
151
+ }
152
+ for (let i = pos; i < blockLen; i++)
153
+ buffer[i] = 0;
154
+ setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
155
+ this.process(view, 0);
156
+ const oview = createView(out);
157
+ const len = this.outputLen;
158
+ if (len % 4)
159
+ throw new Error("_sha2: outputLen should be aligned to 32bit");
160
+ const outLen = len / 4;
161
+ const state = this.get();
162
+ if (outLen > state.length)
163
+ throw new Error("_sha2: outputLen bigger than state");
164
+ for (let i = 0; i < outLen; i++)
165
+ oview.setUint32(4 * i, state[i], isLE);
166
+ }
167
+ digest() {
168
+ const { buffer, outputLen } = this;
169
+ this.digestInto(buffer);
170
+ const res = buffer.slice(0, outputLen);
171
+ this.destroy();
172
+ return res;
173
+ }
174
+ _cloneInto(to) {
175
+ to || (to = new this.constructor());
176
+ to.set(...this.get());
177
+ const { blockLen, buffer, length, finished, destroyed, pos } = this;
178
+ to.destroyed = destroyed;
179
+ to.finished = finished;
180
+ to.length = length;
181
+ to.pos = pos;
182
+ if (length % blockLen)
183
+ to.buffer.set(buffer);
184
+ return to;
185
+ }
186
+ clone() {
187
+ return this._cloneInto();
188
+ }
189
+ };
190
+ var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
191
+ 1779033703,
192
+ 3144134277,
193
+ 1013904242,
194
+ 2773480762,
195
+ 1359893119,
196
+ 2600822924,
197
+ 528734635,
198
+ 1541459225
199
+ ]);
200
+
201
+ // node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha2.js
202
+ var SHA256_K = /* @__PURE__ */ Uint32Array.from([
203
+ 1116352408,
204
+ 1899447441,
205
+ 3049323471,
206
+ 3921009573,
207
+ 961987163,
208
+ 1508970993,
209
+ 2453635748,
210
+ 2870763221,
211
+ 3624381080,
212
+ 310598401,
213
+ 607225278,
214
+ 1426881987,
215
+ 1925078388,
216
+ 2162078206,
217
+ 2614888103,
218
+ 3248222580,
219
+ 3835390401,
220
+ 4022224774,
221
+ 264347078,
222
+ 604807628,
223
+ 770255983,
224
+ 1249150122,
225
+ 1555081692,
226
+ 1996064986,
227
+ 2554220882,
228
+ 2821834349,
229
+ 2952996808,
230
+ 3210313671,
231
+ 3336571891,
232
+ 3584528711,
233
+ 113926993,
234
+ 338241895,
235
+ 666307205,
236
+ 773529912,
237
+ 1294757372,
238
+ 1396182291,
239
+ 1695183700,
240
+ 1986661051,
241
+ 2177026350,
242
+ 2456956037,
243
+ 2730485921,
244
+ 2820302411,
245
+ 3259730800,
246
+ 3345764771,
247
+ 3516065817,
248
+ 3600352804,
249
+ 4094571909,
250
+ 275423344,
251
+ 430227734,
252
+ 506948616,
253
+ 659060556,
254
+ 883997877,
255
+ 958139571,
256
+ 1322822218,
257
+ 1537002063,
258
+ 1747873779,
259
+ 1955562222,
260
+ 2024104815,
261
+ 2227730452,
262
+ 2361852424,
263
+ 2428436474,
264
+ 2756734187,
265
+ 3204031479,
266
+ 3329325298
267
+ ]);
268
+ var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
269
+ var SHA256 = class extends HashMD {
270
+ constructor(outputLen = 32) {
271
+ super(64, outputLen, 8, false);
272
+ this.A = SHA256_IV[0] | 0;
273
+ this.B = SHA256_IV[1] | 0;
274
+ this.C = SHA256_IV[2] | 0;
275
+ this.D = SHA256_IV[3] | 0;
276
+ this.E = SHA256_IV[4] | 0;
277
+ this.F = SHA256_IV[5] | 0;
278
+ this.G = SHA256_IV[6] | 0;
279
+ this.H = SHA256_IV[7] | 0;
280
+ }
281
+ get() {
282
+ const { A, B, C, D, E, F, G, H } = this;
283
+ return [A, B, C, D, E, F, G, H];
284
+ }
285
+ // prettier-ignore
286
+ set(A, B, C, D, E, F, G, H) {
287
+ this.A = A | 0;
288
+ this.B = B | 0;
289
+ this.C = C | 0;
290
+ this.D = D | 0;
291
+ this.E = E | 0;
292
+ this.F = F | 0;
293
+ this.G = G | 0;
294
+ this.H = H | 0;
295
+ }
296
+ process(view, offset) {
297
+ for (let i = 0; i < 16; i++, offset += 4)
298
+ SHA256_W[i] = view.getUint32(offset, false);
299
+ for (let i = 16; i < 64; i++) {
300
+ const W15 = SHA256_W[i - 15];
301
+ const W2 = SHA256_W[i - 2];
302
+ const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
303
+ const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
304
+ SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
305
+ }
306
+ let { A, B, C, D, E, F, G, H } = this;
307
+ for (let i = 0; i < 64; i++) {
308
+ const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
309
+ const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
310
+ const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
311
+ const T2 = sigma0 + Maj(A, B, C) | 0;
312
+ H = G;
313
+ G = F;
314
+ F = E;
315
+ E = D + T1 | 0;
316
+ D = C;
317
+ C = B;
318
+ B = A;
319
+ A = T1 + T2 | 0;
320
+ }
321
+ A = A + this.A | 0;
322
+ B = B + this.B | 0;
323
+ C = C + this.C | 0;
324
+ D = D + this.D | 0;
325
+ E = E + this.E | 0;
326
+ F = F + this.F | 0;
327
+ G = G + this.G | 0;
328
+ H = H + this.H | 0;
329
+ this.set(A, B, C, D, E, F, G, H);
330
+ }
331
+ roundClean() {
332
+ clean(SHA256_W);
333
+ }
334
+ destroy() {
335
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
336
+ clean(this.buffer);
337
+ }
338
+ };
339
+ var sha256 = /* @__PURE__ */ createHasher(() => new SHA256());
340
+
341
+ // node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha256.js
342
+ var sha2562 = sha256;
343
+
344
+ // node_modules/.pnpm/@paybox+mcp-app@file+..+mcp-app_@modelcontextprotocol+sdk@1.29.0_zod@4.4.3__bn.js@5.2.3_ac1e09a20c76a1143611be5dd3d4f9db/node_modules/@paybox/mcp-app/src/signing/agent-code.ts
345
+ var ALPHABET = [
346
+ "\u{1F436}",
347
+ "\u{1F431}",
348
+ "\u{1F42D}",
349
+ "\u{1F430}",
350
+ "\u{1F98A}",
351
+ "\u{1F43B}",
352
+ "\u{1F43C}",
353
+ "\u{1F981}",
354
+ "\u{1F42E}",
355
+ "\u{1F437}",
356
+ "\u{1F438}",
357
+ "\u{1F435}",
358
+ "\u{1F414}",
359
+ "\u{1F427}",
360
+ "\u{1F426}",
361
+ "\u{1F424}",
362
+ "\u{1F986}",
363
+ "\u{1F985}",
364
+ "\u{1F989}",
365
+ "\u{1F987}",
366
+ "\u{1F417}",
367
+ "\u{1F434}",
368
+ "\u{1F984}",
369
+ "\u{1F41D}",
370
+ "\u{1F41B}",
371
+ "\u{1F98B}",
372
+ "\u{1F40C}",
373
+ "\u{1F41E}",
374
+ "\u{1F41C}",
375
+ "\u{1F422}",
376
+ "\u{1F40D}",
377
+ "\u{1F98E}",
378
+ "\u{1F419}",
379
+ "\u{1F990}",
380
+ "\u{1F980}",
381
+ "\u{1F421}",
382
+ "\u{1F420}",
383
+ "\u{1F42C}",
384
+ "\u{1F433}",
385
+ "\u{1F988}",
386
+ "\u{1F406}",
387
+ "\u{1F993}",
388
+ "\u{1F98D}",
389
+ "\u{1F418}",
390
+ "\u{1F98F}",
391
+ "\u{1F42A}",
392
+ "\u{1F992}",
393
+ "\u{1F411}",
394
+ "\u{1F98C}",
395
+ "\u{1F983}",
396
+ "\u{1F99A}",
397
+ "\u{1F335}",
398
+ "\u{1F384}",
399
+ "\u{1F333}",
400
+ "\u{1F334}",
401
+ "\u{1F331}",
402
+ "\u{1F340}",
403
+ "\u{1F38D}",
404
+ "\u{1F341}",
405
+ "\u{1F342}",
406
+ "\u{1F343}",
407
+ "\u{1F33B}",
408
+ "\u{1F339}",
409
+ "\u{1F337}",
410
+ "\u{1F338}",
411
+ "\u{1F33C}",
412
+ "\u{1F33E}",
413
+ "\u{1F490}",
414
+ "\u{1F344}",
415
+ "\u{1F330}",
416
+ "\u{1F30D}",
417
+ "\u{1F319}",
418
+ "\u2B50",
419
+ "\u{1F308}",
420
+ "\u{1F525}",
421
+ "\u{1F4A7}",
422
+ "\u{1F30A}",
423
+ "\u{1F32A}",
424
+ "\u{1F329}",
425
+ "\u{1F347}",
426
+ "\u{1F349}",
427
+ "\u{1F34A}",
428
+ "\u{1F34B}",
429
+ "\u{1F34C}",
430
+ "\u{1F34D}",
431
+ "\u{1F34E}",
432
+ "\u{1F350}",
433
+ "\u{1F351}",
434
+ "\u{1F352}",
435
+ "\u{1F353}",
436
+ "\u{1F95D}",
437
+ "\u{1F951}",
438
+ "\u{1F346}",
439
+ "\u{1F955}",
440
+ "\u{1F33D}",
441
+ "\u{1F966}",
442
+ "\u{1F952}",
443
+ "\u{1F95C}",
444
+ "\u{1F35E}",
445
+ "\u{1F950}",
446
+ "\u{1F9C0}",
447
+ "\u{1F373}",
448
+ "\u{1F95E}",
449
+ "\u{1F354}",
450
+ "\u{1F35F}",
451
+ "\u{1F355}",
452
+ "\u{1F32D}",
453
+ "\u{1F32E}",
454
+ "\u{1F32F}",
455
+ "\u{1F35C}",
456
+ "\u{1F360}",
457
+ "\u{1F364}",
458
+ "\u{1F365}",
459
+ "\u{1F366}",
460
+ "\u{1F368}",
461
+ "\u{1F369}",
462
+ "\u{1F36A}",
463
+ "\u{1F382}",
464
+ "\u{1F370}",
465
+ "\u{1F36B}",
466
+ "\u{1F36C}",
467
+ "\u{1F36D}",
468
+ "\u{1F36E}",
469
+ "\u{1F36F}",
470
+ "\u{1F37C}",
471
+ "\u{1F95B}",
472
+ "\u2615",
473
+ "\u{1F375}",
474
+ "\u{1F376}",
475
+ "\u{1F37E}",
476
+ "\u{1F377}",
477
+ "\u{1F378}",
478
+ "\u{1F379}",
479
+ "\u{1F37A}",
480
+ "\u{1F943}",
481
+ "\u26BD",
482
+ "\u{1F3C0}",
483
+ "\u{1F3C8}",
484
+ "\u26BE",
485
+ "\u{1F3BE}",
486
+ "\u{1F3B1}",
487
+ "\u{1F3D3}",
488
+ "\u{1F3F8}",
489
+ "\u{1F945}",
490
+ "\u{1F3D2}",
491
+ "\u{1F3F9}",
492
+ "\u{1F3A3}",
493
+ "\u{1F94A}",
494
+ "\u{1F3BF}",
495
+ "\u{1F6F7}",
496
+ "\u{1F3AF}",
497
+ "\u{1F3AE}",
498
+ "\u{1F3B2}",
499
+ "\u{1F3B8}",
500
+ "\u{1F3BA}",
501
+ "\u{1F941}",
502
+ "\u{1F3B9}",
503
+ "\u{1F3A4}",
504
+ "\u{1F3A7}",
505
+ "\u{1F4FB}",
506
+ "\u{1F3AC}",
507
+ "\u{1F3A8}",
508
+ "\u{1F3AA}",
509
+ "\u{1F680}",
510
+ "\u{1F6F8}",
511
+ "\u{1F681}",
512
+ "\u{1F682}",
513
+ "\u{1F684}",
514
+ "\u{1F68C}",
515
+ "\u{1F691}",
516
+ "\u{1F693}",
517
+ "\u{1F695}",
518
+ "\u{1F697}",
519
+ "\u{1F69A}",
520
+ "\u{1F69C}",
521
+ "\u{1F6B2}",
522
+ "\u26F5",
523
+ "\u{1F6F6}",
524
+ "\u{1F6A4}",
525
+ "\u{1F5FF}",
526
+ "\u{1F5FD}",
527
+ "\u{1F3A1}",
528
+ "\u{1F3A2}",
529
+ "\u{1F3A0}",
530
+ "\u26F2",
531
+ "\u{1F3F0}",
532
+ "\u{1F3DF}",
533
+ "\u{1F3AD}",
534
+ "\u{1F381}",
535
+ "\u{1F9ED}",
536
+ "\u231A",
537
+ "\u{1F4F1}",
538
+ "\u{1F4BB}",
539
+ "\u{1F4F7}",
540
+ "\u{1F4FA}",
541
+ "\u{1F4DE}",
542
+ "\u{1F4E0}",
543
+ "\u{1F50B}",
544
+ "\u{1F50C}",
545
+ "\u{1F4A1}",
546
+ "\u{1F526}",
547
+ "\u{1F56F}",
548
+ "\u{1F5D1}",
549
+ "\u{1F4B8}",
550
+ "\u{1F4B0}",
551
+ "\u{1F4B3}",
552
+ "\u{1F48E}",
553
+ "\u{1F527}",
554
+ "\u{1F528}",
555
+ "\u{1F529}",
556
+ "\u{1F52B}",
557
+ "\u{1F4A3}",
558
+ "\u{1F52A}",
559
+ "\u{1F52E}",
560
+ "\u{1F4FF}",
561
+ "\u{1F52C}",
562
+ "\u{1F4D4}",
563
+ "\u{1F4DA}",
564
+ "\u{1F31E}",
565
+ "\u26C4",
566
+ "\u2614",
567
+ "\u{1F30B}",
568
+ "\u{1F94C}",
569
+ "\u{1F3E0}",
570
+ "\u{1F3E5}",
571
+ "\u{1F3ED}",
572
+ "\u{1F511}",
573
+ "\u{1F512}",
574
+ "\u23F0",
575
+ "\u231B",
576
+ "\u{1F4C5}",
577
+ "\u{1F4CC}",
578
+ "\u{1F4CE}",
579
+ "\u{1F4CF}",
580
+ "\u{1F388}",
581
+ "\u{1F383}",
582
+ "\u{1F451}",
583
+ "\u{1F453}",
584
+ "\u{1F3A9}",
585
+ "\u{1F45F}",
586
+ "\u{1F462}",
587
+ "\u{1F45C}",
588
+ "\u{1F392}",
589
+ "\u{1F9F2}",
590
+ "\u{1F9EA}",
591
+ "\u{1F9EC}",
592
+ "\u{1F9F8}",
593
+ "\u{1F9E6}",
594
+ "\u{1F9E2}",
595
+ "\u{1F3C6}",
596
+ "\u{1F6F4}",
597
+ "\u{1FA90}",
598
+ "\u{1F3B3}",
599
+ "\u{1F6A6}",
600
+ "\u{1F9EF}",
601
+ "\u{1F9F9}"
602
+ ];
603
+ function toHex(bytes) {
604
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
605
+ }
606
+ var CODE_LENGTH = 8;
607
+ if (ALPHABET.length !== 256) {
608
+ throw new Error(`agent-code alphabet must be exactly 256 entries, got ${ALPHABET.length}`);
609
+ }
610
+ function sha2563(bytes) {
611
+ return sha2562(bytes);
612
+ }
613
+ function codeFromDigest(digest) {
614
+ const code = [];
615
+ for (let i = 0; i < CODE_LENGTH; i += 1) code.push(ALPHABET[digest[i]]);
616
+ return code;
617
+ }
618
+ async function deriveAgentCode(publicKey) {
619
+ if (publicKey.length !== 32) {
620
+ throw new Error(`public key must be 32 bytes, got ${publicKey.length}`);
621
+ }
622
+ return codeFromDigest(sha2563(publicKey));
623
+ }
624
+
625
+ // src/pairing.ts
626
+ var POLL_MS = 1500;
627
+ var TIMEOUT_MS = 10 * 60 * 1e3;
628
+ var MAX_BACKOFF_MS = 15e3;
629
+ var GIVE_UP_AFTER_FAILING_MS = 9e4;
630
+ async function json(url, init) {
631
+ const res = await fetch(url, init);
632
+ if (!res.ok) {
633
+ const body = await res.text().catch(() => "");
634
+ throw new Error(`${init.method ?? "GET"} ${new URL(url).pathname} failed (${res.status})${body ? `: ${body.slice(0, 200)}` : ""}`);
635
+ }
636
+ return res.json();
637
+ }
638
+ async function pairSigningKey(opts) {
639
+ const { pairing_token, client_id } = await json(`${opts.baseUrl}/api/agent-pairings/token`, {
640
+ method: "POST",
641
+ headers: { authorization: `Bearer ${opts.bearer}`, accept: "application/json" }
642
+ });
643
+ const seed = nacl.randomBytes(nacl.sign.seedLength);
644
+ const pair = nacl.sign.keyPair.fromSeed(seed);
645
+ const keypair = { apiPubHex: toHex(pair.publicKey), apiPrivHex: toHex(seed) };
646
+ const { pairing_id } = await json(`${opts.baseUrl}/iframe/pairing`, {
647
+ method: "POST",
648
+ headers: {
649
+ authorization: `Bearer ${pairing_token}`,
650
+ "content-type": "application/json",
651
+ accept: "application/json"
652
+ },
653
+ body: JSON.stringify({ api_pub_hex: keypair.apiPubHex })
654
+ });
655
+ const url = `${opts.appBase}/agent-key?client_id=${client_id}&pairing_id=${pairing_id}`;
656
+ opts.onCode(await deriveAgentCode(pair.publicKey), url);
657
+ const deadline = Date.now() + TIMEOUT_MS;
658
+ let failures = 0;
659
+ let failingSince = 0;
660
+ while (Date.now() < deadline) {
661
+ const backoff = failures ? Math.min(POLL_MS * 2 ** failures, MAX_BACKOFF_MS) : POLL_MS;
662
+ await new Promise((resolve) => setTimeout(resolve, backoff));
663
+ let status;
664
+ try {
665
+ status = (await json(`${opts.baseUrl}/iframe/pairing/${pairing_id}`, {
666
+ headers: { accept: "application/json" }
667
+ })).status;
668
+ failures = 0;
669
+ failingSince = 0;
670
+ } catch (err) {
671
+ failures += 1;
672
+ failingSince ||= Date.now();
673
+ if (Date.now() - failingSince >= GIVE_UP_AFTER_FAILING_MS) {
674
+ throw new Error(`lost contact with PayBox while waiting: ${err.message}`);
675
+ }
676
+ continue;
677
+ }
678
+ if (status === "completed") return encodeToken(keypair);
679
+ if (status === "cancelled") throw new Error("that request was declined in PayBox");
680
+ if (status === "expired") throw new Error("that request expired \u2014 run `paybox connect` again");
681
+ }
682
+ throw new Error("timed out waiting for you to pick the code in PayBox");
683
+ }
684
+
685
+ // src/cli.ts
21
686
  var DEFAULT_BASE_URL = "https://api.paybox.sh";
22
687
  var PKG = "@paybox-sh/sdk";
23
688
  var VERSION = createRequire(import.meta.url)("../package.json").version;
@@ -87,15 +752,6 @@ function isNewer(a, b) {
87
752
  }
88
753
  return false;
89
754
  }
90
- async function prompt(question) {
91
- if (!process.stdin.isTTY) return "";
92
- const rl = createInterface({ input: process.stdin, output: process.stderr });
93
- try {
94
- return (await rl.question(question)).trim();
95
- } finally {
96
- rl.close();
97
- }
98
- }
99
755
  async function run(fn) {
100
756
  try {
101
757
  await fn();
@@ -109,61 +765,62 @@ async function run(fn) {
109
765
  function warnIfUnsignable(c, status) {
110
766
  if (status === "pending_signature" && !c.canSign) {
111
767
  console.error(
112
- "awaiting signatures but no valid pbxk1. signing key is set \u2014 set PAYBOX_SIGNING_KEY and re-run `paybox login`, then poll `paybox request <id>`."
768
+ "awaiting signatures but this machine has no signing key \u2014 run `paybox connect`, then poll `paybox request <id>`."
113
769
  );
114
770
  }
115
771
  }
116
- program.command("login").description("Authenticate via OAuth (browser + passkey), or store a pbx_live_ key").option("--key <key>", "store a pbx_live_ personal API key instead of OAuth").option(
117
- "--signing-key <token>",
118
- "store a pbxk1. wallet signing key; prefer PAYBOX_SIGNING_KEY (an argument is visible in shell history)"
119
- ).option("--app-url <url>", "PayBox app origin for key provisioning (default: derived from --base-url)").option("--no-provision", "skip the wallet signing-key provisioning step").action(
772
+ function resolveBaseUrl() {
773
+ const cfg = loadConfig();
774
+ return (program.opts().baseUrl ?? process.env.PAYBOX_API_URL ?? cfg.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
775
+ }
776
+ program.command("login").description("Authenticate via OAuth (browser + passkey), or store a pbx_live_ key").option("--key <key>", "store a pbx_live_ personal API key instead of OAuth").action(
120
777
  (opts) => run(async () => {
121
778
  const cfg = loadConfig();
122
- const baseUrl = (program.opts().baseUrl ?? process.env.PAYBOX_API_URL ?? cfg.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
123
- cfg.baseUrl = baseUrl;
124
- if (opts.appUrl) cfg.appUrl = opts.appUrl;
125
- const keepExistingLogin = Boolean(opts.signingKey) && Boolean(cfg.apiKey ?? cfg.oauth);
779
+ cfg.baseUrl = resolveBaseUrl();
126
780
  if (opts.key) {
127
781
  cfg.apiKey = opts.key;
128
782
  delete cfg.oauth;
129
- } else if (!keepExistingLogin) {
130
- cfg.oauth = await loginDevice(baseUrl);
783
+ } else {
784
+ cfg.oauth = await loginDevice(cfg.baseUrl);
131
785
  delete cfg.apiKey;
132
786
  }
133
- if (opts.signingKey) cfg.signingKey = opts.signingKey;
787
+ delete cfg.signingKey;
134
788
  saveConfig(cfg);
135
789
  console.error(`Saved credentials to ${configFile()}`);
136
- if (!cfg.oauth || opts.signingKey || opts.provision === false) return;
137
- const cid = agentClientId(cfg.oauth.accessToken);
138
- const appBase = appBaseFrom(baseUrl, opts.appUrl ?? process.env.PAYBOX_APP_URL ?? cfg.appUrl);
139
- if (!cid || !appBase) {
140
- console.error(
141
- "To enable wallet sign/swap, provision a signing key, then set\n PAYBOX_SIGNING_KEY=<pbxk1...> and re-run `paybox login`" + (cid && !appBase ? " (or pass --app-url <paybox app origin>)" : "")
142
- );
143
- return;
790
+ if (!process.env.PAYBOX_SIGNING_KEY) {
791
+ console.error("Run `paybox connect` to connect a signing key; until then sign and swap stop at pending_signature.");
144
792
  }
145
- const url = `${appBase}/agent-key?client_id=${cid}`;
146
- console.error(
147
- `
148
- Next, provision a wallet signing key for this agent (needed for sign/swap):
149
- ${url}
150
- `
151
- );
152
- openBrowser(url);
153
- const key = process.stdin.isTTY ? await prompt("Paste the pbxk1. signing key when ready (or Enter to skip): ") : (process.env.PAYBOX_SIGNING_KEY ?? "").trim();
154
- if (key) {
155
- cfg.signingKey = key;
793
+ })
794
+ );
795
+ program.command("connect").description("Connect a wallet signing key to this machine by picking a code in PayBox").option("--app-url <url>", "PayBox app origin (default: derived from --base-url)").action(
796
+ (opts) => run(async () => {
797
+ const cfg = loadConfig();
798
+ const baseUrl = resolveBaseUrl();
799
+ const appBase = appBaseFrom(baseUrl, opts.appUrl ?? process.env.PAYBOX_APP_URL ?? cfg.appUrl);
800
+ if (!appBase) throw new Error("could not derive the PayBox app origin \u2014 pass --app-url");
801
+ if (opts.appUrl) cfg.appUrl = opts.appUrl;
802
+ if (!cfg.apiKey && cfg.oauth?.expiresAt && Date.now() > cfg.oauth.expiresAt - 3e4) {
803
+ cfg.oauth = await refreshTokens(baseUrl, cfg.oauth);
156
804
  saveConfig(cfg);
157
- console.error("Signing key saved \u2014 sign/swap enabled.");
158
- } else if (process.stdin.isTTY) {
159
- console.error(
160
- "Skipped \u2014 provision one later by setting PAYBOX_SIGNING_KEY and re-running `paybox login`."
161
- );
162
- } else {
163
- console.error(
164
- "No signing key configured, so sign and swap will stop at pending_signature.\nSet PAYBOX_SIGNING_KEY to the `pbxk1.` token and re-run `paybox login`."
165
- );
166
805
  }
806
+ const bearer = cfg.apiKey ?? cfg.oauth?.accessToken;
807
+ if (!bearer) throw new Error("not authenticated \u2014 run `paybox login` first");
808
+ cfg.signingKey = await pairSigningKey({
809
+ baseUrl,
810
+ appBase,
811
+ bearer,
812
+ onCode(code, url) {
813
+ console.error(`
814
+ ${code.join(" ")}
815
+ `);
816
+ console.error(`Open this on any device and pick that code to connect this machine:
817
+ ${url}
818
+ `);
819
+ openBrowser(url);
820
+ }
821
+ });
822
+ saveConfig(cfg);
823
+ console.error("Connected \u2014 sign and swap are enabled on this machine.");
167
824
  })
168
825
  );
169
826
  program.command("logout").description("Forget stored credentials").action(
@@ -276,9 +933,16 @@ program.command("use-service").description("Fetch a paid x402 resource and have
276
933
  emit(result);
277
934
  })
278
935
  );
279
- program.command("portfolio").description("List a wallet address's token balances across chains").requiredOption("--address <addr>").option("--networks <ids>", 'comma-separated network IDs, e.g. "1,8453"').action(
936
+ program.command("portfolio").description("List a wallet address's token balances across chains").requiredOption("--address <addr>").option("--networks <ids>", 'comma-separated network IDs, e.g. "1,8453"').option("--token <addr>", "mint, ERC-20, or native").option("--network-id <id>", "MoonX network id required with --token").action(
280
937
  (o) => run(
281
- async () => emit(await client().getPortfolio({ address: o.address, networkIds: o.networks }))
938
+ async () => emit(
939
+ await client().getPortfolio({
940
+ address: o.address,
941
+ networkIds: o.networks,
942
+ token: o.token,
943
+ networkId: o.networkId == null ? void 0 : Number(o.networkId)
944
+ })
945
+ )
282
946
  )
283
947
  );
284
948
  program.command("verify-solana-balance").description("Verify a Solana transaction's wallet/token effect and current balance").requiredOption("--address <addr>", "canonical Solana wallet address").requiredOption("--mint <addr>", "canonical SPL or Token-2022 mint").requiredOption("--transaction <signature>", "confirmed Solana transaction signature").action(
@@ -294,6 +958,16 @@ program.command("verify-solana-balance").description("Verify a Solana transactio
294
958
  );
295
959
  program.command("claim <request-id>").description("Claim the usable card credentials of an approved payment (one-time)").action((id) => run(async () => emit(await client().claimPaymentCredentials(requestId(id)))));
296
960
  program.command("account-change").description("Get a manage_url for the USER to update this client's access in the app").option("--note <text>", "why the change is needed (shown to the user)").action((o) => run(async () => emit(await client().requestAccountChange(o.note))));
961
+ program.command("deposit-link").description("Open Deposit URL for a granted wallet (charges nothing)").requiredOption("--credential <id>", "a granted wallet credential").option("--amount-usd <n>", "optional amount hint in USD").action(
962
+ (o) => run(
963
+ async () => emit(
964
+ await client().getDepositLink({
965
+ credentialId: credentialId(o.credential),
966
+ amountUsd: o.amountUsd === void 0 ? void 0 : Number(o.amountUsd)
967
+ })
968
+ )
969
+ )
970
+ );
297
971
  program.command("buy-link").description("Signed MoonPay checkout URL funding a granted wallet (charges nothing)").requiredOption("--credential <id>", "a granted wallet credential").option(
298
972
  "--destination <chain>",
299
973
  "exact network: eip155:8453 (default EVM), eip155:1, eip155:4663, or solana:mainnet"
@@ -421,4 +1095,9 @@ function rejectUnknownCommand(argv) {
421
1095
  }
422
1096
  rejectUnknownCommand(process.argv);
423
1097
  program.parseAsync(process.argv);
1098
+ /*! Bundled license information:
1099
+
1100
+ @noble/hashes/esm/utils.js:
1101
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
1102
+ */
424
1103
  //# sourceMappingURL=cli.js.map