@1sat/cli 0.0.111 → 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
@@ -3389,7 +3389,7 @@ function buildPriceUpdateTask(options) {
3389
3389
  lastRunMsecsSinceEpoch: 0,
3390
3390
  async asyncSetup() {},
3391
3391
  trigger(now) {
3392
- if (targets.length === 0)
3392
+ if (targets.length === 0 && !options.onQuote)
3393
3393
  return { run: false };
3394
3394
  if (now - this.lastRunMsecsSinceEpoch < intervalMs)
3395
3395
  return { run: false };
@@ -3402,6 +3402,13 @@ function buildPriceUpdateTask(options) {
3402
3402
  } catch (err) {
3403
3403
  return `rate fetch failed: ${err.message}`;
3404
3404
  }
3405
+ if (options.onQuote) {
3406
+ try {
3407
+ await options.onQuote(quote);
3408
+ } catch (err) {
3409
+ return `quote persist failed: ${err.message}`;
3410
+ }
3411
+ }
3405
3412
  const parts = [];
3406
3413
  for (const target of targets) {
3407
3414
  const currentSats = target.readCurrentSats();
@@ -3498,6 +3505,7 @@ import {
3498
3505
  } from "@1sat/wallet-node";
3499
3506
  import {
3500
3507
  KnexAccountStore,
3508
+ KnexHandleCertStore,
3501
3509
  KnexPendingStore,
3502
3510
  createHostServer,
3503
3511
  createWalletServer
@@ -3644,7 +3652,7 @@ async function runWithStorage(resolved, mode) {
3644
3652
  }
3645
3653
  });
3646
3654
  }
3647
- if (r?.enabled && targets.length > 0) {
3655
+ if (r?.enabled) {
3648
3656
  walletResult.monitor.addTask(buildPriceUpdateTask({
3649
3657
  monitor: walletResult.monitor,
3650
3658
  rateProvider: resolveRateProvider(r.provider ?? "whatsonchain", {
@@ -3655,9 +3663,13 @@ async function runWithStorage(resolved, mode) {
3655
3663
  maxMovePct: r.maxMovePct ?? 25,
3656
3664
  minSats: r.minSats ?? 1
3657
3665
  },
3658
- targets
3666
+ targets,
3667
+ onQuote: async (quote) => {
3668
+ setConfigPath("server.exchangeRate", quote);
3669
+ }
3659
3670
  }));
3660
- 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"}`);
3661
3673
  }
3662
3674
  }
3663
3675
  if (runMonitor) {
@@ -3710,6 +3722,8 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3710
3722
  await pendingStore.init();
3711
3723
  const accountStore = new KnexAccountStore(knex);
3712
3724
  await accountStore.init();
3725
+ const handleCertStore = new KnexHandleCertStore(knex);
3726
+ await handleCertStore.init();
3713
3727
  const handle = await createHostServer({
3714
3728
  wallet: walletResult.wallet,
3715
3729
  sessionStore,
@@ -3718,12 +3732,16 @@ async function startWalletServer(resolved, walletResult, accounts, mode) {
3718
3732
  listen: { port: resolved.port, host: resolved.host },
3719
3733
  accounts: accounts?.walletServerAccounts,
3720
3734
  accountStore,
3735
+ handleCertStore,
3736
+ getExchangeRate: () => loadConfig().server?.exchangeRate ?? null,
3721
3737
  paymail: {
3722
3738
  baseUrl: paymailCfg?.baseUrl ?? `http://${resolved.host}:${resolved.port}`,
3723
3739
  stackUrl: paymailCfg?.stackUrl ?? resolved.stackUrl,
3724
3740
  pendingStore,
3725
3741
  accountStore,
3742
+ certStore: handleCertStore,
3726
3743
  ...paymailCfg?.userDomain && { userDomain: paymailCfg.userDomain },
3744
+ ...paymailCfg?.verifySignature && { verifySignature: true },
3727
3745
  messageboxUrl: `http://127.0.0.1:${resolved.port}/messagebox`,
3728
3746
  hostPrivateKey: resolved.privateKey
3729
3747
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/cli",
3
- "version": "0.0.111",
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.208",
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()