@contextvm/sdk 0.4.4 → 0.4.6
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/esm/core/interfaces.d.ts.map +1 -1
- package/dist/esm/core/utils/utils.d.ts +9 -0
- package/dist/esm/core/utils/utils.d.ts.map +1 -1
- package/dist/esm/core/utils/utils.js +39 -0
- package/dist/esm/core/utils/utils.js.map +1 -1
- package/dist/esm/payments/index.d.ts +3 -0
- package/dist/esm/payments/index.d.ts.map +1 -1
- package/dist/esm/payments/index.js +3 -0
- package/dist/esm/payments/index.js.map +1 -1
- package/dist/esm/payments/nip47/nwc-client.d.ts +7 -4
- package/dist/esm/payments/nip47/nwc-client.d.ts.map +1 -1
- package/dist/esm/payments/nip47/nwc-client.js +83 -13
- package/dist/esm/payments/nip47/nwc-client.js.map +1 -1
- package/dist/esm/payments/nip47/types.d.ts +5 -0
- package/dist/esm/payments/nip47/types.d.ts.map +1 -1
- package/dist/esm/payments/nip57/lnurl.d.ts +22 -0
- package/dist/esm/payments/nip57/lnurl.d.ts.map +1 -0
- package/dist/esm/payments/nip57/lnurl.js +41 -0
- package/dist/esm/payments/nip57/lnurl.js.map +1 -0
- package/dist/esm/payments/nip57/zap-events.d.ts +9 -0
- package/dist/esm/payments/nip57/zap-events.d.ts.map +1 -0
- package/dist/esm/payments/nip57/zap-events.js +18 -0
- package/dist/esm/payments/nip57/zap-events.js.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.d.ts +34 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.d.ts.map +1 -1
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.js +127 -5
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.js.map +1 -1
- package/dist/esm/payments/processors/ln-bolt11-zap-payment-processor.d.ts +48 -0
- package/dist/esm/payments/processors/ln-bolt11-zap-payment-processor.d.ts.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-zap-payment-processor.js +187 -0
- package/dist/esm/payments/processors/ln-bolt11-zap-payment-processor.js.map +1 -0
- package/dist/esm/relay/applesauce-relay-pool.d.ts +1 -2
- package/dist/esm/relay/applesauce-relay-pool.d.ts.map +1 -1
- package/dist/esm/relay/applesauce-relay-pool.js +23 -22
- package/dist/esm/relay/applesauce-relay-pool.js.map +1 -1
- package/dist/esm/transport/base-nostr-transport.d.ts +9 -0
- package/dist/esm/transport/base-nostr-transport.d.ts.map +1 -1
- package/dist/esm/transport/base-nostr-transport.js +27 -2
- package/dist/esm/transport/base-nostr-transport.js.map +1 -1
- package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client-transport.js +1 -0
- package/dist/esm/transport/nostr-client-transport.js.map +1 -1
- package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server-transport.js +1 -0
- package/dist/esm/transport/nostr-server-transport.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,15 +3,17 @@ import { parseNwcConnectionString } from '../nip47/connection.js';
|
|
|
3
3
|
import { NwcClient } from '../nip47/nwc-client.js';
|
|
4
4
|
import { ApplesauceRelayPool } from '../../relay/applesauce-relay-pool.js';
|
|
5
5
|
import { createLogger } from '../../core/utils/logger.js';
|
|
6
|
-
import { sleep } from '../../core/utils/utils.js';
|
|
7
6
|
import { satsToMsats } from '../nip47/utils.js';
|
|
7
|
+
import { LruCache } from '../../core/utils/lru-cache.js';
|
|
8
|
+
import { sleepWithAbort } from '../../core/utils/utils.js';
|
|
8
9
|
/**
|
|
9
10
|
* CEP-8 server payment processor for PMI `bitcoin-lightning-bolt11` backed by NIP-47 (NWC).
|
|
10
11
|
*/
|
|
11
12
|
export class LnBolt11NwcPaymentProcessor {
|
|
12
13
|
constructor(options) {
|
|
13
|
-
var _a, _b, _c, _d;
|
|
14
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
14
15
|
this.pmi = PMI_BITCOIN_LIGHTNING_BOLT11;
|
|
16
|
+
this.notificationWaiters = new Map();
|
|
15
17
|
const connection = parseNwcConnectionString(options.nwcConnectionString);
|
|
16
18
|
const relayHandler = (_a = options.relayHandler) !== null && _a !== void 0 ? _a : new ApplesauceRelayPool([...connection.relays]);
|
|
17
19
|
this.nwc = new NwcClient({
|
|
@@ -23,6 +25,61 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
23
25
|
this.invoiceExpirySeconds = (_c = options.invoiceExpirySeconds) !== null && _c !== void 0 ? _c : this.ttlSeconds;
|
|
24
26
|
this.pollIntervalMs = (_d = options.pollIntervalMs) !== null && _d !== void 0 ? _d : 1500;
|
|
25
27
|
this.logger = createLogger('payments/nwc-processor');
|
|
28
|
+
this.notificationVerificationEnabled =
|
|
29
|
+
(_e = options.enableNotificationVerification) !== null && _e !== void 0 ? _e : false;
|
|
30
|
+
if (options.enableNotificationVerification === undefined) {
|
|
31
|
+
this.notificationVerificationEnabled = false;
|
|
32
|
+
this.initNotificationsPromise = this.initNotificationsBestEffort();
|
|
33
|
+
}
|
|
34
|
+
this.inFlightVerifications = new LruCache((_f = options.maxInFlightVerifications) !== null && _f !== void 0 ? _f : 5000);
|
|
35
|
+
this.invoiceHashCache = new LruCache((_g = options.invoiceHashCacheSize) !== null && _g !== void 0 ? _g : 10000);
|
|
36
|
+
}
|
|
37
|
+
async initNotificationsBestEffort() {
|
|
38
|
+
try {
|
|
39
|
+
const types = await this.nwc.fetchInfoNotificationTypes();
|
|
40
|
+
this.notificationVerificationEnabled = types.has('payment_received');
|
|
41
|
+
}
|
|
42
|
+
catch (_a) {
|
|
43
|
+
this.notificationVerificationEnabled = false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async ensureInitResolved() {
|
|
47
|
+
if (!this.initNotificationsPromise)
|
|
48
|
+
return;
|
|
49
|
+
await this.initNotificationsPromise;
|
|
50
|
+
this.initNotificationsPromise = undefined;
|
|
51
|
+
}
|
|
52
|
+
async ensureNotificationsSubscribed() {
|
|
53
|
+
if (!this.notificationVerificationEnabled)
|
|
54
|
+
return;
|
|
55
|
+
if (this.notificationsUnsubscribe)
|
|
56
|
+
return;
|
|
57
|
+
this.notificationsUnsubscribe = await this.nwc.subscribeNotifications({
|
|
58
|
+
onNotification: (payload) => {
|
|
59
|
+
var _a;
|
|
60
|
+
if (payload.notification_type !== 'payment_received')
|
|
61
|
+
return;
|
|
62
|
+
const paymentHash = (_a = payload.notification) === null || _a === void 0 ? void 0 : _a.payment_hash;
|
|
63
|
+
if (typeof paymentHash !== 'string' || paymentHash.length === 0)
|
|
64
|
+
return;
|
|
65
|
+
const waiters = this.notificationWaiters.get(paymentHash);
|
|
66
|
+
if (!waiters || waiters.length === 0)
|
|
67
|
+
return;
|
|
68
|
+
this.notificationWaiters.delete(paymentHash);
|
|
69
|
+
for (const w of waiters)
|
|
70
|
+
w(paymentHash);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
computeNextDelayMs(params) {
|
|
75
|
+
// Prefer fast early checks (most invoices settle quickly), then back off.
|
|
76
|
+
// Keep a floor for legacy configs that rely on a predictable pollIntervalMs.
|
|
77
|
+
const scheduleMs = [500, 750, 1000, 1500, 2500, 4000, 6500, 10000, 15000];
|
|
78
|
+
const base = scheduleMs[Math.min(params.attempt, scheduleMs.length - 1)];
|
|
79
|
+
const flooredBase = Math.max(this.pollIntervalMs, base);
|
|
80
|
+
// Add small jitter to avoid stampeding on shared relay/wallet infra.
|
|
81
|
+
const jitter = Math.floor(Math.random() * 250);
|
|
82
|
+
return flooredBase + jitter;
|
|
26
83
|
}
|
|
27
84
|
isSettledInvoice(result) {
|
|
28
85
|
// Wallets vary: some set `state`, some only set `settled_at`, some include `preimage`.
|
|
@@ -50,7 +107,7 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
50
107
|
return `settled:${requestEventId}${settledAt ? `:${settledAt}` : ''}`;
|
|
51
108
|
}
|
|
52
109
|
async createPaymentRequired(params) {
|
|
53
|
-
var _a;
|
|
110
|
+
var _a, _b;
|
|
54
111
|
const request = {
|
|
55
112
|
amount: satsToMsats(params.amount),
|
|
56
113
|
description: params.description,
|
|
@@ -68,6 +125,10 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
68
125
|
if (!invoice) {
|
|
69
126
|
throw new Error('NWC make_invoice returned no invoice');
|
|
70
127
|
}
|
|
128
|
+
const paymentHash = (_b = response.result) === null || _b === void 0 ? void 0 : _b.payment_hash;
|
|
129
|
+
if (typeof paymentHash === 'string' && paymentHash.length > 0) {
|
|
130
|
+
this.invoiceHashCache.set(invoice, paymentHash);
|
|
131
|
+
}
|
|
71
132
|
// Keep TTL simple and predictable. Some providers return non-standard `expires_at`.
|
|
72
133
|
const ttl = this.ttlSeconds;
|
|
73
134
|
return {
|
|
@@ -79,19 +140,38 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
79
140
|
};
|
|
80
141
|
}
|
|
81
142
|
async verifyPayment(params) {
|
|
143
|
+
await this.ensureInitResolved();
|
|
144
|
+
const existing = this.inFlightVerifications.get(params.pay_req);
|
|
145
|
+
if (existing) {
|
|
146
|
+
return await existing;
|
|
147
|
+
}
|
|
148
|
+
const run = this.verifyPaymentInternal(params).finally(() => {
|
|
149
|
+
this.inFlightVerifications.delete(params.pay_req);
|
|
150
|
+
});
|
|
151
|
+
this.inFlightVerifications.set(params.pay_req, run);
|
|
152
|
+
return await run;
|
|
153
|
+
}
|
|
154
|
+
async verifyPaymentInternal(params) {
|
|
82
155
|
var _a;
|
|
156
|
+
if (this.notificationVerificationEnabled) {
|
|
157
|
+
return await this.verifyPaymentWithNotifications(params);
|
|
158
|
+
}
|
|
83
159
|
// Note: server-payments middleware already bounds overall time by the `ttl` it emitted.
|
|
84
160
|
// We still keep this loop tight and predictable.
|
|
161
|
+
let attempt = 0;
|
|
85
162
|
while (true) {
|
|
86
163
|
if ((_a = params.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
87
164
|
throw new Error('verifyPayment aborted');
|
|
88
165
|
}
|
|
166
|
+
const cachedPaymentHash = this.invoiceHashCache.get(params.pay_req);
|
|
89
167
|
const response = await this.nwc.request({
|
|
90
168
|
method: 'lookup_invoice',
|
|
91
169
|
resultType: 'lookup_invoice',
|
|
92
170
|
request: {
|
|
93
171
|
method: 'lookup_invoice',
|
|
94
|
-
params:
|
|
172
|
+
params: cachedPaymentHash
|
|
173
|
+
? { payment_hash: cachedPaymentHash }
|
|
174
|
+
: { invoice: params.pay_req },
|
|
95
175
|
},
|
|
96
176
|
});
|
|
97
177
|
if (response.error) {
|
|
@@ -109,6 +189,11 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
109
189
|
hasSettledAt: typeof (result === null || result === void 0 ? void 0 : result.settled_at) === 'number',
|
|
110
190
|
hasPaymentHash: Boolean(result === null || result === void 0 ? void 0 : result.payment_hash),
|
|
111
191
|
});
|
|
192
|
+
if (!cachedPaymentHash &&
|
|
193
|
+
typeof (result === null || result === void 0 ? void 0 : result.payment_hash) === 'string' &&
|
|
194
|
+
result.payment_hash.length > 0) {
|
|
195
|
+
this.invoiceHashCache.set(params.pay_req, result.payment_hash);
|
|
196
|
+
}
|
|
112
197
|
if (this.isSettledInvoice(result)) {
|
|
113
198
|
// Prefer payment_hash as a stable identifier (avoid exposing preimages).
|
|
114
199
|
const paymentHash = this.getReceiptFromInvoiceResult({
|
|
@@ -122,8 +207,45 @@ export class LnBolt11NwcPaymentProcessor {
|
|
|
122
207
|
throw new Error(`Invoice ${state}`);
|
|
123
208
|
}
|
|
124
209
|
}
|
|
125
|
-
|
|
210
|
+
const delayMs = this.computeNextDelayMs({ attempt });
|
|
211
|
+
attempt += 1;
|
|
212
|
+
await sleepWithAbort({ ms: delayMs, abortSignal: params.abortSignal });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async verifyPaymentWithNotifications(params) {
|
|
216
|
+
var _a;
|
|
217
|
+
await this.ensureNotificationsSubscribed();
|
|
218
|
+
if ((_a = params.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
219
|
+
throw new Error('verifyPayment aborted');
|
|
220
|
+
}
|
|
221
|
+
const paymentHash = this.invoiceHashCache.get(params.pay_req);
|
|
222
|
+
if (!paymentHash) {
|
|
223
|
+
throw new Error('NWC notification verification requires payment_hash');
|
|
126
224
|
}
|
|
225
|
+
const got = await new Promise((resolve, reject) => {
|
|
226
|
+
const existing = this.notificationWaiters.get(paymentHash);
|
|
227
|
+
const waiters = existing !== null && existing !== void 0 ? existing : [];
|
|
228
|
+
waiters.push(resolve);
|
|
229
|
+
this.notificationWaiters.set(paymentHash, waiters);
|
|
230
|
+
if (!params.abortSignal)
|
|
231
|
+
return;
|
|
232
|
+
const abortSignal = params.abortSignal;
|
|
233
|
+
const onAbort = () => {
|
|
234
|
+
abortSignal.removeEventListener('abort', onAbort);
|
|
235
|
+
// Remove this waiter so future notifications don't leak memory.
|
|
236
|
+
const current = this.notificationWaiters.get(paymentHash);
|
|
237
|
+
if (current) {
|
|
238
|
+
const next = current.filter((w) => w !== resolve);
|
|
239
|
+
if (next.length === 0)
|
|
240
|
+
this.notificationWaiters.delete(paymentHash);
|
|
241
|
+
else
|
|
242
|
+
this.notificationWaiters.set(paymentHash, next);
|
|
243
|
+
}
|
|
244
|
+
reject(new Error('verifyPayment aborted'));
|
|
245
|
+
};
|
|
246
|
+
abortSignal.addEventListener('abort', onAbort, { once: true });
|
|
247
|
+
});
|
|
248
|
+
return { _meta: { payment_hash: got } };
|
|
127
249
|
}
|
|
128
250
|
}
|
|
129
251
|
//# sourceMappingURL=ln-bolt11-nwc-payment-processor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ln-bolt11-nwc-payment-processor.js","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-nwc-payment-processor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAe,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ln-bolt11-nwc-payment-processor.js","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-nwc-payment-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { RelayHandler } from '../../core/interfaces.js';
|
|
2
|
+
import type { PaymentProcessor, PaymentProcessorCreateParams, PaymentProcessorVerifyParams } from '../types.js';
|
|
3
|
+
export interface LnBolt11ZapPaymentProcessorOptions {
|
|
4
|
+
/** Lightning address (LUD-16), e.g. `alice@example.com`. */
|
|
5
|
+
lnAddress: string;
|
|
6
|
+
/** Optional relay handler to reuse; otherwise a new ApplesauceRelayPool is created. */
|
|
7
|
+
relayHandler?: RelayHandler;
|
|
8
|
+
/** Relay URLs used both in zap request `relays` tag and to subscribe for zap receipts. */
|
|
9
|
+
relayUrls?: string[];
|
|
10
|
+
/** Time-to-live in seconds returned in `payment_required`. @default 300 */
|
|
11
|
+
ttlSeconds?: number;
|
|
12
|
+
/** Maximum number of in-flight invoice verifications to dedupe. @default 5000 */
|
|
13
|
+
maxInFlightVerifications?: number;
|
|
14
|
+
/** Maximum number of pending invoice issuances to remember. @default 10000 */
|
|
15
|
+
maxPendingInvoices?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* CEP-8 server payment processor for PMI `bitcoin-lightning-bolt11` backed by NIP-57 zap receipts.
|
|
19
|
+
*
|
|
20
|
+
* This issues a BOLT11 invoice via LNURL-pay zap request (kind 9734) and verifies settlement by
|
|
21
|
+
* subscribing for zap receipts (kind 9735).
|
|
22
|
+
*/
|
|
23
|
+
export declare class LnBolt11ZapPaymentProcessor implements PaymentProcessor {
|
|
24
|
+
readonly pmi: "bitcoin-lightning-bolt11";
|
|
25
|
+
private static readonly DEFAULT_RELAY_URLS;
|
|
26
|
+
private readonly lnAddress;
|
|
27
|
+
private readonly relayHandler;
|
|
28
|
+
private readonly relayUrls;
|
|
29
|
+
private readonly ttlSeconds;
|
|
30
|
+
private readonly logger;
|
|
31
|
+
private readonly signerSecretKey;
|
|
32
|
+
private readonly inFlightVerifications;
|
|
33
|
+
private readonly pendingInvoices;
|
|
34
|
+
constructor(options: LnBolt11ZapPaymentProcessorOptions);
|
|
35
|
+
createPaymentRequired(params: PaymentProcessorCreateParams): Promise<{
|
|
36
|
+
amount: number;
|
|
37
|
+
pay_req: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
pmi: string;
|
|
40
|
+
ttl?: number;
|
|
41
|
+
_meta?: Record<string, unknown>;
|
|
42
|
+
}>;
|
|
43
|
+
verifyPayment(params: PaymentProcessorVerifyParams): Promise<{
|
|
44
|
+
_meta?: Record<string, unknown>;
|
|
45
|
+
}>;
|
|
46
|
+
private verifyPaymentInternal;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=ln-bolt11-zap-payment-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln-bolt11-zap-payment-processor.d.ts","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-zap-payment-processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAU7D,OAAO,KAAK,EACV,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,EAC7B,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,kCAAkC;IACjD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAElB,uFAAuF;IACvF,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,iFAAiF;IACjF,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAQD;;;;;GAKG;AACH,qBAAa,2BAA4B,YAAW,gBAAgB;IAClE,SAAgB,GAAG,6BAAgC;IAInD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAIxC;IAEF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAa;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAEpC;IACF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;gBAE5C,OAAO,EAAE,kCAAkC;IAoBjD,qBAAqB,CAChC,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;IAqEW,aAAa,CACxB,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;YAWjC,qBAAqB;CAwGpC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { kinds } from 'nostr-tools';
|
|
2
|
+
import { finalizeEvent, generateSecretKey } from 'nostr-tools/pure';
|
|
3
|
+
import { ApplesauceRelayPool } from '../../relay/applesauce-relay-pool.js';
|
|
4
|
+
import { createLogger } from '../../core/utils/logger.js';
|
|
5
|
+
import { LruCache } from '../../core/utils/lru-cache.js';
|
|
6
|
+
import { PMI_BITCOIN_LIGHTNING_BOLT11 } from '../pmis.js';
|
|
7
|
+
import { fetchLnurlPayParams, requestZapInvoice } from '../nip57/lnurl.js';
|
|
8
|
+
import { createZapRequest, getBolt11FromZapReceipt, } from '../nip57/zap-events.js';
|
|
9
|
+
/**
|
|
10
|
+
* CEP-8 server payment processor for PMI `bitcoin-lightning-bolt11` backed by NIP-57 zap receipts.
|
|
11
|
+
*
|
|
12
|
+
* This issues a BOLT11 invoice via LNURL-pay zap request (kind 9734) and verifies settlement by
|
|
13
|
+
* subscribing for zap receipts (kind 9735).
|
|
14
|
+
*/
|
|
15
|
+
export class LnBolt11ZapPaymentProcessor {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
18
|
+
this.pmi = PMI_BITCOIN_LIGHTNING_BOLT11;
|
|
19
|
+
this.lnAddress = options.lnAddress;
|
|
20
|
+
this.relayUrls =
|
|
21
|
+
(_d = (_a = options.relayUrls) !== null && _a !== void 0 ? _a : (_c = (_b = options.relayHandler) === null || _b === void 0 ? void 0 : _b.getRelayUrls) === null || _c === void 0 ? void 0 : _c.call(_b)) !== null && _d !== void 0 ? _d : LnBolt11ZapPaymentProcessor.DEFAULT_RELAY_URLS;
|
|
22
|
+
this.relayHandler =
|
|
23
|
+
(_e = options.relayHandler) !== null && _e !== void 0 ? _e : new ApplesauceRelayPool([...this.relayUrls]);
|
|
24
|
+
this.ttlSeconds = (_f = options.ttlSeconds) !== null && _f !== void 0 ? _f : 300;
|
|
25
|
+
this.logger = createLogger('payments/zap-processor');
|
|
26
|
+
this.signerSecretKey = generateSecretKey();
|
|
27
|
+
this.inFlightVerifications = new LruCache((_g = options.maxInFlightVerifications) !== null && _g !== void 0 ? _g : 5000);
|
|
28
|
+
this.pendingInvoices = new LruCache((_h = options.maxPendingInvoices) !== null && _h !== void 0 ? _h : 10000);
|
|
29
|
+
}
|
|
30
|
+
async createPaymentRequired(params) {
|
|
31
|
+
if (this.relayUrls.length === 0) {
|
|
32
|
+
throw new Error('LnBolt11ZapPaymentProcessor requires relayUrls or a relayHandler with getRelayUrls() for verification');
|
|
33
|
+
}
|
|
34
|
+
const amountMsats = Math.round(params.amount * 1000);
|
|
35
|
+
this.logger.debug('Creating zap invoice', {
|
|
36
|
+
requestEventId: params.requestEventId,
|
|
37
|
+
amountSats: params.amount,
|
|
38
|
+
});
|
|
39
|
+
const payParams = await fetchLnurlPayParams({ lnAddress: this.lnAddress });
|
|
40
|
+
if (!payParams.allowsNostr || !payParams.nostrPubkey) {
|
|
41
|
+
throw new Error('LNURL-pay endpoint does not support NIP-57 zaps');
|
|
42
|
+
}
|
|
43
|
+
if (typeof payParams.minSendable === 'number' &&
|
|
44
|
+
amountMsats < payParams.minSendable) {
|
|
45
|
+
throw new Error(`Amount is below lnurl minimum: ${amountMsats}msat < ${payParams.minSendable}msat`);
|
|
46
|
+
}
|
|
47
|
+
if (typeof payParams.maxSendable === 'number' &&
|
|
48
|
+
amountMsats > payParams.maxSendable) {
|
|
49
|
+
throw new Error(`Amount is above lnurl maximum: ${amountMsats}msat > ${payParams.maxSendable}msat`);
|
|
50
|
+
}
|
|
51
|
+
const zapRequest = finalizeEvent(createZapRequest({
|
|
52
|
+
amountMsats,
|
|
53
|
+
recipientPubkey: payParams.nostrPubkey,
|
|
54
|
+
relays: this.relayUrls,
|
|
55
|
+
}), this.signerSecretKey);
|
|
56
|
+
const { pr } = await requestZapInvoice({
|
|
57
|
+
callback: payParams.callback,
|
|
58
|
+
amountMsats,
|
|
59
|
+
zapRequestJson: JSON.stringify(zapRequest),
|
|
60
|
+
});
|
|
61
|
+
const since = Math.floor(Date.now() / 1000) - 10;
|
|
62
|
+
this.pendingInvoices.set(pr, {
|
|
63
|
+
expectedZapperPubkey: payParams.nostrPubkey,
|
|
64
|
+
since,
|
|
65
|
+
amountMsats,
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
amount: params.amount,
|
|
69
|
+
pay_req: pr,
|
|
70
|
+
pmi: this.pmi,
|
|
71
|
+
ttl: this.ttlSeconds,
|
|
72
|
+
_meta: {
|
|
73
|
+
rail: 'nip57',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async verifyPayment(params) {
|
|
78
|
+
const existing = this.inFlightVerifications.get(params.pay_req);
|
|
79
|
+
if (existing)
|
|
80
|
+
return await existing;
|
|
81
|
+
const run = this.verifyPaymentInternal(params).finally(() => {
|
|
82
|
+
this.inFlightVerifications.delete(params.pay_req);
|
|
83
|
+
});
|
|
84
|
+
this.inFlightVerifications.set(params.pay_req, run);
|
|
85
|
+
return await run;
|
|
86
|
+
}
|
|
87
|
+
async verifyPaymentInternal(params) {
|
|
88
|
+
if (this.relayUrls.length === 0) {
|
|
89
|
+
throw new Error('LnBolt11ZapPaymentProcessor requires relayUrls or a relayHandler with getRelayUrls() for verification');
|
|
90
|
+
}
|
|
91
|
+
const pending = this.pendingInvoices.get(params.pay_req);
|
|
92
|
+
if (!pending) {
|
|
93
|
+
// Stateless fallback: re-fetch pay params to get the expected zapper pubkey.
|
|
94
|
+
const payParams = await fetchLnurlPayParams({
|
|
95
|
+
lnAddress: this.lnAddress,
|
|
96
|
+
});
|
|
97
|
+
if (!payParams.nostrPubkey) {
|
|
98
|
+
throw new Error('Cannot verify zap receipt: missing lnurl nostrPubkey');
|
|
99
|
+
}
|
|
100
|
+
this.pendingInvoices.set(params.pay_req, {
|
|
101
|
+
expectedZapperPubkey: payParams.nostrPubkey,
|
|
102
|
+
since: Math.floor(Date.now() / 1000) - this.ttlSeconds,
|
|
103
|
+
amountMsats: NaN,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const meta = this.pendingInvoices.get(params.pay_req);
|
|
107
|
+
if (!meta) {
|
|
108
|
+
throw new Error('Cannot verify zap receipt: missing pending invoice metadata');
|
|
109
|
+
}
|
|
110
|
+
const filter = {
|
|
111
|
+
kinds: [kinds.Zap],
|
|
112
|
+
authors: [meta.expectedZapperPubkey],
|
|
113
|
+
since: meta.since,
|
|
114
|
+
};
|
|
115
|
+
this.logger.debug('Subscribing for zap receipts', {
|
|
116
|
+
requestEventId: params.requestEventId,
|
|
117
|
+
relayCount: this.relayUrls.length,
|
|
118
|
+
expectedZapperPubkey: meta.expectedZapperPubkey,
|
|
119
|
+
since: meta.since,
|
|
120
|
+
});
|
|
121
|
+
const receiptPromise = new Promise((resolve, reject) => {
|
|
122
|
+
var _a;
|
|
123
|
+
let unsubscribe;
|
|
124
|
+
let settled = false;
|
|
125
|
+
const onAbort = () => {
|
|
126
|
+
settled = true;
|
|
127
|
+
cleanup();
|
|
128
|
+
reject(new Error('verifyPayment aborted'));
|
|
129
|
+
};
|
|
130
|
+
const cleanup = () => {
|
|
131
|
+
var _a;
|
|
132
|
+
try {
|
|
133
|
+
unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
|
|
134
|
+
}
|
|
135
|
+
catch (_b) {
|
|
136
|
+
// best-effort
|
|
137
|
+
}
|
|
138
|
+
unsubscribe = undefined;
|
|
139
|
+
(_a = params.abortSignal) === null || _a === void 0 ? void 0 : _a.removeEventListener('abort', onAbort);
|
|
140
|
+
};
|
|
141
|
+
(_a = params.abortSignal) === null || _a === void 0 ? void 0 : _a.addEventListener('abort', onAbort, { once: true });
|
|
142
|
+
void this.relayHandler
|
|
143
|
+
.subscribe([filter], (event) => {
|
|
144
|
+
try {
|
|
145
|
+
const bolt11 = getBolt11FromZapReceipt(event);
|
|
146
|
+
if (bolt11 !== params.pay_req)
|
|
147
|
+
return;
|
|
148
|
+
this.logger.info('Zap receipt matched invoice', {
|
|
149
|
+
requestEventId: params.requestEventId,
|
|
150
|
+
zapReceiptEventId: event.id,
|
|
151
|
+
});
|
|
152
|
+
settled = true;
|
|
153
|
+
cleanup();
|
|
154
|
+
resolve(event);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
settled = true;
|
|
158
|
+
cleanup();
|
|
159
|
+
reject(error);
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
.then((u) => {
|
|
163
|
+
unsubscribe = u;
|
|
164
|
+
if (settled) {
|
|
165
|
+
// Event/abort/error may have fired before subscribe resolved.
|
|
166
|
+
unsubscribe();
|
|
167
|
+
unsubscribe = undefined;
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
.catch((error) => {
|
|
171
|
+
settled = true;
|
|
172
|
+
cleanup();
|
|
173
|
+
reject(error);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
const receipt = await receiptPromise;
|
|
177
|
+
return { _meta: { zap_receipt_event_id: receipt.id } };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Defaults for the minimal constructor (lnAddress-only). These are public relays;
|
|
181
|
+
// callers can override via options.relayUrls.
|
|
182
|
+
LnBolt11ZapPaymentProcessor.DEFAULT_RELAY_URLS = [
|
|
183
|
+
'wss://relay.damus.io',
|
|
184
|
+
'wss://relay.nostr.band',
|
|
185
|
+
'wss://nos.lol',
|
|
186
|
+
];
|
|
187
|
+
//# sourceMappingURL=ln-bolt11-zap-payment-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln-bolt11-zap-payment-processor.js","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-zap-payment-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,7 @@ export interface ApplesauceRelayPoolOptions {
|
|
|
15
15
|
export declare class ApplesauceRelayPool implements RelayHandler {
|
|
16
16
|
private readonly relayUrls;
|
|
17
17
|
private relayGroup;
|
|
18
|
-
private
|
|
19
|
-
private activeUnsubscribers;
|
|
18
|
+
private readonly subscriptions;
|
|
20
19
|
private static readonly PUBLISH_ATTEMPT_TIMEOUT_MS;
|
|
21
20
|
private static readonly PUBLISH_RETRY_INTERVAL_MS;
|
|
22
21
|
private static readonly PUBLISH_ERROR_LOG_INTERVAL_MS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applesauce-relay-pool.d.ts","sourceRoot":"","sources":["../../../src/relay/applesauce-relay-pool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAoBrD,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,MAGzB,CAAC;
|
|
1
|
+
{"version":3,"file":"applesauce-relay-pool.d.ts","sourceRoot":"","sources":["../../../src/relay/applesauce-relay-pool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAoBrD,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,MAGzB,CAAC;AAeF,oDAAoD;AACpD,MAAM,WAAW,0BAA0B;IACzC,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwC;IAGtE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAU;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAO;IACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,CAAU;IAG/D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IAGxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,2BAA2B,CAAS;IAE5D,OAAO,CAAC,uBAAuB;IA8B/B,OAAO,CAAC,gBAAgB,CAAC,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,eAAe,CAAC,CAAgB;IACxC,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAe;IAE7B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAY7B;;;OAGG;YACW,gBAAgB;IAwF9B,OAAO,CAAC,WAAW;IA4CnB;;;;OAIG;gBACS,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,0BAA0B;IASlE;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;;OAGG;IACG,OAAO,CACX,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,WAAW,CAAA;KAAE,GACnC,OAAO,CAAC,IAAI,CAAC;IA0DhB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAkC1B;;;;;OAKG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EACpC,MAAM,CAAC,EAAE,MAAM,IAAI,GAClB,OAAO,CAAC,MAAM,IAAI,CAAC;IA6BtB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BjC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,WAAW,IAAI,IAAI;IAgBnB;;;OAGG;IACH,YAAY,IAAI,MAAM,EAAE;IAIxB,sCAAsC;IACtC,OAAO,CAAC,eAAe;IAOvB,0EAA0E;IAC1E,OAAO,CAAC,gBAAgB;IA2BxB,gEAAgE;YAClD,aAAa;IA+E3B,6EAA6E;IAC7E,OAAO,CAAC,OAAO;CA2ChB"}
|
|
@@ -145,8 +145,7 @@ export class ApplesauceRelayPool {
|
|
|
145
145
|
*/
|
|
146
146
|
constructor(relayUrls, opts) {
|
|
147
147
|
var _a, _b;
|
|
148
|
-
this.
|
|
149
|
-
this.activeUnsubscribers = [];
|
|
148
|
+
this.subscriptions = new Map();
|
|
150
149
|
this.destroy$ = new Subject();
|
|
151
150
|
this.relayObservers = [];
|
|
152
151
|
this.relays = [];
|
|
@@ -274,28 +273,25 @@ export class ApplesauceRelayPool {
|
|
|
274
273
|
*/
|
|
275
274
|
async subscribe(filters, onEvent, onEose) {
|
|
276
275
|
const id = `sub:${Date.now()}:${Math.random().toString(16).slice(2)}`;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.
|
|
280
|
-
// Start the subscription and store the unsubscribe handle
|
|
281
|
-
const unsubscribe = this.createSubscription(filters, onEvent, onEose);
|
|
282
|
-
this.activeUnsubscribers.push(unsubscribe);
|
|
276
|
+
const state = { id, filters, onEvent, onEose };
|
|
277
|
+
state.unsubscribe = this.createSubscription(filters, onEvent, onEose);
|
|
278
|
+
this.subscriptions.set(id, state);
|
|
283
279
|
// Start ping monitor lazily on first subscription
|
|
284
280
|
logger.debug('Starting ping monitor from subscribe', {
|
|
285
|
-
|
|
281
|
+
activeSubscriptions: this.subscriptions.size,
|
|
286
282
|
});
|
|
287
283
|
this.startPingMonitor();
|
|
288
284
|
// Return a per-subscription unsubscribe that also cleans up replay intent.
|
|
289
285
|
return () => {
|
|
286
|
+
var _a, _b;
|
|
290
287
|
try {
|
|
291
|
-
unsubscribe();
|
|
288
|
+
(_b = (_a = this.subscriptions.get(id)) === null || _a === void 0 ? void 0 : _a.unsubscribe) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
292
289
|
}
|
|
293
290
|
finally {
|
|
294
|
-
this.
|
|
295
|
-
this.activeUnsubscribers = this.activeUnsubscribers.filter((u) => u !== unsubscribe);
|
|
291
|
+
this.subscriptions.delete(id);
|
|
296
292
|
// If nothing is subscribed, stop pinging (otherwise liveness can
|
|
297
293
|
// incorrectly rebuild a perfectly healthy-but-idle pool).
|
|
298
|
-
if (this.
|
|
294
|
+
if (this.subscriptions.size === 0) {
|
|
299
295
|
this.stopPingMonitor();
|
|
300
296
|
}
|
|
301
297
|
}
|
|
@@ -333,11 +329,13 @@ export class ApplesauceRelayPool {
|
|
|
333
329
|
* Used internally during rebuild to preserve subscription intent for replay.
|
|
334
330
|
*/
|
|
335
331
|
stopActiveSubscriptions() {
|
|
332
|
+
var _a;
|
|
336
333
|
logger.debug('Stopping active subscriptions (preserving descriptors)');
|
|
337
334
|
try {
|
|
338
|
-
for (const
|
|
339
|
-
unsubscribe();
|
|
340
|
-
|
|
335
|
+
for (const sub of this.subscriptions.values()) {
|
|
336
|
+
(_a = sub.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(sub);
|
|
337
|
+
sub.unsubscribe = undefined;
|
|
338
|
+
}
|
|
341
339
|
}
|
|
342
340
|
catch (error) {
|
|
343
341
|
logger.error('Error while stopping active subscriptions', { error });
|
|
@@ -347,10 +345,13 @@ export class ApplesauceRelayPool {
|
|
|
347
345
|
* Unsubscribes from all active subscriptions and clears subscription descriptors.
|
|
348
346
|
*/
|
|
349
347
|
unsubscribe() {
|
|
348
|
+
var _a;
|
|
350
349
|
logger.debug('Unsubscribing from all subscriptions');
|
|
351
350
|
try {
|
|
352
|
-
this.
|
|
353
|
-
|
|
351
|
+
for (const sub of this.subscriptions.values()) {
|
|
352
|
+
(_a = sub.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(sub);
|
|
353
|
+
}
|
|
354
|
+
this.subscriptions.clear();
|
|
354
355
|
// If nothing is subscribed, stop pinging (otherwise liveness can
|
|
355
356
|
// incorrectly rebuild a perfectly healthy-but-idle pool).
|
|
356
357
|
this.stopPingMonitor();
|
|
@@ -401,12 +402,12 @@ export class ApplesauceRelayPool {
|
|
|
401
402
|
// If there are no active subscriptions, don't perform liveness checks.
|
|
402
403
|
// applesauce-relay may legitimately close sockets after `keepAlive` when
|
|
403
404
|
// nothing is subscribed, and that should not trigger a rebuild.
|
|
404
|
-
if (this.
|
|
405
|
+
if (this.subscriptions.size === 0) {
|
|
405
406
|
logger.debug('Skipping liveness check: no active subscriptions');
|
|
406
407
|
return;
|
|
407
408
|
}
|
|
408
409
|
logger.debug('Running liveness check', {
|
|
409
|
-
|
|
410
|
+
activeSubscriptions: this.subscriptions.size,
|
|
410
411
|
relayCount: this.relays.length,
|
|
411
412
|
});
|
|
412
413
|
const relays = this.relays;
|
|
@@ -484,8 +485,8 @@ export class ApplesauceRelayPool {
|
|
|
484
485
|
this.relayGroup = new RelayGroup(this.relays);
|
|
485
486
|
// Replay all stored subscription descriptors
|
|
486
487
|
// Note: New subscriptions added during rebuild will be replayed after this completes
|
|
487
|
-
for (const
|
|
488
|
-
|
|
488
|
+
for (const sub of this.subscriptions.values()) {
|
|
489
|
+
sub.unsubscribe = this.createSubscription(sub.filters, sub.onEvent, sub.onEose);
|
|
489
490
|
}
|
|
490
491
|
logger.info('Relay pool rebuilt successfully');
|
|
491
492
|
// Resume ping monitor
|