@1sat/cli 0.0.110 → 0.0.112

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,7 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
4
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
2
+ var __esm = (fn, res, err) => () => {
3
+ if (fn)
4
+ try {
5
+ res = fn(fn = 0);
6
+ } catch (e) {
7
+ err = [e];
8
+ }
9
+ if (err)
10
+ throw err[0];
11
+ return res;
12
+ };
5
13
 
6
14
  // src/args.ts
7
15
  function parseGlobalFlags(args) {
@@ -505,11 +513,11 @@ async function handleActionCommand(args, opts) {
505
513
  Registered actions:
506
514
  `);
507
515
  const grouped = new Map;
508
- for (const action2 of actions) {
509
- const cat = action2.meta.category;
516
+ for (const action of actions) {
517
+ const cat = action.meta.category;
510
518
  if (!grouped.has(cat))
511
519
  grouped.set(cat, []);
512
- grouped.get(cat).push(action2);
520
+ grouped.get(cat).push(action);
513
521
  }
514
522
  for (const [category, categoryActions] of grouped) {
515
523
  console.log(` ${category}:`);
@@ -1433,7 +1441,7 @@ function createApprovalAuth(wallet) {
1433
1441
  get(target, property) {
1434
1442
  if (property === "createAction")
1435
1443
  return async (...args) => {
1436
- const satoshis = args[0].outputs?.reduce((sum, output2) => sum + output2.satoshis, 0) ?? 0;
1444
+ const satoshis = args[0].outputs?.reduce((sum, output) => sum + output.satoshis, 0) ?? 0;
1437
1445
  if (!Number.isSafeInteger(satoshis) || satoshis <= 0)
1438
1446
  throw new Error("Invalid HTTP payment amount");
1439
1447
  if (approved === false)
@@ -1957,15 +1965,15 @@ async function handleInitCommand(_args, opts) {
1957
1965
  }
1958
1966
  let wif;
1959
1967
  if (keySource === "generate") {
1960
- const pk2 = PrivateKey2.fromRandom();
1961
- wif = pk2.toWif();
1962
- const address2 = pk2.toPublicKey().toAddress();
1968
+ const pk = PrivateKey2.fromRandom();
1969
+ wif = pk.toWif();
1970
+ const address = pk.toPublicKey().toAddress();
1963
1971
  console.log();
1964
1972
  console.log(formatWarning(" IMPORTANT: Back up your private key!"));
1965
1973
  console.log(formatWarning(" If you lose it, your funds are gone forever."));
1966
1974
  console.log();
1967
1975
  console.log(` ${formatValue("WIF:")} ${wif}`);
1968
- console.log(` ${formatValue("Address:")} ${address2}`);
1976
+ console.log(` ${formatValue("Address:")} ${address}`);
1969
1977
  console.log();
1970
1978
  const confirmed = await confirm2({
1971
1979
  message: "Have you saved your private key somewhere safe?"
@@ -3381,7 +3389,7 @@ function buildPriceUpdateTask(options) {
3381
3389
  lastRunMsecsSinceEpoch: 0,
3382
3390
  async asyncSetup() {},
3383
3391
  trigger(now) {
3384
- if (targets.length === 0)
3392
+ if (targets.length === 0 && !options.onQuote)
3385
3393
  return { run: false };
3386
3394
  if (now - this.lastRunMsecsSinceEpoch < intervalMs)
3387
3395
  return { run: false };
@@ -3394,6 +3402,13 @@ function buildPriceUpdateTask(options) {
3394
3402
  } catch (err) {
3395
3403
  return `rate fetch failed: ${err.message}`;
3396
3404
  }
3405
+ if (options.onQuote) {
3406
+ try {
3407
+ await options.onQuote(quote);
3408
+ } catch (err) {
3409
+ return `quote persist failed: ${err.message}`;
3410
+ }
3411
+ }
3397
3412
  const parts = [];
3398
3413
  for (const target of targets) {
3399
3414
  const currentSats = target.readCurrentSats();
@@ -3490,6 +3505,7 @@ import {
3490
3505
  } from "@1sat/wallet-node";
3491
3506
  import {
3492
3507
  KnexAccountStore,
3508
+ KnexHandleCertStore,
3493
3509
  KnexPendingStore,
3494
3510
  createHostServer,
3495
3511
  createWalletServer
@@ -3636,7 +3652,7 @@ async function runWithStorage(resolved, mode) {
3636
3652
  }
3637
3653
  });
3638
3654
  }
3639
- if (r?.enabled && targets.length > 0) {
3655
+ if (r?.enabled) {
3640
3656
  walletResult.monitor.addTask(buildPriceUpdateTask({
3641
3657
  monitor: walletResult.monitor,
3642
3658
  rateProvider: resolveRateProvider(r.provider ?? "whatsonchain", {
@@ -3647,9 +3663,13 @@ async function runWithStorage(resolved, mode) {
3647
3663
  maxMovePct: r.maxMovePct ?? 25,
3648
3664
  minSats: r.minSats ?? 1
3649
3665
  },
3650
- targets
3666
+ targets,
3667
+ onQuote: async (quote) => {
3668
+ setConfigPath("server.exchangeRate", quote);
3669
+ }
3651
3670
  }));
3652
- console.log(`[repricer] enabled — ${targets.map((t) => `${t.name} $${t.targetUsd}`).join(", ")} every ${Math.round((r.intervalMs ?? 900000) / 1000)}s via ${r.provider ?? "whatsonchain"}`);
3671
+ const targetNote = targets.map((t) => `${t.name} $${t.targetUsd}`).join(", ") || "quote only";
3672
+ console.log(`[repricer] enabled — ${targetNote} every ${Math.round((r.intervalMs ?? 900000) / 1000)}s via ${r.provider ?? "whatsonchain"}`);
3653
3673
  }
3654
3674
  }
3655
3675
  if (runMonitor) {
@@ -3679,7 +3699,7 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3679
3699
  ttlSeconds: sessionStoreCfg.ttlSeconds
3680
3700
  } : undefined;
3681
3701
  if (mode === "wallet") {
3682
- const handle2 = createWalletServer({
3702
+ const handle = createWalletServer({
3683
3703
  wallet: walletResult.wallet,
3684
3704
  storage: walletResult.getActiveStorage(),
3685
3705
  serverIdentityKey: walletResult.wallet.identityKey,
@@ -3689,10 +3709,10 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3689
3709
  accounts: accounts?.walletServerAccounts,
3690
3710
  sessionStore
3691
3711
  });
3692
- const port2 = await handle2.start();
3693
- const notes2 = [resolved.accounts.enabled ? "accounts: on" : ""].filter(Boolean).join(", ");
3694
- console.log(`[wallet] listening on ${resolved.host}:${port2}${notes2 ? ` (${notes2})` : ""}`);
3695
- return { stop: () => handle2.stop() };
3712
+ const port = await handle.start();
3713
+ const notes = [resolved.accounts.enabled ? "accounts: on" : ""].filter(Boolean).join(", ");
3714
+ console.log(`[wallet] listening on ${resolved.host}:${port}${notes ? ` (${notes})` : ""}`);
3715
+ return { stop: () => handle.stop() };
3696
3716
  }
3697
3717
  const serverCfg = config.server ?? {};
3698
3718
  const paymailCfg = serverCfg.paymail;
@@ -3702,6 +3722,8 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3702
3722
  await pendingStore.init();
3703
3723
  const accountStore = new KnexAccountStore(knex);
3704
3724
  await accountStore.init();
3725
+ const handleCertStore = new KnexHandleCertStore(knex);
3726
+ await handleCertStore.init();
3705
3727
  const handle = await createHostServer({
3706
3728
  wallet: walletResult.wallet,
3707
3729
  sessionStore,
@@ -3710,12 +3732,16 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3710
3732
  listen: { port: resolved.port, host: resolved.host },
3711
3733
  accounts: accounts?.walletServerAccounts,
3712
3734
  accountStore,
3735
+ handleCertStore,
3736
+ getExchangeRate: () => loadConfig().server?.exchangeRate ?? null,
3713
3737
  paymail: {
3714
3738
  baseUrl: paymailCfg?.baseUrl ?? `http://${resolved.host}:${resolved.port}`,
3715
3739
  stackUrl: paymailCfg?.stackUrl ?? resolved.stackUrl,
3716
3740
  pendingStore,
3717
3741
  accountStore,
3742
+ certStore: handleCertStore,
3718
3743
  ...paymailCfg?.userDomain && { userDomain: paymailCfg.userDomain },
3744
+ ...paymailCfg?.verifySignature && { verifySignature: true },
3719
3745
  messageboxUrl: `http://127.0.0.1:${resolved.port}/messagebox`,
3720
3746
  hostPrivateKey: resolved.privateKey
3721
3747
  },
@@ -4859,8 +4885,8 @@ async function walletListOutputs(args, opts) {
4859
4885
  ${result.totalOutputs} total outputs in basket '${basket}':
4860
4886
  `);
4861
4887
  for (const out of result.outputs) {
4862
- const tags2 = out.tags?.join(", ") || "none";
4863
- console.log(` ${out.outpoint} | ${out.satoshis} sats | tags: ${tags2}`);
4888
+ const tags = out.tags?.join(", ") || "none";
4889
+ console.log(` ${out.outpoint} | ${out.satoshis} sats | tags: ${tags}`);
4864
4890
  }
4865
4891
  console.log();
4866
4892
  }
@@ -5118,7 +5144,6 @@ var init_wallet = __esm(() => {
5118
5144
  });
5119
5145
 
5120
5146
  // src/main.ts
5121
- var exports_main = {};
5122
5147
  import { existsSync as existsSync4 } from "node:fs";
5123
5148
  import { resolve } from "node:path";
5124
5149
  import { config as loadEnv } from "dotenv";
@@ -5258,4 +5283,4 @@ var init_main = __esm(() => {
5258
5283
 
5259
5284
  // src/cli.ts
5260
5285
  process.env.DOTENV_CONFIG_QUIET = "true";
5261
- await Promise.resolve().then(() => (init_main(), exports_main));
5286
+ await Promise.resolve().then(() => (init_main(), {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/cli",
3
- "version": "0.0.110",
3
+ "version": "0.0.112",
4
4
  "description": "CLI for 1Sat Ordinals SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -27,11 +27,11 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "dependencies": {
30
- "@1sat/actions": "0.0.207",
30
+ "@1sat/actions": "0.0.211",
31
31
  "@1sat/client": "0.0.51",
32
- "@1sat/types": "0.0.41",
32
+ "@1sat/types": "0.0.43",
33
33
  "@1sat/wallet-node": "0.0.73",
34
- "@1sat/wallet-server": "0.0.48",
34
+ "@1sat/wallet-server": "0.0.49",
35
35
  "@bsv/sdk": "^2.1.9",
36
36
  "@bsv/wallet-toolbox": "npm:@bopen-io/wallet-toolbox@2.6.2-brc153.5",
37
37
  "chalk": "^5.0.0",
@@ -26,6 +26,7 @@ import {
26
26
  } from '@1sat/wallet-node'
27
27
  import {
28
28
  KnexAccountStore,
29
+ KnexHandleCertStore,
29
30
  KnexPendingStore,
30
31
  createHostServer,
31
32
  createWalletServer,
@@ -298,7 +299,7 @@ async function runWithStorage(
298
299
  },
299
300
  })
300
301
  }
301
- if (r?.enabled && targets.length > 0) {
302
+ if (r?.enabled) {
302
303
  walletResult.monitor.addTask(
303
304
  buildPriceUpdateTask({
304
305
  monitor: walletResult.monitor,
@@ -311,12 +312,16 @@ async function runWithStorage(
311
312
  minSats: r.minSats ?? 1,
312
313
  },
313
314
  targets,
315
+ onQuote: async (quote) => {
316
+ setConfigPath('server.exchangeRate', quote)
317
+ },
314
318
  }),
315
319
  )
320
+ const targetNote =
321
+ targets.map((t) => `${t.name} $${t.targetUsd}`).join(', ') ||
322
+ 'quote only'
316
323
  console.log(
317
- `[repricer] enabled — ${targets
318
- .map((t) => `${t.name} $${t.targetUsd}`)
319
- .join(', ')} every ${Math.round(
324
+ `[repricer] enabled — ${targetNote} every ${Math.round(
320
325
  (r.intervalMs ?? 900_000) / 1000,
321
326
  )}s via ${r.provider ?? 'whatsonchain'}`,
322
327
  )
@@ -401,6 +406,8 @@ async function startWalletServer(
401
406
  await pendingStore.init()
402
407
  const accountStore = new KnexAccountStore(knex)
403
408
  await accountStore.init()
409
+ const handleCertStore = new KnexHandleCertStore(knex)
410
+ await handleCertStore.init()
404
411
 
405
412
  const handle = await createHostServer({
406
413
  wallet: walletResult.wallet,
@@ -410,13 +417,17 @@ async function startWalletServer(
410
417
  listen: { port: resolved.port, host: resolved.host },
411
418
  accounts: accounts?.walletServerAccounts,
412
419
  accountStore,
420
+ handleCertStore,
421
+ getExchangeRate: () => loadConfig().server?.exchangeRate ?? null,
413
422
  paymail: {
414
423
  baseUrl:
415
424
  paymailCfg?.baseUrl ?? `http://${resolved.host}:${resolved.port}`,
416
425
  stackUrl: paymailCfg?.stackUrl ?? resolved.stackUrl,
417
426
  pendingStore,
418
427
  accountStore,
428
+ certStore: handleCertStore,
419
429
  ...(paymailCfg?.userDomain && { userDomain: paymailCfg.userDomain }),
430
+ ...(paymailCfg?.verifySignature && { verifySignature: true }),
420
431
  messageboxUrl: `http://127.0.0.1:${resolved.port}/messagebox`,
421
432
  hostPrivateKey: resolved.privateKey,
422
433
  },
package/src/config.ts CHANGED
@@ -118,6 +118,11 @@ export interface ServerPaymailConfig {
118
118
  * only resolves when its identity holds an account on this host.
119
119
  */
120
120
  userDomain?: string
121
+ /**
122
+ * Require signed P2P metadata on receive-beef / receive-transaction.
123
+ * Advertised as Request Sender Validation on well-known. Default false.
124
+ */
125
+ verifySignature?: boolean
121
126
  }
122
127
 
123
128
  export interface ServerSessionStoreConfig {
@@ -153,6 +158,12 @@ export interface ServerConfig {
153
158
  paymail?: ServerPaymailConfig
154
159
  /** Shared BSV/USD repricer engine for the accounts storage price. */
155
160
  repricer?: RepricerConfig
161
+ /** Last successful BSV/USD quote from the repricer. Served at GET /exchange-rate. */
162
+ exchangeRate?: {
163
+ bsvUsd: number
164
+ timestamp: number
165
+ source: string
166
+ }
156
167
  /**
157
168
  * Redis-shared BRC-104 sessions. Required when multiple serve instances
158
169
  * run behind one load balancer; unset keeps sessions in-memory.
@@ -1,5 +1,5 @@
1
1
  import { computeReprice } from './computeReprice.js'
2
- import type { RateProvider, RepricerBounds } from './types.js'
2
+ import type { BsvUsdQuote, RateProvider, RepricerBounds } from './types.js'
3
3
 
4
4
  /** One price the repricer maintains from the shared BSV/USD quote. */
5
5
  export interface RepriceTarget {
@@ -20,6 +20,8 @@ export interface PriceUpdateTaskOptions {
20
20
  intervalMs: number
21
21
  bounds: RepricerBounds
22
22
  targets: RepriceTarget[]
23
+ /** Called after a successful rate fetch, even when every target is skipped. */
24
+ onQuote?: (quote: BsvUsdQuote) => Promise<void>
23
25
  }
24
26
 
25
27
  export interface PriceUpdateTask {
@@ -47,7 +49,7 @@ export function buildPriceUpdateTask(
47
49
  lastRunMsecsSinceEpoch: 0,
48
50
  async asyncSetup() {},
49
51
  trigger(now: number): { run: boolean } {
50
- if (targets.length === 0) return { run: false }
52
+ if (targets.length === 0 && !options.onQuote) return { run: false }
51
53
  if (now - this.lastRunMsecsSinceEpoch < intervalMs) return { run: false }
52
54
  return { run: true }
53
55
  },
@@ -59,6 +61,14 @@ export function buildPriceUpdateTask(
59
61
  return `rate fetch failed: ${(err as Error).message}`
60
62
  }
61
63
 
64
+ if (options.onQuote) {
65
+ try {
66
+ await options.onQuote(quote)
67
+ } catch (err) {
68
+ return `quote persist failed: ${(err as Error).message}`
69
+ }
70
+ }
71
+
62
72
  const parts: string[] = []
63
73
  for (const target of targets) {
64
74
  const currentSats = target.readCurrentSats()