@contextvm/sdk 0.3.2 → 0.4.1
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/utils/utils.d.ts +11 -0
- package/dist/esm/core/utils/utils.d.ts.map +1 -1
- package/dist/esm/core/utils/utils.js +15 -0
- package/dist/esm/core/utils/utils.js.map +1 -1
- package/dist/esm/gateway/index.d.ts.map +1 -1
- package/dist/esm/gateway/index.js +5 -0
- package/dist/esm/gateway/index.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/payments/cap-tags.d.ts +13 -0
- package/dist/esm/payments/cap-tags.d.ts.map +1 -0
- package/dist/esm/payments/cap-tags.js +38 -0
- package/dist/esm/payments/cap-tags.js.map +1 -0
- package/dist/esm/payments/client-payments.d.ts +10 -0
- package/dist/esm/payments/client-payments.d.ts.map +1 -0
- package/dist/esm/payments/client-payments.js +108 -0
- package/dist/esm/payments/client-payments.js.map +1 -0
- package/dist/esm/payments/fake-payment-handler.d.ts +19 -0
- package/dist/esm/payments/fake-payment-handler.d.ts.map +1 -0
- package/dist/esm/payments/fake-payment-handler.js +16 -0
- package/dist/esm/payments/fake-payment-handler.js.map +1 -0
- package/dist/esm/payments/fake-payment-processor.d.ts +34 -0
- package/dist/esm/payments/fake-payment-processor.d.ts.map +1 -0
- package/dist/esm/payments/fake-payment-processor.js +29 -0
- package/dist/esm/payments/fake-payment-processor.js.map +1 -0
- package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.d.ts +24 -0
- package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.d.ts.map +1 -0
- package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.js +44 -0
- package/dist/esm/payments/handlers/ln-bolt11-lnbits-payment-handler.js.map +1 -0
- package/dist/esm/payments/handlers/ln-bolt11-nwc-payment-handler.d.ts +20 -0
- package/dist/esm/payments/handlers/ln-bolt11-nwc-payment-handler.d.ts.map +1 -0
- package/dist/esm/payments/handlers/ln-bolt11-nwc-payment-handler.js +36 -0
- package/dist/esm/payments/handlers/ln-bolt11-nwc-payment-handler.js.map +1 -0
- package/dist/esm/payments/index.d.ts +17 -0
- package/dist/esm/payments/index.d.ts.map +1 -0
- package/dist/esm/payments/index.js +17 -0
- package/dist/esm/payments/index.js.map +1 -0
- package/dist/esm/payments/nip47/connection.d.ts +9 -0
- package/dist/esm/payments/nip47/connection.d.ts.map +1 -0
- package/dist/esm/payments/nip47/connection.js +34 -0
- package/dist/esm/payments/nip47/connection.js.map +1 -0
- package/dist/esm/payments/nip47/nwc-client.d.ts +38 -0
- package/dist/esm/payments/nip47/nwc-client.d.ts.map +1 -0
- package/dist/esm/payments/nip47/nwc-client.js +144 -0
- package/dist/esm/payments/nip47/nwc-client.js.map +1 -0
- package/dist/esm/payments/nip47/types.d.ts +54 -0
- package/dist/esm/payments/nip47/types.d.ts.map +1 -0
- package/dist/esm/payments/nip47/types.js +2 -0
- package/dist/esm/payments/nip47/types.js.map +1 -0
- package/dist/esm/payments/nip47/utils.d.ts +7 -0
- package/dist/esm/payments/nip47/utils.d.ts.map +1 -0
- package/dist/esm/payments/nip47/utils.js +9 -0
- package/dist/esm/payments/nip47/utils.js.map +1 -0
- package/dist/esm/payments/pmi-tags.d.ts +8 -0
- package/dist/esm/payments/pmi-tags.d.ts.map +1 -0
- package/dist/esm/payments/pmi-tags.js +9 -0
- package/dist/esm/payments/pmi-tags.js.map +1 -0
- package/dist/esm/payments/pmis.d.ts +7 -0
- package/dist/esm/payments/pmis.d.ts.map +1 -0
- package/dist/esm/payments/pmis.js +7 -0
- package/dist/esm/payments/pmis.js.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.d.ts +50 -0
- package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.d.ts.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.js +133 -0
- package/dist/esm/payments/processors/ln-bolt11-lnbits-payment-processor.js.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.d.ts +41 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.d.ts.map +1 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.js +129 -0
- package/dist/esm/payments/processors/ln-bolt11-nwc-payment-processor.js.map +1 -0
- package/dist/esm/payments/server-payments.d.ts +32 -0
- package/dist/esm/payments/server-payments.d.ts.map +1 -0
- package/dist/esm/payments/server-payments.js +199 -0
- package/dist/esm/payments/server-payments.js.map +1 -0
- package/dist/esm/payments/server-transport-payments.d.ts +7 -0
- package/dist/esm/payments/server-transport-payments.d.ts.map +1 -0
- package/dist/esm/payments/server-transport-payments.js +14 -0
- package/dist/esm/payments/server-transport-payments.js.map +1 -0
- package/dist/esm/payments/types.d.ts +174 -0
- package/dist/esm/payments/types.d.ts.map +1 -0
- package/dist/esm/payments/types.js +5 -0
- package/dist/esm/payments/types.js.map +1 -0
- package/dist/esm/transport/nostr-client-transport.d.ts +32 -0
- package/dist/esm/transport/nostr-client-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-client-transport.js +87 -18
- package/dist/esm/transport/nostr-client-transport.js.map +1 -1
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts +24 -0
- package/dist/esm/transport/nostr-server/announcement-manager.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server/announcement-manager.js +48 -5
- package/dist/esm/transport/nostr-server/announcement-manager.js.map +1 -1
- package/dist/esm/transport/nostr-server-transport.d.ts +30 -0
- package/dist/esm/transport/nostr-server-transport.d.ts.map +1 -1
- package/dist/esm/transport/nostr-server-transport.js +78 -5
- package/dist/esm/transport/nostr-server-transport.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/payments/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,iDAAiD,CAAC;AAChE,cAAc,oDAAoD,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './fake-payment-handler.js';
|
|
3
|
+
export * from './fake-payment-processor.js';
|
|
4
|
+
export * from './client-payments.js';
|
|
5
|
+
export * from './server-payments.js';
|
|
6
|
+
export * from './server-transport-payments.js';
|
|
7
|
+
export * from './pmi-tags.js';
|
|
8
|
+
export * from './cap-tags.js';
|
|
9
|
+
export * from './pmis.js';
|
|
10
|
+
export * from './nip47/connection.js';
|
|
11
|
+
export * from './nip47/nwc-client.js';
|
|
12
|
+
export * from './nip47/types.js';
|
|
13
|
+
export * from './handlers/ln-bolt11-nwc-payment-handler.js';
|
|
14
|
+
export * from './handlers/ln-bolt11-lnbits-payment-handler.js';
|
|
15
|
+
export * from './processors/ln-bolt11-nwc-payment-processor.js';
|
|
16
|
+
export * from './processors/ln-bolt11-lnbits-payment-processor.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/payments/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,iDAAiD,CAAC;AAChE,cAAc,oDAAoD,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NwcConnection } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses a Nostr Wallet Connect connection string.
|
|
4
|
+
*
|
|
5
|
+
* Example:
|
|
6
|
+
* `nostr+walletconnect://<wallet_pubkey>?relay=wss://...&relay=wss://...&secret=<hex>`
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseNwcConnectionString(connectionString: string): NwcConnection;
|
|
9
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/payments/nip47/connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUhD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,MAAM,GACvB,aAAa,CAuBf"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const Hex32 = z.string().regex(/^[0-9a-f]{64}$/i);
|
|
3
|
+
const PubkeyHex = z.string().regex(/^[0-9a-f]{64}$/i);
|
|
4
|
+
function normalizeRelayUrl(relay) {
|
|
5
|
+
// Minimal normalization (we can tighten later).
|
|
6
|
+
return relay.trim();
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parses a Nostr Wallet Connect connection string.
|
|
10
|
+
*
|
|
11
|
+
* Example:
|
|
12
|
+
* `nostr+walletconnect://<wallet_pubkey>?relay=wss://...&relay=wss://...&secret=<hex>`
|
|
13
|
+
*/
|
|
14
|
+
export function parseNwcConnectionString(connectionString) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const url = new URL(connectionString);
|
|
17
|
+
// NIP-47 uses protocol `nostr+walletconnect://` and places the wallet pubkey
|
|
18
|
+
// in either host or pathname (implementations differ).
|
|
19
|
+
const walletPubkeyRaw = (((_a = url.pathname) === null || _a === void 0 ? void 0 : _a.replace(/^\//, '')) || url.host).trim();
|
|
20
|
+
const secret = (_b = url.searchParams.get('secret')) === null || _b === void 0 ? void 0 : _b.trim();
|
|
21
|
+
const relayParams = url.searchParams.getAll('relay');
|
|
22
|
+
const relays = relayParams.map(normalizeRelayUrl).filter(Boolean);
|
|
23
|
+
if (!walletPubkeyRaw || !secret || relays.length === 0) {
|
|
24
|
+
throw new Error('Invalid NWC connection string');
|
|
25
|
+
}
|
|
26
|
+
const walletPubkey = PubkeyHex.parse(walletPubkeyRaw);
|
|
27
|
+
const clientSecretKeyHex = Hex32.parse(secret);
|
|
28
|
+
return {
|
|
29
|
+
walletPubkey,
|
|
30
|
+
relays,
|
|
31
|
+
clientSecretKeyHex,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../../src/payments/nip47/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAEtD,SAAS,iBAAiB,CAAC,KAAa;IACtC,gDAAgD;IAChD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,gBAAwB;;IAExB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAEtC,6EAA6E;IAC7E,uDAAuD;IACvD,MAAM,eAAe,GAAG,CAAC,CAAA,MAAA,GAAG,CAAC,QAAQ,0CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9E,MAAM,MAAM,GAAG,MAAA,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,0CAAE,IAAI,EAAE,CAAC;IAEtD,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElE,IAAI,CAAC,eAAe,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO;QACL,YAAY;QACZ,MAAM;QACN,kBAAkB;KACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RelayHandler } from '../../core/interfaces.js';
|
|
2
|
+
import type { NwcConnection, NwcRequest, NwcResponse } from './types.js';
|
|
3
|
+
export declare const NWC_INFO_KIND = 13194;
|
|
4
|
+
export declare const NWC_REQUEST_KIND = 23194;
|
|
5
|
+
export declare const NWC_RESPONSE_KIND = 23195;
|
|
6
|
+
export interface NwcClientOptions {
|
|
7
|
+
relayHandler: RelayHandler;
|
|
8
|
+
connection: NwcConnection;
|
|
9
|
+
/** How long to wait for a single NIP-47 response. @default 60_000 */
|
|
10
|
+
responseTimeoutMs?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Minimal NIP-47 client for request/response over relays.
|
|
14
|
+
*
|
|
15
|
+
* Policy: use `nip04` for encryption/decryption.
|
|
16
|
+
*
|
|
17
|
+
* Rationale: many real-world NWC wallets still use NIP-04; keep this client minimal and
|
|
18
|
+
* consistent with the working reference implementation.
|
|
19
|
+
*/
|
|
20
|
+
export declare class NwcClient {
|
|
21
|
+
private readonly relayHandler;
|
|
22
|
+
private readonly connection;
|
|
23
|
+
private readonly responseTimeoutMs;
|
|
24
|
+
private readonly logger;
|
|
25
|
+
private connected;
|
|
26
|
+
private requestQueue;
|
|
27
|
+
constructor(options: NwcClientOptions);
|
|
28
|
+
connect(): Promise<void>;
|
|
29
|
+
disconnect(): Promise<void>;
|
|
30
|
+
request<M extends string, P, R>(params: {
|
|
31
|
+
method: M;
|
|
32
|
+
request: NwcRequest<M, P>;
|
|
33
|
+
resultType: M;
|
|
34
|
+
responseResultGuard?: (result: unknown) => result is R;
|
|
35
|
+
expirationSeconds?: number;
|
|
36
|
+
}): Promise<NwcResponse<M, R>>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=nwc-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nwc-client.d.ts","sourceRoot":"","sources":["../../../../src/payments/nip47/nwc-client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzE,eAAO,MAAM,aAAa,QAAsB,CAAC;AACjD,eAAO,MAAM,gBAAgB,QAAyB,CAAC;AACvD,eAAO,MAAM,iBAAiB,QAA0B,CAAC;AAUzD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,aAAa,CAAC;IAE1B,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,SAAS,CAAS;IAI1B,OAAO,CAAC,YAAY,CAAoC;gBAErC,OAAO,EAAE,gBAAgB;IAO/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE;QACnD,MAAM,EAAE,CAAC,CAAC;QACV,OAAO,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,UAAU,EAAE,CAAC,CAAC;QACd,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC;QACvD,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CA6H/B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { kinds, nip04 } from 'nostr-tools';
|
|
2
|
+
import { finalizeEvent } from 'nostr-tools/pure';
|
|
3
|
+
import { hexToBytes } from 'nostr-tools/utils';
|
|
4
|
+
import { createLogger } from '../../core/utils/logger.js';
|
|
5
|
+
import { withTimeout } from '../../core/utils/utils.js';
|
|
6
|
+
export const NWC_INFO_KIND = kinds.NWCWalletInfo;
|
|
7
|
+
export const NWC_REQUEST_KIND = kinds.NWCWalletRequest;
|
|
8
|
+
export const NWC_RESPONSE_KIND = kinds.NWCWalletResponse;
|
|
9
|
+
function nowSeconds() {
|
|
10
|
+
return Math.floor(Date.now() / 1000);
|
|
11
|
+
}
|
|
12
|
+
function getTagValue(tags, name) {
|
|
13
|
+
var _a;
|
|
14
|
+
return (_a = tags.find((t) => t[0] === name)) === null || _a === void 0 ? void 0 : _a[1];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Minimal NIP-47 client for request/response over relays.
|
|
18
|
+
*
|
|
19
|
+
* Policy: use `nip04` for encryption/decryption.
|
|
20
|
+
*
|
|
21
|
+
* Rationale: many real-world NWC wallets still use NIP-04; keep this client minimal and
|
|
22
|
+
* consistent with the working reference implementation.
|
|
23
|
+
*/
|
|
24
|
+
export class NwcClient {
|
|
25
|
+
constructor(options) {
|
|
26
|
+
var _a;
|
|
27
|
+
this.connected = false;
|
|
28
|
+
// RelayHandler only exposes a global `unsubscribe()`. To avoid cross-request
|
|
29
|
+
// interference, we serialize NWC requests per client instance.
|
|
30
|
+
this.requestQueue = Promise.resolve();
|
|
31
|
+
this.relayHandler = options.relayHandler;
|
|
32
|
+
this.connection = options.connection;
|
|
33
|
+
this.responseTimeoutMs = (_a = options.responseTimeoutMs) !== null && _a !== void 0 ? _a : 60000;
|
|
34
|
+
this.logger = createLogger('payments/nwc');
|
|
35
|
+
}
|
|
36
|
+
async connect() {
|
|
37
|
+
if (this.connected)
|
|
38
|
+
return;
|
|
39
|
+
await this.relayHandler.connect();
|
|
40
|
+
this.connected = true;
|
|
41
|
+
}
|
|
42
|
+
async disconnect() {
|
|
43
|
+
this.relayHandler.unsubscribe();
|
|
44
|
+
if (!this.connected)
|
|
45
|
+
return;
|
|
46
|
+
await this.relayHandler.disconnect();
|
|
47
|
+
this.connected = false;
|
|
48
|
+
}
|
|
49
|
+
async request(params) {
|
|
50
|
+
const now = nowSeconds();
|
|
51
|
+
const run = async () => {
|
|
52
|
+
await this.connect();
|
|
53
|
+
const clientSecretKey = hexToBytes(this.connection.clientSecretKeyHex);
|
|
54
|
+
const plaintext = JSON.stringify(params.request);
|
|
55
|
+
const encryptedContent = await nip04.encrypt(this.connection.clientSecretKeyHex, this.connection.walletPubkey, plaintext);
|
|
56
|
+
const eventTemplate = {
|
|
57
|
+
kind: NWC_REQUEST_KIND,
|
|
58
|
+
created_at: now,
|
|
59
|
+
content: encryptedContent,
|
|
60
|
+
tags: [
|
|
61
|
+
['p', this.connection.walletPubkey],
|
|
62
|
+
// NOTE: Historically, NWC has used NIP-04 and many implementations do not require this tag.
|
|
63
|
+
// Keeping it to aid wallet-side debugging.
|
|
64
|
+
['encryption', 'nip04'],
|
|
65
|
+
...(params.expirationSeconds
|
|
66
|
+
? [['expiration', String(params.expirationSeconds)]]
|
|
67
|
+
: []),
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
const signedRequest = finalizeEvent(eventTemplate, clientSecretKey);
|
|
71
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
72
|
+
const filters = [
|
|
73
|
+
{
|
|
74
|
+
kinds: [NWC_RESPONSE_KIND],
|
|
75
|
+
'#e': [signedRequest.id],
|
|
76
|
+
authors: [this.connection.walletPubkey],
|
|
77
|
+
since: now - 5,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
this.logger.debug('subscribe for response', {
|
|
81
|
+
method: params.method,
|
|
82
|
+
requestId: signedRequest.id,
|
|
83
|
+
filters,
|
|
84
|
+
});
|
|
85
|
+
void this.relayHandler
|
|
86
|
+
.subscribe(filters, (event) => {
|
|
87
|
+
this.logger.debug('received response event', {
|
|
88
|
+
method: params.method,
|
|
89
|
+
requestId: signedRequest.id,
|
|
90
|
+
eventId: event.id,
|
|
91
|
+
pubkey: event.pubkey,
|
|
92
|
+
});
|
|
93
|
+
resolve(event);
|
|
94
|
+
})
|
|
95
|
+
.catch(reject);
|
|
96
|
+
});
|
|
97
|
+
this.logger.debug('publish request', {
|
|
98
|
+
method: params.method,
|
|
99
|
+
requestId: signedRequest.id,
|
|
100
|
+
encryption: 'nip04',
|
|
101
|
+
});
|
|
102
|
+
await this.relayHandler.publish(signedRequest);
|
|
103
|
+
try {
|
|
104
|
+
const responseEvent = await withTimeout(responsePromise, this.responseTimeoutMs, `NWC response timed out for ${params.method}`);
|
|
105
|
+
// Validate correlation.
|
|
106
|
+
const eTag = getTagValue(responseEvent.tags, 'e');
|
|
107
|
+
if (eTag !== signedRequest.id) {
|
|
108
|
+
throw new Error('NWC response did not correlate to request');
|
|
109
|
+
}
|
|
110
|
+
const decrypted = await nip04.decrypt(this.connection.clientSecretKeyHex, responseEvent.pubkey, responseEvent.content);
|
|
111
|
+
const parsed = JSON.parse(decrypted);
|
|
112
|
+
if (parsed.result_type !== params.resultType) {
|
|
113
|
+
throw new Error(`Unexpected NWC result_type: ${String(parsed.result_type)} (expected ${params.resultType})`);
|
|
114
|
+
}
|
|
115
|
+
if (parsed.error) {
|
|
116
|
+
return parsed;
|
|
117
|
+
}
|
|
118
|
+
if (params.responseResultGuard && parsed.result !== null) {
|
|
119
|
+
if (!params.responseResultGuard(parsed.result)) {
|
|
120
|
+
throw new Error('Unexpected NWC result shape');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
// Best-effort cleanup (RelayHandler has global unsubscribe).
|
|
127
|
+
this.relayHandler.unsubscribe();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const prev = this.requestQueue;
|
|
131
|
+
let release;
|
|
132
|
+
this.requestQueue = new Promise((r) => {
|
|
133
|
+
release = r;
|
|
134
|
+
});
|
|
135
|
+
await prev;
|
|
136
|
+
try {
|
|
137
|
+
return await run();
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
release === null || release === void 0 ? void 0 : release();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=nwc-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nwc-client.js","sourceRoot":"","sources":["../../../../src/payments/nip47/nwc-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type NwcEncryptionMode = 'nip44_v2';
|
|
2
|
+
export interface NwcConnection {
|
|
3
|
+
/** Wallet service pubkey (hex). */
|
|
4
|
+
walletPubkey: string;
|
|
5
|
+
/** Relay URLs for reaching the wallet service. */
|
|
6
|
+
relays: readonly string[];
|
|
7
|
+
/** Client secret key (hex, 32 bytes) used for signing and encryption. */
|
|
8
|
+
clientSecretKeyHex: string;
|
|
9
|
+
}
|
|
10
|
+
export type NwcRequest<M extends string = string, P = unknown> = {
|
|
11
|
+
method: M;
|
|
12
|
+
params: P;
|
|
13
|
+
};
|
|
14
|
+
export type NwcError = {
|
|
15
|
+
code: string;
|
|
16
|
+
message: string;
|
|
17
|
+
};
|
|
18
|
+
export type NwcResponse<T extends string = string, R = unknown> = {
|
|
19
|
+
result_type: T;
|
|
20
|
+
error: NwcError | null;
|
|
21
|
+
result: R | null;
|
|
22
|
+
};
|
|
23
|
+
export type NwcMakeInvoiceParams = {
|
|
24
|
+
/** Invoice amount in msats. */
|
|
25
|
+
amount: number;
|
|
26
|
+
description?: string;
|
|
27
|
+
expiry?: number;
|
|
28
|
+
};
|
|
29
|
+
export type NwcInvoiceState = 'pending' | 'settled' | 'accepted' | 'expired' | 'failed';
|
|
30
|
+
export type NwcInvoiceResult = {
|
|
31
|
+
type?: 'incoming' | 'outgoing';
|
|
32
|
+
state?: NwcInvoiceState;
|
|
33
|
+
invoice?: string;
|
|
34
|
+
payment_hash?: string;
|
|
35
|
+
preimage?: string;
|
|
36
|
+
created_at?: number;
|
|
37
|
+
expires_at?: number;
|
|
38
|
+
settled_at?: number;
|
|
39
|
+
amount?: number;
|
|
40
|
+
};
|
|
41
|
+
export type NwcLookupInvoiceParams = {
|
|
42
|
+
payment_hash?: string;
|
|
43
|
+
invoice?: string;
|
|
44
|
+
};
|
|
45
|
+
export type NwcPayInvoiceParams = {
|
|
46
|
+
invoice: string;
|
|
47
|
+
/** Optional amount override in msats (usually omitted for fixed-amount invoices). */
|
|
48
|
+
amount?: number;
|
|
49
|
+
};
|
|
50
|
+
export type NwcPayInvoiceResult = {
|
|
51
|
+
preimage?: string;
|
|
52
|
+
fees_paid?: number;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/payments/nip47/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,IAAI;IAC/D,MAAM,EAAE,CAAC,CAAC;IACV,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,IAAI;IAChE,WAAW,EAAE,CAAC,CAAC;IACf,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,CAAC;AAEb,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC/B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/payments/nip47/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/payments/nip47/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/payments/nip47/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,GAAG,IAAI,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PaymentProcessor, PmiTag } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds Nostr `pmi` tags for a set of server-side processors.
|
|
4
|
+
*
|
|
5
|
+
* Tag order is preserved and expresses server preference.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createPmiTagsFromProcessors(processors: readonly PaymentProcessor[]): PmiTag[];
|
|
8
|
+
//# sourceMappingURL=pmi-tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmi-tags.d.ts","sourceRoot":"","sources":["../../../src/payments/pmi-tags.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,SAAS,gBAAgB,EAAE,GACtC,MAAM,EAAE,CAEV"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds Nostr `pmi` tags for a set of server-side processors.
|
|
3
|
+
*
|
|
4
|
+
* Tag order is preserved and expresses server preference.
|
|
5
|
+
*/
|
|
6
|
+
export function createPmiTagsFromProcessors(processors) {
|
|
7
|
+
return processors.map((p) => ['pmi', p.pmi]);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=pmi-tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmi-tags.js","sourceRoot":"","sources":["../../../src/payments/pmi-tags.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAAuC;IAEvC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmis.d.ts","sourceRoot":"","sources":["../../../src/payments/pmis.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAG,0BAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmis.js","sourceRoot":"","sources":["../../../src/payments/pmis.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,0BAAmC,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PaymentProcessor, PaymentProcessorCreateParams, PaymentProcessorVerifyParams } from '../types.js';
|
|
2
|
+
export interface LnBolt11LnbitsPaymentProcessorOptions {
|
|
3
|
+
/** LNbits instance base URL (e.g. `https://lnbits.example.com`). */
|
|
4
|
+
lnbitsUrl: string;
|
|
5
|
+
/** LNbits wallet invoice/read key. */
|
|
6
|
+
lnbitsApiKey: string;
|
|
7
|
+
/** Optional HTTP Basic Auth credentials (`user:password`) for proxied instances. */
|
|
8
|
+
lnbitsBasicAuth?: string;
|
|
9
|
+
/** Fallback TTL in seconds for the payment request. @default 300 */
|
|
10
|
+
ttlSeconds?: number;
|
|
11
|
+
/** Invoice expiry in seconds passed to LNbits. @default ttlSeconds */
|
|
12
|
+
invoiceExpirySeconds?: number;
|
|
13
|
+
/** Poll interval for payment verification. @default 1500 */
|
|
14
|
+
pollIntervalMs?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* CEP-8 server payment processor for PMI `bitcoin-lightning-bolt11` backed by LNbits REST API.
|
|
18
|
+
*
|
|
19
|
+
* Creates BOLT11 invoices via the LNbits `/api/v1/payments` endpoint and polls
|
|
20
|
+
* for settlement using the same API.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LnBolt11LnbitsPaymentProcessor implements PaymentProcessor {
|
|
23
|
+
readonly pmi: "bitcoin-lightning-bolt11";
|
|
24
|
+
private readonly lnbitsUrl;
|
|
25
|
+
private readonly lnbitsApiKey;
|
|
26
|
+
private readonly lnbitsBasicAuth?;
|
|
27
|
+
private readonly ttlSeconds;
|
|
28
|
+
private readonly invoiceExpirySeconds;
|
|
29
|
+
private readonly pollIntervalMs;
|
|
30
|
+
private readonly logger;
|
|
31
|
+
constructor(options: LnBolt11LnbitsPaymentProcessorOptions);
|
|
32
|
+
private buildHeaders;
|
|
33
|
+
createPaymentRequired(params: PaymentProcessorCreateParams): Promise<{
|
|
34
|
+
amount: number;
|
|
35
|
+
pay_req: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
pmi: string;
|
|
38
|
+
ttl?: number;
|
|
39
|
+
}>;
|
|
40
|
+
verifyPayment(params: PaymentProcessorVerifyParams): Promise<{
|
|
41
|
+
_meta?: Record<string, unknown>;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Extract payment hash from a BOLT11 invoice by checking it against LNbits.
|
|
45
|
+
* LNbits returns the payment_hash when creating an invoice, but verifyPayment
|
|
46
|
+
* only receives pay_req. We decode it via LNbits decode endpoint.
|
|
47
|
+
*/
|
|
48
|
+
private getPaymentHashFromInvoice;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=ln-bolt11-lnbits-payment-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln-bolt11-lnbits-payment-processor.d.ts","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-lnbits-payment-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,EAC7B,MAAM,aAAa,CAAC;AAKrB,MAAM,WAAW,qCAAqC;IACpD,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,gBAAgB;IACrE,SAAgB,GAAG,6BAAgC;IAEnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEb,OAAO,EAAE,qCAAqC;IAUjE,OAAO,CAAC,YAAY;IAYP,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;KACd,CAAC;IA+CW,aAAa,CACxB,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IA0C/C;;;;OAIG;YACW,yBAAyB;CAoCxC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { PMI_BITCOIN_LIGHTNING_BOLT11 } from '../pmis.js';
|
|
2
|
+
import { createLogger } from '../../core/utils/logger.js';
|
|
3
|
+
import { sleep } from '../../core/utils/utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* CEP-8 server payment processor for PMI `bitcoin-lightning-bolt11` backed by LNbits REST API.
|
|
6
|
+
*
|
|
7
|
+
* Creates BOLT11 invoices via the LNbits `/api/v1/payments` endpoint and polls
|
|
8
|
+
* for settlement using the same API.
|
|
9
|
+
*/
|
|
10
|
+
export class LnBolt11LnbitsPaymentProcessor {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
var _a, _b, _c;
|
|
13
|
+
this.pmi = PMI_BITCOIN_LIGHTNING_BOLT11;
|
|
14
|
+
this.lnbitsUrl = options.lnbitsUrl.replace(/\/+$/, '');
|
|
15
|
+
this.lnbitsApiKey = options.lnbitsApiKey;
|
|
16
|
+
this.lnbitsBasicAuth = options.lnbitsBasicAuth;
|
|
17
|
+
this.ttlSeconds = (_a = options.ttlSeconds) !== null && _a !== void 0 ? _a : 300;
|
|
18
|
+
this.invoiceExpirySeconds = (_b = options.invoiceExpirySeconds) !== null && _b !== void 0 ? _b : this.ttlSeconds;
|
|
19
|
+
this.pollIntervalMs = (_c = options.pollIntervalMs) !== null && _c !== void 0 ? _c : 1500;
|
|
20
|
+
this.logger = createLogger('payments/lnbits-processor');
|
|
21
|
+
}
|
|
22
|
+
buildHeaders() {
|
|
23
|
+
const headers = {
|
|
24
|
+
'Content-Type': 'application/json',
|
|
25
|
+
'X-Api-Key': this.lnbitsApiKey,
|
|
26
|
+
};
|
|
27
|
+
if (this.lnbitsBasicAuth) {
|
|
28
|
+
const encoded = Buffer.from(this.lnbitsBasicAuth).toString('base64');
|
|
29
|
+
headers['Authorization'] = `Basic ${encoded}`;
|
|
30
|
+
}
|
|
31
|
+
return headers;
|
|
32
|
+
}
|
|
33
|
+
async createPaymentRequired(params) {
|
|
34
|
+
var _a;
|
|
35
|
+
const body = JSON.stringify({
|
|
36
|
+
out: false,
|
|
37
|
+
amount: params.amount,
|
|
38
|
+
memo: (_a = params.description) !== null && _a !== void 0 ? _a : `CVM payment: ${params.requestEventId.slice(0, 8)}`,
|
|
39
|
+
expiry: this.invoiceExpirySeconds,
|
|
40
|
+
});
|
|
41
|
+
const response = await fetch(`${this.lnbitsUrl}/api/v1/payments`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: this.buildHeaders(),
|
|
44
|
+
body,
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const text = await response.text();
|
|
48
|
+
throw new Error(`LNbits create invoice failed: ${response.status} ${text}`);
|
|
49
|
+
}
|
|
50
|
+
const result = (await response.json());
|
|
51
|
+
if (!result.payment_request) {
|
|
52
|
+
throw new Error('LNbits returned no payment_request');
|
|
53
|
+
}
|
|
54
|
+
this.logger.debug('Invoice created', {
|
|
55
|
+
requestEventId: params.requestEventId,
|
|
56
|
+
paymentHash: result.payment_hash,
|
|
57
|
+
amount: params.amount,
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
amount: params.amount,
|
|
61
|
+
pay_req: result.payment_request,
|
|
62
|
+
description: params.description,
|
|
63
|
+
pmi: this.pmi,
|
|
64
|
+
ttl: this.ttlSeconds,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async verifyPayment(params) {
|
|
68
|
+
var _a;
|
|
69
|
+
// We need the payment hash to check status. Derive it from the invoice
|
|
70
|
+
// by first looking it up via the decoded invoice endpoint, or by checking
|
|
71
|
+
// all recent payments. The simplest approach: decode the bolt11 to get the hash.
|
|
72
|
+
const paymentHash = await this.getPaymentHashFromInvoice(params.pay_req);
|
|
73
|
+
while (true) {
|
|
74
|
+
if ((_a = params.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
75
|
+
throw new Error('verifyPayment aborted');
|
|
76
|
+
}
|
|
77
|
+
const response = await fetch(`${this.lnbitsUrl}/api/v1/payments/${paymentHash}`, {
|
|
78
|
+
method: 'GET',
|
|
79
|
+
headers: this.buildHeaders(),
|
|
80
|
+
});
|
|
81
|
+
if (response.ok) {
|
|
82
|
+
const result = (await response.json());
|
|
83
|
+
this.logger.debug('Payment check', {
|
|
84
|
+
requestEventId: params.requestEventId,
|
|
85
|
+
paymentHash,
|
|
86
|
+
paid: result.paid,
|
|
87
|
+
});
|
|
88
|
+
if (result.paid) {
|
|
89
|
+
return { _meta: { payment_hash: paymentHash } };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
this.logger.debug('Payment check request failed', {
|
|
94
|
+
status: response.status,
|
|
95
|
+
paymentHash,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
await sleep(this.pollIntervalMs);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Extract payment hash from a BOLT11 invoice by checking it against LNbits.
|
|
103
|
+
* LNbits returns the payment_hash when creating an invoice, but verifyPayment
|
|
104
|
+
* only receives pay_req. We decode it via LNbits decode endpoint.
|
|
105
|
+
*/
|
|
106
|
+
async getPaymentHashFromInvoice(bolt11) {
|
|
107
|
+
const response = await fetch(`${this.lnbitsUrl}/api/v1/payments/decode`, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: this.buildHeaders(),
|
|
110
|
+
body: JSON.stringify({ data: bolt11 }),
|
|
111
|
+
});
|
|
112
|
+
if (response.ok) {
|
|
113
|
+
const decoded = (await response.json());
|
|
114
|
+
if (decoded.payment_hash) {
|
|
115
|
+
return decoded.payment_hash;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Fallback: search recent payments for matching bolt11
|
|
119
|
+
const paymentsResponse = await fetch(`${this.lnbitsUrl}/api/v1/payments?limit=50`, {
|
|
120
|
+
method: 'GET',
|
|
121
|
+
headers: this.buildHeaders(),
|
|
122
|
+
});
|
|
123
|
+
if (paymentsResponse.ok) {
|
|
124
|
+
const payments = (await paymentsResponse.json());
|
|
125
|
+
const match = payments.find((p) => p.bolt11 === bolt11);
|
|
126
|
+
if (match) {
|
|
127
|
+
return match.payment_hash;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
throw new Error('Could not resolve payment hash from invoice');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=ln-bolt11-lnbits-payment-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln-bolt11-lnbits-payment-processor.js","sourceRoot":"","sources":["../../../../src/payments/processors/ln-bolt11-lnbits-payment-processor.ts"],"names":[],"mappings":"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"}
|