@openreceive/http 0.4.12 → 0.4.13

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.
@@ -7,7 +7,7 @@ import {
7
7
  isServiceErrorShape,
8
8
  mapHostRouteError,
9
9
  startNotificationWorker
10
- } from "./chunk-PGZAFYN6.js";
10
+ } from "./chunk-YIN33FVH.js";
11
11
  export {
12
12
  HostError,
13
13
  HttpError,
@@ -1307,10 +1307,11 @@ function abortableDelay(milliseconds, signal) {
1307
1307
  }
1308
1308
 
1309
1309
  // src/reconcile-gate.ts
1310
- var OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS = 2;
1310
+ var OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS = 3;
1311
1311
  var OPENRECEIVE_RECONCILE_SCAN_TIMEOUT_MS = 9e3;
1312
+ var SCAN_BACKSTOP_GRACE_MS = 500;
1312
1313
  var OPENRECEIVE_RECONCILE_SCAN_MAX_PAGES = 50;
1313
- var EARLY_INVOICE_INTERVAL_SECONDS = 2;
1314
+ var EARLY_INVOICE_INTERVAL_SECONDS = 3;
1314
1315
  var MID_INVOICE_INTERVAL_SECONDS = 6;
1315
1316
  var LATE_INVOICE_INTERVAL_SECONDS = 12;
1316
1317
  var EARLY_INVOICE_WINDOW_SECONDS = 2 * 60;
@@ -1345,7 +1346,10 @@ async function maybeReconcilePayments(input) {
1345
1346
  try {
1346
1347
  const clock = input.clock ?? unixSeconds5;
1347
1348
  const now = clock();
1348
- const minInterval = Math.max(2, input.minIntervalSeconds ?? 2);
1349
+ const minInterval = Math.max(
1350
+ OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS,
1351
+ input.minIntervalSeconds ?? OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS
1352
+ );
1349
1353
  const timeout = Math.min(
1350
1354
  OPENRECEIVE_RECONCILE_SCAN_TIMEOUT_MS,
1351
1355
  input.scanTimeoutMs ?? OPENRECEIVE_RECONCILE_SCAN_TIMEOUT_MS
@@ -1370,20 +1374,19 @@ async function maybeReconcilePayments(input) {
1370
1374
  candidates = await input.host.payments.listReconcilableAttempts(null);
1371
1375
  const last = candidates.at(-1);
1372
1376
  scheduler.cursor = last === void 0 || candidates.length < OPENRECEIVE_RECONCILE_BATCH_SIZE ? null : { created_at: last.createdAt, payment_hash: last.paymentHash };
1373
- const fresh = candidates.filter((attempt) => !queued.has(attempt.paymentHash));
1374
- if (fresh.length > 0)
1375
- scheduler.windows.push(
1376
- createPaymentScanWindow(
1377
- fresh.map((attempt) => ({
1378
- payment_hash: attempt.paymentHash,
1379
- created_at: attempt.createdAt,
1380
- expires_at: attempt.expiresAt,
1381
- created_at_source: attempt.createdAtSource ?? "host"
1382
- })),
1383
- now,
1384
- input.overlapSeconds
1385
- )
1377
+ const fresh = candidates.filter((attempt) => !queued.has(attempt.paymentHash)).map((attempt) => ({
1378
+ payment_hash: attempt.paymentHash,
1379
+ created_at: attempt.createdAt,
1380
+ expires_at: attempt.expiresAt,
1381
+ created_at_source: attempt.createdAtSource ?? "host"
1382
+ }));
1383
+ for (const wallet of [true, false]) {
1384
+ const cohort = fresh.filter(
1385
+ (attempt) => attempt.created_at_source === "wallet" === wallet
1386
1386
  );
1387
+ if (cohort.length > 0 && scheduler.windows.length < 2)
1388
+ scheduler.windows.push(createPaymentScanWindow(cohort, now, input.overlapSeconds));
1389
+ }
1387
1390
  }
1388
1391
  const window = scheduler.windows.shift();
1389
1392
  if (window === void 0) {
@@ -1445,7 +1448,7 @@ async function maybeReconcilePayments(input) {
1445
1448
  }
1446
1449
  }
1447
1450
  }),
1448
- timeout,
1451
+ timeout + SCAN_BACKSTOP_GRACE_MS,
1449
1452
  controller
1450
1453
  );
1451
1454
  if (slice.outcome === "continued") {
package/dist/index.d.ts CHANGED
@@ -282,15 +282,16 @@ declare function startReconciler(input: {
282
282
 
283
283
  /**
284
284
  * Floor for the durable reconcile-gate interval: at most one real wallet scan
285
- * per two seconds across EVERY worker sharing the host database. This gate is
285
+ * per three seconds across EVERY worker sharing the host database. This gate is
286
286
  * the NWC rate limit for settlement scans — open tabs polling `payments/check`
287
287
  * (~3s) all share the one global pass instead of fanning out wallet walks.
288
288
  */
289
- declare const OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS: 2;
289
+ declare const OPENRECEIVE_MIN_RECONCILE_INTERVAL_SECONDS: 3;
290
290
  /**
291
291
  * Wall-clock bound on an awaited request-path pass: a slow wallet must not
292
- * hang user-facing requests. A timed-out pass counts as a failed scan; the
293
- * gate stays claimed so the next interval retries without a stampede.
292
+ * hang user-facing requests. A page still in flight at the deadline is cut;
293
+ * the pass keeps the progress of its completed pages, and the next interval
294
+ * resumes there.
294
295
  */
295
296
  declare const OPENRECEIVE_RECONCILE_SCAN_TIMEOUT_MS: 9000;
296
297
  /** Page cap per wallet-history walk on the awaited request path. */
@@ -304,7 +305,7 @@ type OpportunisticReconcileResult = {
304
305
  interface MaybeReconcilePaymentsOptions {
305
306
  readonly service: OpenReceive;
306
307
  readonly host: Host;
307
- /** Gate interval floor. Default (and minimum) 2 seconds. */
308
+ /** Gate interval floor. Default (and minimum) 3 seconds. */
308
309
  readonly minIntervalSeconds?: number;
309
310
  readonly overlapSeconds?: number;
310
311
  readonly scanTimeoutMs?: number;
@@ -315,7 +316,7 @@ interface MaybeReconcilePaymentsOptions {
315
316
  }
316
317
  /**
317
318
  * The gate interval for the current pending set: the configured floor,
318
- * stretched by invoice age (2s while any pending invoice is under 2 minutes
319
+ * stretched by invoice age (3s while any pending invoice is under 2 minutes
319
320
  * old, 6s under 5 minutes, else 12s).
320
321
  */
321
322
  declare function reconcileIntervalSeconds(attempts: readonly ReconcilableAttempt[], now: number, minIntervalSeconds?: number): number;
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  startReconciler,
35
35
  typeOrmDb,
36
36
  webRequest
37
- } from "./chunk-PGZAFYN6.js";
37
+ } from "./chunk-YIN33FVH.js";
38
38
  export {
39
39
  HostError,
40
40
  HttpError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openreceive/http",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "Node.js HTTP routes and payment storage for Bitcoin Lightning checkout, with optional USDT, USDC, SOL and ETH swaps.",
5
5
  "keywords": [
6
6
  "bitcoin",
@@ -17,8 +17,8 @@
17
17
  "main": "./dist/index.js",
18
18
  "types": "./dist/index.d.ts",
19
19
  "dependencies": {
20
- "@openreceive/core": "0.4.12",
21
- "@openreceive/node": "0.4.12"
20
+ "@openreceive/core": "0.4.13",
21
+ "@openreceive/node": "0.4.13"
22
22
  },
23
23
  "exports": {
24
24
  ".": {
@@ -49,7 +49,7 @@ same diagnostics redacted, always exit 0 — safe to share.
49
49
  ## 4. Paid but never settles
50
50
 
51
51
  - Settlement is opportunistic: any OpenReceive request runs one reconcile pass
52
- through a durable gate (min 2s between wallet scans, stretched by invoice
52
+ through a durable gate (min 3s between wallet scans, stretched by invoice
53
53
  age). A quiet server settles on the next request — or run the optional
54
54
  notification worker. No timer is missing; that is the design.
55
55
  - An unpaid attempt closes only after a successful wallet scan at/after expiry
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (BTCPay Server)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Connect a BTCPay Server store to a receive-only NWC wallet with the OpenReceive
6
6
  plugin, and optionally let payers pay BTCPay invoices with USDT, USDC, ETH or
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Django)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Django project — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the Python package is on PyPI
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (FastAPI)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a FastAPI application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the engine is on PyPI
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Fastify)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Fastify application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the packages are on npm, and
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Laravel)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Laravel application — the app you are already working in.
6
6
  You do not need a copy of the OpenReceive source: the package is on Packagist
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Next.js)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Next.js App Router application — the app you are already
6
6
  working in. You do not need a copy of the OpenReceive source: the packages are
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Node.js)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Node application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the packages are on npm, and the
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (PHP)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a PHP application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the engine is on Packagist
@@ -651,7 +651,7 @@ use registry `icon_path` / tutorial `path` keys as browser URLs.
651
651
 
652
652
  Settlement runs on the request path. Every payment route first runs one bounded
653
653
  reconcile pass through the durable `openreceive_meta` gate. The gate allows at
654
- most one real wallet scan every 2 seconds, shared by every PHP process. You do
654
+ most one real wallet scan every 3 seconds, shared by every PHP process. You do
655
655
  not need a cron job. Tune or disable it with `Engine`'s
656
656
  `opportunisticReconcile` (`false`, or `['min_interval_seconds' => …]`).
657
657
 
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (Rails)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Add OpenReceive to a Rails application — the app you are already working in. You
6
6
  do not need a copy of the OpenReceive source: the gem is on RubyGems, the
@@ -1,6 +1,6 @@
1
1
  # OpenReceive agent directions (WordPress + WooCommerce)
2
2
 
3
- These directions describe OpenReceive 0.4.12.
3
+ These directions describe OpenReceive 0.4.13.
4
4
 
5
5
  Install and configure the OpenReceive gateway in the existing WooCommerce
6
6
  store. Preserve its theme, checkout, customer accounts, order model and prices.