@thecryptodonkey/toll-booth 3.2.4 → 3.2.5
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/adapters/express.js +2 -1
- package/dist/adapters/web-standard.js +2 -1
- package/dist/booth.d.ts +1 -0
- package/dist/booth.js +10 -2
- package/package.json +1 -1
package/dist/adapters/express.js
CHANGED
|
@@ -136,7 +136,8 @@ export function createExpressMiddleware(engineOrConfig, upstreamArg) {
|
|
|
136
136
|
const tollCostHeader = upstream_res.headers.get('x-toll-cost');
|
|
137
137
|
if (tollCostHeader !== null && /^\d+$/.test(tollCostHeader)) {
|
|
138
138
|
const actualCost = parseInt(tollCostHeader, 10);
|
|
139
|
-
|
|
139
|
+
const maxAllowed = (result.estimatedCost ?? actualCost) * 10;
|
|
140
|
+
if (Number.isSafeInteger(actualCost) && actualCost >= 0 && actualCost <= maxAllowed) {
|
|
140
141
|
const reconciled = engine.reconcile(result.paymentHash, actualCost);
|
|
141
142
|
if (reconciled.adjusted) {
|
|
142
143
|
res.setHeader('X-Credit-Balance', String(reconciled.newBalance));
|
|
@@ -123,7 +123,8 @@ export function createWebStandardMiddleware(engineOrConfig, upstreamArg) {
|
|
|
123
123
|
const tollCostHeader = res.headers.get('x-toll-cost');
|
|
124
124
|
if (tollCostHeader !== null && /^\d+$/.test(tollCostHeader)) {
|
|
125
125
|
const actualCost = parseInt(tollCostHeader, 10);
|
|
126
|
-
|
|
126
|
+
const maxAllowed = (result.estimatedCost ?? actualCost) * 10;
|
|
127
|
+
if (Number.isSafeInteger(actualCost) && actualCost >= 0 && actualCost <= maxAllowed) {
|
|
127
128
|
const reconciled = engine.reconcile(result.paymentHash, actualCost);
|
|
128
129
|
if (reconciled.adjusted) {
|
|
129
130
|
responseHeaders.set('X-Credit-Balance', String(reconciled.newBalance));
|
package/dist/booth.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export declare class Booth {
|
|
|
34
34
|
private readonly rootKey;
|
|
35
35
|
private readonly redeemCashu?;
|
|
36
36
|
private readonly pruneTimer?;
|
|
37
|
+
private closed;
|
|
37
38
|
constructor(config: BoothOptions & EventHandler);
|
|
38
39
|
/** Reset free-tier counters for all IPs. */
|
|
39
40
|
resetFreeTier(): void;
|
package/dist/booth.js
CHANGED
|
@@ -54,6 +54,7 @@ export class Booth {
|
|
|
54
54
|
rootKey;
|
|
55
55
|
redeemCashu;
|
|
56
56
|
pruneTimer;
|
|
57
|
+
closed = false;
|
|
57
58
|
constructor(config) {
|
|
58
59
|
if (!config.backend && !config.redeemCashu && !config.x402) {
|
|
59
60
|
throw new Error('At least one payment method required: provide a Lightning backend, redeemCashu callback, or x402 config');
|
|
@@ -197,8 +198,8 @@ export class Booth {
|
|
|
197
198
|
// Auto-recover any pending Cashu claims from a previous crash
|
|
198
199
|
if (this.redeemCashu) {
|
|
199
200
|
const fn = this.redeemCashu;
|
|
200
|
-
this.recoverPendingClaims(fn).catch(() => {
|
|
201
|
-
|
|
201
|
+
this.recoverPendingClaims(fn).catch((err) => {
|
|
202
|
+
console.warn('[toll-booth] Cashu recovery failed:', err instanceof Error ? err.message : err);
|
|
202
203
|
});
|
|
203
204
|
}
|
|
204
205
|
}
|
|
@@ -222,12 +223,18 @@ export class Booth {
|
|
|
222
223
|
let recovered = 0;
|
|
223
224
|
const renewIntervalMs = Math.max(1_000, Math.floor(REDEEM_LEASE_MS / 2));
|
|
224
225
|
for (const claim of claims) {
|
|
226
|
+
if (this.closed)
|
|
227
|
+
break;
|
|
225
228
|
// Respect active leases so startup recovery does not race in-flight requests
|
|
226
229
|
// (or another process already handling this claim).
|
|
227
230
|
const leasedClaim = this.storage.tryAcquireRecoveryLease(claim.paymentHash, REDEEM_LEASE_MS);
|
|
228
231
|
if (!leasedClaim)
|
|
229
232
|
continue;
|
|
230
233
|
const timer = setInterval(() => {
|
|
234
|
+
if (this.closed) {
|
|
235
|
+
clearInterval(timer);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
231
238
|
this.storage.extendRecoveryLease(leasedClaim.paymentHash, REDEEM_LEASE_MS);
|
|
232
239
|
}, renewIntervalMs);
|
|
233
240
|
try {
|
|
@@ -254,6 +261,7 @@ export class Booth {
|
|
|
254
261
|
return recovered;
|
|
255
262
|
}
|
|
256
263
|
close() {
|
|
264
|
+
this.closed = true;
|
|
257
265
|
if (this.pruneTimer)
|
|
258
266
|
clearInterval(this.pruneTimer);
|
|
259
267
|
this.storage.close();
|
package/package.json
CHANGED