@ghostlytools/cli 1.3.5 → 1.3.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.
Files changed (53) hide show
  1. package/dist/assets/{api-CgPyYfjH.js → api-Br3msjtR.js} +2 -2
  2. package/dist/assets/{api-Do7NjRg2.js → api-z9mlywrn.js} +9 -9
  3. package/dist/assets/{api-Do7NjRg2.js.map → api-z9mlywrn.js.map} +1 -1
  4. package/dist/assets/{apiKit-eh5qBKIl.js → apiKit-lX3Xx_hY.js} +2 -2
  5. package/dist/assets/{apiKit-eh5qBKIl.js.map → apiKit-lX3Xx_hY.js.map} +1 -1
  6. package/dist/assets/{apps-Cl9MtELY.js → apps-BUK6bEKW.js} +2 -2
  7. package/dist/assets/{apps-Cl9MtELY.js.map → apps-BUK6bEKW.js.map} +1 -1
  8. package/dist/assets/{apps-B83dRFga.js → apps-Dn7rCafG.js} +1 -1
  9. package/dist/assets/{arkade-B5Xn40bC.js → arkade-uqAXA5BT.js} +2 -2
  10. package/dist/assets/{arkade-B5Xn40bC.js.map → arkade-uqAXA5BT.js.map} +1 -1
  11. package/dist/assets/{backup-BjZcDFjL.js → backup-CJQK5Miu.js} +4 -4
  12. package/dist/assets/{backup-BjZcDFjL.js.map → backup-CJQK5Miu.js.map} +1 -1
  13. package/dist/assets/{backup-CDOh2tuw.js → backup-_JnqeFZb.js} +1 -1
  14. package/dist/assets/buttons-DDB9Xdha.js +2 -0
  15. package/dist/assets/{buttons-CUKHafux.js → buttons-DDvTuViY.js} +3 -3
  16. package/dist/assets/{buttons-CUKHafux.js.map → buttons-DDvTuViY.js.map} +1 -1
  17. package/dist/assets/{envelope-wspXCjle.js → envelope-BqvBb6hC.js} +2 -2
  18. package/dist/assets/{envelope-wspXCjle.js.map → envelope-BqvBb6hC.js.map} +1 -1
  19. package/dist/assets/{groupFiles-Cfrjo3YS.js → groupFiles-B1lL6wch.js} +3 -3
  20. package/dist/assets/{groupFiles-Cfrjo3YS.js.map → groupFiles-B1lL6wch.js.map} +1 -1
  21. package/dist/assets/{host-BdS-7nRW.js → host-DFzlKU3P.js} +8 -8
  22. package/dist/assets/{host-BdS-7nRW.js.map → host-DFzlKU3P.js.map} +1 -1
  23. package/dist/assets/{hyperdhtRelay-H97Vz73W.js → hyperdhtRelay-DwlOY6aD.js} +2 -2
  24. package/dist/assets/{hyperdhtRelay-H97Vz73W.js.map → hyperdhtRelay-DwlOY6aD.js.map} +1 -1
  25. package/dist/assets/{irohWeb-jErC-V0J.js → irohWeb-DZDCyL9b.js} +2 -2
  26. package/dist/assets/{irohWeb-jErC-V0J.js.map → irohWeb-DZDCyL9b.js.map} +1 -1
  27. package/dist/assets/{main-C14lA5aK.js → main-DgbdDDif.js} +14 -14
  28. package/dist/assets/{main-C14lA5aK.js.map → main-DgbdDDif.js.map} +1 -1
  29. package/dist/assets/{mainline-CYI1tZT7.js → mainline-BHE5-R3A.js} +2 -2
  30. package/dist/assets/{mainline-CYI1tZT7.js.map → mainline-BHE5-R3A.js.map} +1 -1
  31. package/dist/assets/{networkReason-CiHrd-kG.js → networkReason-Btv4b2C4.js} +2 -2
  32. package/dist/assets/{networkReason-CiHrd-kG.js.map → networkReason-Btv4b2C4.js.map} +1 -1
  33. package/dist/assets/{nwc-0JYm8Vys.js → nwc-z0pa5zql.js} +3 -3
  34. package/dist/assets/{nwc-0JYm8Vys.js.map → nwc-z0pa5zql.js.map} +1 -1
  35. package/dist/assets/{nwcProvider-2coJAsqr.js → nwcProvider-C1AhPoFW.js} +2 -2
  36. package/dist/assets/{nwcProvider-2coJAsqr.js.map → nwcProvider-C1AhPoFW.js.map} +1 -1
  37. package/dist/assets/{registry-sML83UvL.js → registry-C09xXyx-.js} +1 -1
  38. package/dist/assets/{registry-BptCF3tL.js → registry-JrnwUWmh.js} +3 -3
  39. package/dist/assets/{registry-BptCF3tL.js.map → registry-JrnwUWmh.js.map} +1 -1
  40. package/dist/assets/{resolve-2hGrvTen.js → resolve-Ssq1nDy4.js} +2 -2
  41. package/dist/assets/{resolve-2hGrvTen.js.map → resolve-Ssq1nDy4.js.map} +1 -1
  42. package/dist/assets/{server-BbPiCghe.js → server-D6FSznK5.js} +19 -13
  43. package/dist/assets/server-D6FSznK5.js.map +1 -0
  44. package/dist/assets/{src-BLzG4Sfv.js → src-XhjSWnp-.js} +7 -2
  45. package/dist/assets/{src-BLzG4Sfv.js.map → src-XhjSWnp-.js.map} +1 -1
  46. package/dist/assets/{turnRefs-ClWSgjb0.js → turnRefs-Cle33IoV.js} +2 -2
  47. package/dist/assets/{turnRefs-ClWSgjb0.js.map → turnRefs-Cle33IoV.js.map} +1 -1
  48. package/dist/assets/{usdt-zwyn_AQK.js → usdt-DO86yko2.js} +3 -3
  49. package/dist/assets/{usdt-zwyn_AQK.js.map → usdt-DO86yko2.js.map} +1 -1
  50. package/dist/ghostly.mjs +1 -1
  51. package/package.json +1 -1
  52. package/dist/assets/buttons-CFabREDv.js +0 -2
  53. package/dist/assets/server-BbPiCghe.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Qc as RelayTransport, dl as parseRelayPayload, hl as publicKeyFromZ32, il as isDiscoveryBudgetError, ll as newerPacket } from "./src-BLzG4Sfv.js";
1
+ import { Qc as RelayTransport, dl as parseRelayPayload, hl as publicKeyFromZ32, il as isDiscoveryBudgetError, ll as newerPacket } from "./src-XhjSWnp-.js";
2
2
  import { ed25519 } from "@noble/curves/ed25519.js";
3
3
  import { createHash } from "node:crypto";
4
4
  import DHT from "bittorrent-dht";
@@ -195,4 +195,4 @@ var RelaysAndDht = class {
195
195
  //#endregion
196
196
  export { Mainline, RelaysAndDht };
197
197
 
198
- //# sourceMappingURL=mainline-CYI1tZT7.js.map
198
+ //# sourceMappingURL=mainline-BHE5-R3A.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mainline-CYI1tZT7.js","names":[],"sources":["../../src/runtime/mainline.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport DHT from \"bittorrent-dht\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport {\n RelayTransport, isDiscoveryBudgetError, newerPacket, parseRelayPayload, publicKeyFromZ32,\n type DiscoveryStatus, type GhostRecord, type Identity, type PkarrRequestOptions, type PkarrTransport, type RelayTransportOptions, type SignedPacket,\n} from \"@ghostly/core\";\n\n/**\n * Pkarr over the Mainline DHT (BEP44), from Node, as the Desktop reaches it from Rust: the relays are HTTP bridges to\n * this same DHT, so a headless Ghostly that speaks it directly keeps finding its contacts while the relays fail (they\n * answered HTTP 500 for more than ten minutes on 2026-09-27, and a group's edges stayed down all that while).\n *\n * A Pkarr packet is a BEP44 mutable item: the key is the Ed25519 public key, the value the DNS packet, the sequence\n * number its timestamp in microseconds, and the signature the one the relay payload already carries (over\n * `3:seqi<seq>e1:v<len>:<v>`). So one signed payload goes to the relays and to the DHT unchanged.\n */\n\nexport interface MainlineOptions {\n /** `host:port` nodes to start from; the public routers when absent; none with `false` (a testnet's first node). */\n bootstrap?: string[] | false;\n /** Address to bind (a loopback testnet binds 127.0.0.1). */\n host?: string;\n /** How long a lookup may take before it is given up, in ms. */\n timeoutMs?: number;\n}\n\nconst SIGNATURE = 64, TIMESTAMP = 8;\nconst verify = (sig: Uint8Array, message: Uint8Array, key: Uint8Array) => { try { return ed25519.verify(sig, message, key); } catch { return false; } };\n\n/** A DHT node of this process: puts and gets Pkarr packets. */\nexport class Mainline {\n private readonly dht: DHT;\n /** Its UDP socket is bound. */\n readonly listening: Promise<void>;\n private readonly timeoutMs: number;\n\n constructor(options: MainlineOptions = {}) {\n this.timeoutMs = options.timeoutMs ?? 20_000;\n const bootstrap = options.bootstrap === false ? false : options.bootstrap?.length ? options.bootstrap : undefined;\n this.dht = new DHT({ verify, ...(bootstrap !== undefined ? { bootstrap } : {}), ...(options.host ? { host: options.host } : {}) });\n this.listening = new Promise((resolve) => this.dht.listen(0, options.host, () => resolve()));\n // A node of the table that errors must not end the process.\n this.dht.on(\"error\", () => {});\n }\n\n /** Adds a node (a testnet's peers). */\n addNode(host: string, port: number): void { this.dht.addNode({ host, port }); }\n address(): { port: number } { return this.dht.address() as { port: number }; }\n\n /** Puts a relay payload (`<signature><timestamp><DNS packet>`) as the mutable item of `pubKeyZ32`; resolves with the nodes that took it. */\n put(pubKeyZ32: string, payload: Uint8Array): Promise<number> {\n const k = Buffer.from(publicKeyFromZ32(pubKeyZ32));\n const sig = Buffer.from(payload.subarray(0, SIGNATURE));\n const seq = Number(new DataView(payload.buffer, payload.byteOffset + SIGNATURE, TIMESTAMP).getBigUint64(0));\n const v = Buffer.from(payload.subarray(SIGNATURE + TIMESTAMP));\n return this.bounded(new Promise((resolve, reject) => {\n this.dht.put({ k, v, seq, sig }, (error, _hash, nodes) => {\n if (error) reject(error); else if (!nodes) reject(new Error(\"No DHT node took the packet\")); else resolve(nodes);\n });\n }));\n }\n\n /** The newest packet of `pubKeyZ32` the DHT holds, checked; null when nobody has one. */\n get(pubKeyZ32: string): Promise<SignedPacket | null> {\n const k = Buffer.from(publicKeyFromZ32(pubKeyZ32));\n // A mutable item without salt is found under the SHA-1 of its public key (BEP44).\n const target = createHash(\"sha1\").update(k).digest();\n return this.bounded(new Promise((resolve, reject) => {\n this.dht.get(target, { cache: false }, (error, found) => {\n if (error) return reject(error);\n if (!found?.v || !found.sig) return resolve(null);\n const timestamp = new Uint8Array(TIMESTAMP);\n new DataView(timestamp.buffer).setBigUint64(0, BigInt(found.seq));\n const payload = new Uint8Array(SIGNATURE + TIMESTAMP + found.v.length);\n payload.set(found.sig, 0); payload.set(timestamp, SIGNATURE); payload.set(found.v, SIGNATURE + TIMESTAMP);\n try { resolve(parseRelayPayload(pubKeyZ32, payload)); } catch { resolve(null); }\n });\n }));\n }\n\n private bounded<T>(work: Promise<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(\"DHT lookup timed out\")), this.timeoutMs);\n work.then((value) => { clearTimeout(timer); resolve(value); }, (error) => { clearTimeout(timer); reject(error); });\n });\n }\n\n destroy(): Promise<void> { return new Promise((resolve) => this.dht.destroy(() => resolve())); }\n}\n\n/**\n * The relays first, as the web app reaches Pkarr (its contacts read only the relays), and the DHT beside them: every\n * packet also goes to the DHT, and a read goes there when every relay is failing or the read failed for anything but\n * this app's own request budget (that is a wait, not an outage).\n *\n * `pinned`: the relays given are the only ones (`GHOSTLY_PKARR_RELAYS`, a private network): the profile's `relays`\n * setting does not replace them. With no DHT (`dht` null), the relays alone carry every packet.\n */\nexport class RelaysAndDht implements PkarrTransport {\n readonly relays: RelayTransport;\n private lastVia: \"relay\" | \"dht\" = \"relay\";\n\n constructor(private readonly dht: Mainline | null, relays: RelayTransportOptions = {}, private readonly pinned = false) {\n this.relays = new RelayTransport(relays);\n }\n\n async publish(identity: Identity, records: GhostRecord[], options: PkarrRequestOptions = {}): Promise<void> {\n // BEP44 sequence numbers must strictly increase, on the relays and on the DHT alike: one payload for both, dated\n // past every packet put or read under the key (`RelayTransport.publishDated`), whichever clock dated those.\n // With the DHT, the packet goes there whatever the relays' budgets say: signed every time. Without it (a private\n // network's relays only), a publish none of them takes now is not signed at all.\n await this.relays.publishDated(identity, records, (key, payload, timestamp, conflict) => this.putBoth(key, payload, options, conflict, timestamp), options, false, this.dht !== null);\n }\n\n publishPayload(pubKeyZ32: string, payload: Uint8Array, options: PkarrRequestOptions = {}): Promise<void> {\n return this.putBoth(pubKeyZ32, payload, options);\n }\n\n /**\n * `timestamp`: the payload was just signed here (`publish`), dated so; its signature is not checked again on the way\n * to the relays. Without it (`publishPayload`, signed elsewhere) the relays' side checks it to read its date.\n */\n private async putBoth(pubKeyZ32: string, payload: Uint8Array, options: PkarrRequestOptions, conflict?: (relay: string) => void, timestamp?: bigint): Promise<void> {\n const toRelays = () => timestamp === undefined\n ? this.relays.publishPayload(pubKeyZ32, payload, options, conflict)\n : this.relays.putSigned(pubKeyZ32, payload, timestamp, options, conflict);\n if (!this.dht) return toRelays();\n const onDht = this.dht.put(pubKeyZ32, payload);\n onDht.catch(() => {});\n try {\n await toRelays();\n } catch (error) {\n // Held back by this app's budget: the relays take it when it frees (browser contacts read only them).\n if (isDiscoveryBudgetError(error)) throw error;\n // The relays failed: out on the DHT is out (a Pkarr relay reads the DHT for a key it has not got).\n await onDht.catch(() => { throw error; });\n }\n }\n\n async resolve(pubKeyZ32: string, options: PkarrRequestOptions = {}): Promise<SignedPacket | null> {\n if (!this.dht) return this.relays.resolve(pubKeyZ32, options);\n let fromRelays: SignedPacket | null = null, failed: unknown = null;\n // Every relay left alone for failing: the relays answer from what they last saw, if anything; the DHT is asked.\n const down = () => this.relays.discovery().relays.every((relay) => relay.state === \"failing\");\n if (!down()) {\n try { fromRelays = await this.relays.resolve(pubKeyZ32, options); this.lastVia = \"relay\"; } catch (error) {\n if (isDiscoveryBudgetError(error)) throw error;\n failed = error;\n }\n if (!failed && !down()) return fromRelays;\n }\n try {\n const fromDht = await this.dht.get(pubKeyZ32);\n this.lastVia = \"dht\";\n if (fromDht) this.relays.sawTimestamp(pubKeyZ32, fromDht.timestampMicros);\n return newerPacket(fromRelays, fromDht);\n } catch (error) {\n if (fromRelays) return fromRelays;\n throw failed ?? error;\n }\n }\n\n describe(): { protocol: string; relays: string[] } {\n return { protocol: this.dht ? \"Pkarr relays (HTTP), and the Mainline DHT (BEP44) directly\" : \"Pkarr relays (HTTP)\", relays: this.relays.describe().relays };\n }\n discovery(): DiscoveryStatus {\n const status = this.relays.discovery();\n return this.lastVia === \"dht\" ? { ...status, path: { via: \"dht\" } } : status;\n }\n subscribe(listener: Parameters<RelayTransport[\"subscribe\"]>[0]): () => void { return this.relays.subscribe(listener); }\n /** A relay's answer only: a packet the DHT hands back when the relays are down may be older than one already read. */\n readAnsweredAt(pubKeyZ32: string): number | undefined { return this.relays.readAnsweredAt(pubKeyZ32); }\n readHeldBackFor(pubKeyZ32: string): number | undefined { return this.relays.readHeldBackFor(pubKeyZ32); }\n onServerTime(listener: Parameters<RelayTransport[\"onServerTime\"]>[0]): () => void { return this.relays.onServerTime(listener); }\n configure({ relays }: { relays: string[]; readRelays: boolean }): void { if (!this.pinned) this.relays.setRelays(relays); }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mainline-BHE5-R3A.js","names":[],"sources":["../../src/runtime/mainline.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport DHT from \"bittorrent-dht\";\nimport { ed25519 } from \"@noble/curves/ed25519.js\";\nimport {\n RelayTransport, isDiscoveryBudgetError, newerPacket, parseRelayPayload, publicKeyFromZ32,\n type DiscoveryStatus, type GhostRecord, type Identity, type PkarrRequestOptions, type PkarrTransport, type RelayTransportOptions, type SignedPacket,\n} from \"@ghostly/core\";\n\n/**\n * Pkarr over the Mainline DHT (BEP44), from Node, as the Desktop reaches it from Rust: the relays are HTTP bridges to\n * this same DHT, so a headless Ghostly that speaks it directly keeps finding its contacts while the relays fail (they\n * answered HTTP 500 for more than ten minutes on 2026-09-27, and a group's edges stayed down all that while).\n *\n * A Pkarr packet is a BEP44 mutable item: the key is the Ed25519 public key, the value the DNS packet, the sequence\n * number its timestamp in microseconds, and the signature the one the relay payload already carries (over\n * `3:seqi<seq>e1:v<len>:<v>`). So one signed payload goes to the relays and to the DHT unchanged.\n */\n\nexport interface MainlineOptions {\n /** `host:port` nodes to start from; the public routers when absent; none with `false` (a testnet's first node). */\n bootstrap?: string[] | false;\n /** Address to bind (a loopback testnet binds 127.0.0.1). */\n host?: string;\n /** How long a lookup may take before it is given up, in ms. */\n timeoutMs?: number;\n}\n\nconst SIGNATURE = 64, TIMESTAMP = 8;\nconst verify = (sig: Uint8Array, message: Uint8Array, key: Uint8Array) => { try { return ed25519.verify(sig, message, key); } catch { return false; } };\n\n/** A DHT node of this process: puts and gets Pkarr packets. */\nexport class Mainline {\n private readonly dht: DHT;\n /** Its UDP socket is bound. */\n readonly listening: Promise<void>;\n private readonly timeoutMs: number;\n\n constructor(options: MainlineOptions = {}) {\n this.timeoutMs = options.timeoutMs ?? 20_000;\n const bootstrap = options.bootstrap === false ? false : options.bootstrap?.length ? options.bootstrap : undefined;\n this.dht = new DHT({ verify, ...(bootstrap !== undefined ? { bootstrap } : {}), ...(options.host ? { host: options.host } : {}) });\n this.listening = new Promise((resolve) => this.dht.listen(0, options.host, () => resolve()));\n // A node of the table that errors must not end the process.\n this.dht.on(\"error\", () => {});\n }\n\n /** Adds a node (a testnet's peers). */\n addNode(host: string, port: number): void { this.dht.addNode({ host, port }); }\n address(): { port: number } { return this.dht.address() as { port: number }; }\n\n /** Puts a relay payload (`<signature><timestamp><DNS packet>`) as the mutable item of `pubKeyZ32`; resolves with the nodes that took it. */\n put(pubKeyZ32: string, payload: Uint8Array): Promise<number> {\n const k = Buffer.from(publicKeyFromZ32(pubKeyZ32));\n const sig = Buffer.from(payload.subarray(0, SIGNATURE));\n const seq = Number(new DataView(payload.buffer, payload.byteOffset + SIGNATURE, TIMESTAMP).getBigUint64(0));\n const v = Buffer.from(payload.subarray(SIGNATURE + TIMESTAMP));\n return this.bounded(new Promise((resolve, reject) => {\n this.dht.put({ k, v, seq, sig }, (error, _hash, nodes) => {\n if (error) reject(error); else if (!nodes) reject(new Error(\"No DHT node took the packet\")); else resolve(nodes);\n });\n }));\n }\n\n /** The newest packet of `pubKeyZ32` the DHT holds, checked; null when nobody has one. */\n get(pubKeyZ32: string): Promise<SignedPacket | null> {\n const k = Buffer.from(publicKeyFromZ32(pubKeyZ32));\n // A mutable item without salt is found under the SHA-1 of its public key (BEP44).\n const target = createHash(\"sha1\").update(k).digest();\n return this.bounded(new Promise((resolve, reject) => {\n this.dht.get(target, { cache: false }, (error, found) => {\n if (error) return reject(error);\n if (!found?.v || !found.sig) return resolve(null);\n const timestamp = new Uint8Array(TIMESTAMP);\n new DataView(timestamp.buffer).setBigUint64(0, BigInt(found.seq));\n const payload = new Uint8Array(SIGNATURE + TIMESTAMP + found.v.length);\n payload.set(found.sig, 0); payload.set(timestamp, SIGNATURE); payload.set(found.v, SIGNATURE + TIMESTAMP);\n try { resolve(parseRelayPayload(pubKeyZ32, payload)); } catch { resolve(null); }\n });\n }));\n }\n\n private bounded<T>(work: Promise<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(\"DHT lookup timed out\")), this.timeoutMs);\n work.then((value) => { clearTimeout(timer); resolve(value); }, (error) => { clearTimeout(timer); reject(error); });\n });\n }\n\n destroy(): Promise<void> { return new Promise((resolve) => this.dht.destroy(() => resolve())); }\n}\n\n/**\n * The relays first, as the web app reaches Pkarr (its contacts read only the relays), and the DHT beside them: every\n * packet also goes to the DHT, and a read goes there when every relay is failing or the read failed for anything but\n * this app's own request budget (that is a wait, not an outage).\n *\n * `pinned`: the relays given are the only ones (`GHOSTLY_PKARR_RELAYS`, a private network): the profile's `relays`\n * setting does not replace them. With no DHT (`dht` null), the relays alone carry every packet.\n */\nexport class RelaysAndDht implements PkarrTransport {\n readonly relays: RelayTransport;\n private lastVia: \"relay\" | \"dht\" = \"relay\";\n\n constructor(private readonly dht: Mainline | null, relays: RelayTransportOptions = {}, private readonly pinned = false) {\n this.relays = new RelayTransport(relays);\n }\n\n async publish(identity: Identity, records: GhostRecord[], options: PkarrRequestOptions = {}): Promise<void> {\n // BEP44 sequence numbers must strictly increase, on the relays and on the DHT alike: one payload for both, dated\n // past every packet put or read under the key (`RelayTransport.publishDated`), whichever clock dated those.\n // With the DHT, the packet goes there whatever the relays' budgets say: signed every time. Without it (a private\n // network's relays only), a publish none of them takes now is not signed at all.\n await this.relays.publishDated(identity, records, (key, payload, timestamp, conflict) => this.putBoth(key, payload, options, conflict, timestamp), options, false, this.dht !== null);\n }\n\n publishPayload(pubKeyZ32: string, payload: Uint8Array, options: PkarrRequestOptions = {}): Promise<void> {\n return this.putBoth(pubKeyZ32, payload, options);\n }\n\n /**\n * `timestamp`: the payload was just signed here (`publish`), dated so; its signature is not checked again on the way\n * to the relays. Without it (`publishPayload`, signed elsewhere) the relays' side checks it to read its date.\n */\n private async putBoth(pubKeyZ32: string, payload: Uint8Array, options: PkarrRequestOptions, conflict?: (relay: string) => void, timestamp?: bigint): Promise<void> {\n const toRelays = () => timestamp === undefined\n ? this.relays.publishPayload(pubKeyZ32, payload, options, conflict)\n : this.relays.putSigned(pubKeyZ32, payload, timestamp, options, conflict);\n if (!this.dht) return toRelays();\n const onDht = this.dht.put(pubKeyZ32, payload);\n onDht.catch(() => {});\n try {\n await toRelays();\n } catch (error) {\n // Held back by this app's budget: the relays take it when it frees (browser contacts read only them).\n if (isDiscoveryBudgetError(error)) throw error;\n // The relays failed: out on the DHT is out (a Pkarr relay reads the DHT for a key it has not got).\n await onDht.catch(() => { throw error; });\n }\n }\n\n async resolve(pubKeyZ32: string, options: PkarrRequestOptions = {}): Promise<SignedPacket | null> {\n if (!this.dht) return this.relays.resolve(pubKeyZ32, options);\n let fromRelays: SignedPacket | null = null, failed: unknown = null;\n // Every relay left alone for failing: the relays answer from what they last saw, if anything; the DHT is asked.\n const down = () => this.relays.discovery().relays.every((relay) => relay.state === \"failing\");\n if (!down()) {\n try { fromRelays = await this.relays.resolve(pubKeyZ32, options); this.lastVia = \"relay\"; } catch (error) {\n if (isDiscoveryBudgetError(error)) throw error;\n failed = error;\n }\n if (!failed && !down()) return fromRelays;\n }\n try {\n const fromDht = await this.dht.get(pubKeyZ32);\n this.lastVia = \"dht\";\n if (fromDht) this.relays.sawTimestamp(pubKeyZ32, fromDht.timestampMicros);\n return newerPacket(fromRelays, fromDht);\n } catch (error) {\n if (fromRelays) return fromRelays;\n throw failed ?? error;\n }\n }\n\n describe(): { protocol: string; relays: string[] } {\n return { protocol: this.dht ? \"Pkarr relays (HTTP), and the Mainline DHT (BEP44) directly\" : \"Pkarr relays (HTTP)\", relays: this.relays.describe().relays };\n }\n discovery(): DiscoveryStatus {\n const status = this.relays.discovery();\n return this.lastVia === \"dht\" ? { ...status, path: { via: \"dht\" } } : status;\n }\n subscribe(listener: Parameters<RelayTransport[\"subscribe\"]>[0]): () => void { return this.relays.subscribe(listener); }\n /** A relay's answer only: a packet the DHT hands back when the relays are down may be older than one already read. */\n readAnsweredAt(pubKeyZ32: string): number | undefined { return this.relays.readAnsweredAt(pubKeyZ32); }\n readHeldBackFor(pubKeyZ32: string): number | undefined { return this.relays.readHeldBackFor(pubKeyZ32); }\n onServerTime(listener: Parameters<RelayTransport[\"onServerTime\"]>[0]): () => void { return this.relays.onServerTime(listener); }\n configure({ relays }: { relays: string[]; readRelays: boolean }): void { if (!this.pinned) this.relays.setRelays(relays); }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Xn as engineError, Zn as engineText } from "./src-BLzG4Sfv.js";
1
+ import { Xn as engineError, Zn as engineText } from "./src-XhjSWnp-.js";
2
2
  import { f as store, i as STORES, m as wrap, p as transact, u as openDb } from "./idb-B5L8wuOm.js";
3
3
  //#region ../browser/src/engine/paymentAdapters/persistence.ts
4
4
  /**
@@ -151,4 +151,4 @@ function rpcHost(url) {
151
151
  //#endregion
152
152
  export { sealSeed as a, newDeviceKey as i, rpcHost as n, unsealSeed as o, intentRepository as r, networkReason as t };
153
153
 
154
- //# sourceMappingURL=networkReason-CiHrd-kG.js.map
154
+ //# sourceMappingURL=networkReason-Btv4b2C4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"networkReason-CiHrd-kG.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/persistence.ts","../../../browser/src/engine/paymentAdapters/networkReason.ts"],"sourcesContent":["import { engineError, engineText } from \"@ghostly/core\";\nimport { STORES, openDb, store, transact, wrap } from \"../../shared/idb\";\nimport type { IntentRepository, SavedIntent } from \"./coordinator\";\n/**\n * A USDT payment is one transaction at one account nonce. Another payment from the same account and chain that is\n * submitted or of unknown outcome holds its nonce until it confirms. A review made after it was sent took the next\n * nonce and may go at once. One made before (or read from an RPC that had not seen it yet) has the same or a lower\n * nonce: sent, it would replace the earlier transaction or be dropped, so it is refused. A row with no nonce refuses.\n */\nfunction nonceTaken(review:SavedIntent[\"review\"],intents:SavedIntent[]):boolean {\n if(review.method!==\"usdt\")return false;\n const from=review.evm?.from?.toLowerCase(), nonce=review.evm?.nonce;\n return intents.some(({review:other})=>other.id!==review.id && other.method===\"usdt\" && other.chainId===review.chainId && other.evm?.from?.toLowerCase()===from && [\"submitted\",\"unknown\"].includes(other.state)\n && !(typeof nonce===\"number\" && typeof other.evm?.nonce===\"number\" && nonce>other.evm.nonce));\n}\nexport const intentRepository: IntentRepository = {\n async get(id) { return wrap<SavedIntent | undefined>((await store(STORES.intents,\"readonly\")).get(id)); },\n async list() { return wrap<SavedIntent[]>((await store(STORES.intents,\"readonly\")).getAll()); },\n async put(intent) { await transact([STORES.intents],s=>{s[STORES.intents].put(intent);}); },\n async claim(id) {\n const tx=(await openDb()).transaction(STORES.intents,\"readwrite\");\n return new Promise<SavedIntent>((resolve,reject)=>{\n let saved:SavedIntent;\n let reason=engineText(\"alreadySubmitted\");\n const request=tx.objectStore(STORES.intents).getAll();\n request.onsuccess=()=>{\n const intents:SavedIntent[]=request.result;\n saved=intents.find(item=>item.review.id===id)!;\n if(!saved || saved.review.state!==\"pending\") {tx.abort();return;}\n const duplicate=saved.review.requestId && intents.some(({review})=>review.id!==id && review.requestId===saved.review.requestId && review.linkId===saved.review.linkId && [\"submitted\",\"settled\",\"unknown\"].includes(review.state));\n if(duplicate){tx.abort();return;}\n if(nonceTaken(saved.review,intents)){reason=engineText(\"sentAfterReview\");tx.abort();return;}\n saved.review={...saved.review,state:\"submitted\",error:undefined,submittedAt:Date.now()};\n tx.objectStore(STORES.intents).put(saved);\n };\n tx.oncomplete=()=>resolve(saved);\n tx.onabort=tx.onerror=()=>reject(new Error(reason));\n });\n },\n async cancel(id) {\n const tx=(await openDb()).transaction(STORES.intents,\"readwrite\");\n return new Promise<SavedIntent>((resolve,reject)=>{\n let saved:SavedIntent;\n const request=tx.objectStore(STORES.intents).get(id);\n request.onsuccess=()=>{\n saved=request.result;\n if(!saved || saved.review.state!==\"pending\"){tx.abort();return;}\n saved.review={...saved.review,state:\"cancelled\"};\n tx.objectStore(STORES.intents).put(saved);\n };\n tx.oncomplete=()=>resolve(saved);\n tx.onabort=tx.onerror=()=>reject(engineError(\"cannotCancelSubmitted\"));\n });\n },\n};\n/** Key for a wallet that needs no password: its seed is protected like the Cashu proofs in the same database. */\nexport function newDeviceKey():string {return btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32)))).replace(/=+$/,\"\");}\nexport interface EncryptedSeed {version:1;salt:number[];iv:number[];ciphertext:number[]}\nasync function passwordKey(password:string,salt:Uint8Array<ArrayBuffer>) {\n const material=await crypto.subtle.importKey(\"raw\",new TextEncoder().encode(password),\"PBKDF2\",false,[\"deriveKey\"]);\n return crypto.subtle.deriveKey({name:\"PBKDF2\",hash:\"SHA-256\",salt,iterations:600000},material,{name:\"AES-GCM\",length:256},false,[\"encrypt\",\"decrypt\"]);\n}\nexport async function sealSeed(seed:string,password:string):Promise<EncryptedSeed> {\n if(password.length<12)throw new Error(\"Use at least 12 characters for the wallet password\");\n const salt=crypto.getRandomValues(new Uint8Array(16)),iv=crypto.getRandomValues(new Uint8Array(12));\n const ciphertext=await crypto.subtle.encrypt({name:\"AES-GCM\",iv},await passwordKey(password,salt),new TextEncoder().encode(seed));\n return {version:1,salt:[...salt],iv:[...iv],ciphertext:[...new Uint8Array(ciphertext)]};\n}\nexport async function unsealSeed(seed:EncryptedSeed,password:string):Promise<string> {\n if(seed.version!==1)throw new Error(\"Unsupported wallet backup version\");\n try {return new TextDecoder().decode(await crypto.subtle.decrypt({name:\"AES-GCM\",iv:new Uint8Array(seed.iv)},await passwordKey(password,new Uint8Array(seed.salt)),new Uint8Array(seed.ciphertext)));}\n catch {throw new Error(\"Could not unlock the wallet. Check the password and backup.\");}\n}\n","import { engineText } from \"@ghostly/core\";\n\n/**\n * A request's failure as a person says it, when the browser's own words say nothing: a request that timed out or was\n * given up (\"Fetch is aborted\" in Safari, \"signal timed out\" in Chromium) did not answer in time; one that never left\n * (\"Failed to fetch\", \"Load failed\") could not reach it. `host` names what was asked, when known. Anything else is\n * `null`: its own words are kept.\n */\nexport function networkReason(error: unknown, host?: string): string | null {\n const name = error instanceof Error ? error.name : \"\";\n const text = error instanceof Error ? error.message : String(error);\n if (name === \"AbortError\" || name === \"TimeoutError\" || /^(fetch is aborted|signal timed out|signal is aborted without reason|the (user|operation) (aborted a request|was aborted)\\.?|this operation was aborted|the operation timed out\\.?)$/i.test(text.trim()))\n return host ? engineText(\"hostTimedOut\", { host }) : engineText(\"networkTimedOut\");\n if (/^(failed to fetch|load failed|fetch failed|networkerror when attempting to fetch resource\\.?|network request failed)$/i.test(text.trim()))\n return host ? engineText(\"hostUnreachable\", { host }) : engineText(\"networkUnreachable\");\n return null;\n}\n\n/** A request URL's host, for a reason that names it; the URL itself when it does not parse. */\nexport function rpcHost(url: string): string {\n try { return new URL(url).host; } catch { return url; }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"networkReason-Btv4b2C4.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/persistence.ts","../../../browser/src/engine/paymentAdapters/networkReason.ts"],"sourcesContent":["import { engineError, engineText } from \"@ghostly/core\";\nimport { STORES, openDb, store, transact, wrap } from \"../../shared/idb\";\nimport type { IntentRepository, SavedIntent } from \"./coordinator\";\n/**\n * A USDT payment is one transaction at one account nonce. Another payment from the same account and chain that is\n * submitted or of unknown outcome holds its nonce until it confirms. A review made after it was sent took the next\n * nonce and may go at once. One made before (or read from an RPC that had not seen it yet) has the same or a lower\n * nonce: sent, it would replace the earlier transaction or be dropped, so it is refused. A row with no nonce refuses.\n */\nfunction nonceTaken(review:SavedIntent[\"review\"],intents:SavedIntent[]):boolean {\n if(review.method!==\"usdt\")return false;\n const from=review.evm?.from?.toLowerCase(), nonce=review.evm?.nonce;\n return intents.some(({review:other})=>other.id!==review.id && other.method===\"usdt\" && other.chainId===review.chainId && other.evm?.from?.toLowerCase()===from && [\"submitted\",\"unknown\"].includes(other.state)\n && !(typeof nonce===\"number\" && typeof other.evm?.nonce===\"number\" && nonce>other.evm.nonce));\n}\nexport const intentRepository: IntentRepository = {\n async get(id) { return wrap<SavedIntent | undefined>((await store(STORES.intents,\"readonly\")).get(id)); },\n async list() { return wrap<SavedIntent[]>((await store(STORES.intents,\"readonly\")).getAll()); },\n async put(intent) { await transact([STORES.intents],s=>{s[STORES.intents].put(intent);}); },\n async claim(id) {\n const tx=(await openDb()).transaction(STORES.intents,\"readwrite\");\n return new Promise<SavedIntent>((resolve,reject)=>{\n let saved:SavedIntent;\n let reason=engineText(\"alreadySubmitted\");\n const request=tx.objectStore(STORES.intents).getAll();\n request.onsuccess=()=>{\n const intents:SavedIntent[]=request.result;\n saved=intents.find(item=>item.review.id===id)!;\n if(!saved || saved.review.state!==\"pending\") {tx.abort();return;}\n const duplicate=saved.review.requestId && intents.some(({review})=>review.id!==id && review.requestId===saved.review.requestId && review.linkId===saved.review.linkId && [\"submitted\",\"settled\",\"unknown\"].includes(review.state));\n if(duplicate){tx.abort();return;}\n if(nonceTaken(saved.review,intents)){reason=engineText(\"sentAfterReview\");tx.abort();return;}\n saved.review={...saved.review,state:\"submitted\",error:undefined,submittedAt:Date.now()};\n tx.objectStore(STORES.intents).put(saved);\n };\n tx.oncomplete=()=>resolve(saved);\n tx.onabort=tx.onerror=()=>reject(new Error(reason));\n });\n },\n async cancel(id) {\n const tx=(await openDb()).transaction(STORES.intents,\"readwrite\");\n return new Promise<SavedIntent>((resolve,reject)=>{\n let saved:SavedIntent;\n const request=tx.objectStore(STORES.intents).get(id);\n request.onsuccess=()=>{\n saved=request.result;\n if(!saved || saved.review.state!==\"pending\"){tx.abort();return;}\n saved.review={...saved.review,state:\"cancelled\"};\n tx.objectStore(STORES.intents).put(saved);\n };\n tx.oncomplete=()=>resolve(saved);\n tx.onabort=tx.onerror=()=>reject(engineError(\"cannotCancelSubmitted\"));\n });\n },\n};\n/** Key for a wallet that needs no password: its seed is protected like the Cashu proofs in the same database. */\nexport function newDeviceKey():string {return btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32)))).replace(/=+$/,\"\");}\nexport interface EncryptedSeed {version:1;salt:number[];iv:number[];ciphertext:number[]}\nasync function passwordKey(password:string,salt:Uint8Array<ArrayBuffer>) {\n const material=await crypto.subtle.importKey(\"raw\",new TextEncoder().encode(password),\"PBKDF2\",false,[\"deriveKey\"]);\n return crypto.subtle.deriveKey({name:\"PBKDF2\",hash:\"SHA-256\",salt,iterations:600000},material,{name:\"AES-GCM\",length:256},false,[\"encrypt\",\"decrypt\"]);\n}\nexport async function sealSeed(seed:string,password:string):Promise<EncryptedSeed> {\n if(password.length<12)throw new Error(\"Use at least 12 characters for the wallet password\");\n const salt=crypto.getRandomValues(new Uint8Array(16)),iv=crypto.getRandomValues(new Uint8Array(12));\n const ciphertext=await crypto.subtle.encrypt({name:\"AES-GCM\",iv},await passwordKey(password,salt),new TextEncoder().encode(seed));\n return {version:1,salt:[...salt],iv:[...iv],ciphertext:[...new Uint8Array(ciphertext)]};\n}\nexport async function unsealSeed(seed:EncryptedSeed,password:string):Promise<string> {\n if(seed.version!==1)throw new Error(\"Unsupported wallet backup version\");\n try {return new TextDecoder().decode(await crypto.subtle.decrypt({name:\"AES-GCM\",iv:new Uint8Array(seed.iv)},await passwordKey(password,new Uint8Array(seed.salt)),new Uint8Array(seed.ciphertext)));}\n catch {throw new Error(\"Could not unlock the wallet. Check the password and backup.\");}\n}\n","import { engineText } from \"@ghostly/core\";\n\n/**\n * A request's failure as a person says it, when the browser's own words say nothing: a request that timed out or was\n * given up (\"Fetch is aborted\" in Safari, \"signal timed out\" in Chromium) did not answer in time; one that never left\n * (\"Failed to fetch\", \"Load failed\") could not reach it. `host` names what was asked, when known. Anything else is\n * `null`: its own words are kept.\n */\nexport function networkReason(error: unknown, host?: string): string | null {\n const name = error instanceof Error ? error.name : \"\";\n const text = error instanceof Error ? error.message : String(error);\n if (name === \"AbortError\" || name === \"TimeoutError\" || /^(fetch is aborted|signal timed out|signal is aborted without reason|the (user|operation) (aborted a request|was aborted)\\.?|this operation was aborted|the operation timed out\\.?)$/i.test(text.trim()))\n return host ? engineText(\"hostTimedOut\", { host }) : engineText(\"networkTimedOut\");\n if (/^(failed to fetch|load failed|fetch failed|networkerror when attempting to fetch resource\\.?|network request failed)$/i.test(text.trim()))\n return host ? engineText(\"hostUnreachable\", { host }) : engineText(\"networkUnreachable\");\n return null;\n}\n\n/** A request URL's host, for a reason that names it; the URL itself when it does not parse. */\nexport function rpcHost(url: string): string {\n try { return new URL(url).host; } catch { return url; }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { In as decodeBolt11 } from "./src-BLzG4Sfv.js";
1
+ import { In as decodeBolt11 } from "./src-XhjSWnp-.js";
2
2
  import { t as NothingSpentError } from "./types-C4_KafL_.js";
3
- import { n as parseNwcUri } from "./nwcProvider-2coJAsqr.js";
3
+ import { n as parseNwcUri } from "./nwcProvider-C1AhPoFW.js";
4
4
  import { sha256 } from "@noble/hashes/sha2.js";
5
5
  import * as nip04 from "nostr-tools/nip04";
6
6
  import * as nip44 from "nostr-tools/nip44";
@@ -609,4 +609,4 @@ var NwcLightning = class NwcLightning {
609
609
  //#endregion
610
610
  export { NwcLightning };
611
611
 
612
- //# sourceMappingURL=nwc-0JYm8Vys.js.map
612
+ //# sourceMappingURL=nwc-z0pa5zql.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nwc-0JYm8Vys.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/providers/nwc.ts"],"sourcesContent":["import { decodeBolt11 } from \"@ghostly/core\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport * as nip04 from \"nostr-tools/nip04\";\nimport * as nip44 from \"nostr-tools/nip44\";\nimport { finalizeEvent, getPublicKey, verifyEvent, type Event } from \"nostr-tools/pure\";\nimport type { InvoiceStatus, LightningCapabilities, LightningInfo, LightningInvoice, LightningPayResult, LightningPaymentRef, LightningPaymentStatus, LightningProvider } from \"./lightning\";\nimport { parseNwcUri, type NwcConnection } from \"./nwcProvider\";\nimport { NothingSpentError, type ProviderNetwork } from \"./types\";\n\n/**\n * Lightning through a wallet reached over Nostr Wallet Connect (NIP-47): Alby Hub, a node's NWC service, a\n * hosted wallet. The person pastes the wallet's `nostr+walletconnect://` URI; requests are signed with the\n * key it carries, encrypted to the wallet (NIP-44, or NIP-04 when its info event offers nothing else) and\n * sent through its relay; the answers come back the same way. That wallet holds the sats, applies its own\n * fee limit, and is custodial or not depending on what it is.\n *\n * Money safety (PROVIDERS.md): a request that never reached the relay, or an error code the wallet answers\n * before it tries to pay, is `NothingSpentError`. A `pay_invoice` whose answer does not come back in time,\n * or any other error, is an unknown outcome, and `paymentStatus` asks `lookup_invoice` until it ends.\n */\n\nconst KIND = { info: 13194, request: 23194, response: 23195 } as const;\n/** A relay message, an encrypted answer, an info event, an invoice: nothing bigger is read. */\nconst MAX_MESSAGE = 256 * 1024;\nconst MAX_CONTENT = 64 * 1024;\nconst MAX_INFO = 4096;\nconst MAX_INVOICE = 7089;\nconst CONNECT_MS = 10_000;\nconst ACK_MS = 10_000;\nconst REQUEST_MS = 20_000;\n/** A payment may take a while to route; an answer after this is an unknown outcome, looked up later. */\nconst PAY_MS = 90_000;\n/** The wallet must not start a payment it receives after this (NIP-47 `expiration`). */\nconst PAY_EXPIRY_S = 60;\n/** A payment the wallet never heard of is failed once its invoice can no longer be paid, with room for clocks. */\nconst EXPIRED_MARGIN_MS = 10 * 60_000;\nconst INVOICE_EXPIRY_S = 3600;\n\n/** Error codes a wallet answers before it tries to pay: nothing can have left it. (`BAD_REQUEST`: Alby Hub, an invoice it cannot read.) */\nconst REFUSED_BEFORE_PAYING = new Set([\"RATE_LIMITED\", \"NOT_IMPLEMENTED\", \"INSUFFICIENT_BALANCE\", \"QUOTA_EXCEEDED\", \"RESTRICTED\", \"UNAUTHORIZED\", \"UNSUPPORTED_ENCRYPTION\", \"BAD_REQUEST\"]);\nconst NETWORKS: Record<string, ProviderNetwork> = { mainnet: \"bitcoin\", bitcoin: \"bitcoin\", testnet: \"testnet\", testnet3: \"testnet\", testnet4: \"testnet\", signet: \"signet\", mutinynet: \"mutinynet\", regtest: \"regtest\" };\n\nconst HEX64 = /^[0-9a-f]{64}$/;\nconst hex = (bytes: Uint8Array) => Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\nconst bytes = (text: string) => Uint8Array.from(text.match(/../g)!, (b) => parseInt(b, 16));\nconst now = () => Math.floor(Date.now() / 1000);\nconst isMsat = (value: unknown): value is number => Number.isSafeInteger(value) && (value as number) >= 0;\n\n// -- one relay -----------------------------------------------------------------------------------------\n\n/** The request never reached the relay (not connected, refused by it): the wallet cannot have seen it. */\nexport class NotDelivered extends Error {\n constructor(message: string) { super(message); this.name = \"NotDelivered\"; }\n}\n/** An error the wallet answered, with its NIP-47 code. */\nexport class NwcError extends Error {\n constructor(readonly code: string, message: string) { super(message); this.name = \"NwcError\"; }\n}\n/** No answer in time. The request may or may not have been acted on. */\nexport class NoAnswer extends Error {\n constructor(method: string) { super(`The wallet did not answer ${method} in time`); this.name = \"NoAnswer\"; }\n}\n\ninterface Filter { kinds: number[]; authors: string[]; \"#p\"?: string[]; since?: number; limit?: number }\ninterface Subscription { filter: Filter; event(event: unknown): void; eose?(): void }\n\n/**\n * A minimal NIP-01 client for one relay: it knows exactly whether an event was written to an open socket\n * and whether the relay acknowledged it, which is what tells \"nothing sent\" from \"unknown\" apart.\n * It reconnects when asked to send again, and subscriptions follow it.\n */\nexport class RelayConnection {\n private socket?: WebSocket;\n private opening?: Promise<WebSocket>;\n private readonly subs = new Map<string, Subscription>();\n private readonly acks = new Map<string, { ok(): void; fail(error: Error): void }>();\n private closed = false;\n\n constructor(readonly url: string, private readonly WebSocketImpl: typeof WebSocket = globalThis.WebSocket) {}\n\n open(): Promise<WebSocket> {\n if (this.closed) return Promise.reject(new Error(\"The wallet connection is closed\"));\n if (this.socket?.readyState === 1) return Promise.resolve(this.socket);\n if (!this.opening) {\n const opening = this.connectSocket();\n this.opening = opening;\n opening.catch(() => {}).finally(() => { if (this.opening === opening) this.opening = undefined; });\n }\n return this.opening;\n }\n\n private connectSocket(): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n let settled = false;\n const socket = new this.WebSocketImpl(this.url);\n const done = (error?: Error) => {\n if (settled) return;\n settled = true; clearTimeout(timer);\n if (error) { try { socket.close(); } catch { /* already closed */ } reject(error); return; }\n if (this.closed) { socket.close(); reject(new Error(\"The wallet connection is closed\")); return; }\n this.socket = socket;\n for (const [id, sub] of this.subs) this.write([\"REQ\", id, sub.filter]);\n resolve(socket);\n };\n const timer = setTimeout(() => done(new Error(\"The wallet's relay did not answer\")), CONNECT_MS);\n socket.onopen = () => done();\n socket.onerror = () => done(new Error(\"Could not reach the wallet's relay\"));\n socket.onclose = () => {\n done(new Error(\"The wallet's relay closed the connection\"));\n if (this.socket !== socket) return;\n this.socket = undefined;\n // Written, not acknowledged: whether the relay kept it is unknown.\n for (const [id, ack] of this.acks) { this.acks.delete(id); ack.fail(new Error(\"The relay connection dropped before it confirmed the request\")); }\n };\n socket.onmessage = (message) => { if (this.socket === socket) this.receive(message.data); };\n });\n }\n\n subscribe(id: string, filter: Filter, sub: Omit<Subscription, \"filter\">) {\n this.subs.set(id, { ...sub, filter });\n this.write([\"REQ\", id, filter]);\n }\n\n unsubscribe(id: string) {\n if (this.subs.delete(id)) this.write([\"CLOSE\", id]);\n }\n\n /**\n * Events matching `filter` the relay has stored, until it says that is all (or `ms` pass). With\n * `waitForOne`, a relay that has none yet is listened to until one arrives live, within `ms`.\n */\n async fetch(filter: Filter, { ms = CONNECT_MS, waitForOne = false }: { ms?: number; waitForOne?: boolean } = {}): Promise<unknown[]> {\n await this.open();\n const id = `q${hex(crypto.getRandomValues(new Uint8Array(6)))}`, events: unknown[] = [];\n try {\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, ms);\n let stored = false;\n const finish = () => { clearTimeout(timer); resolve(); };\n this.subscribe(id, filter, {\n event: (e) => { if (events.length < 20) events.push(e); if (stored) finish(); },\n eose: () => { stored = true; if (events.length || !waitForOne) finish(); },\n });\n });\n } finally { this.unsubscribe(id); }\n return events;\n }\n\n /**\n * Resolves once the relay accepted the event. `NotDelivered` when it certainly did not reach it (no open\n * socket, refused); any other rejection means it may have.\n */\n async publish(event: Event): Promise<void> {\n let socket: WebSocket;\n try { socket = await this.open(); } catch (error) { throw new NotDelivered(error instanceof Error ? error.message : \"Could not reach the wallet's relay\"); }\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => { this.acks.delete(event.id); reject(new Error(\"The relay did not confirm the request\")); }, ACK_MS);\n this.acks.set(event.id, { ok: () => { clearTimeout(timer); resolve(); }, fail: (error) => { clearTimeout(timer); reject(error); } });\n // A socket that is not open anymore drops what it is given without a word: nothing was sent.\n if (socket.readyState !== 1 || socket !== this.socket) { this.acks.delete(event.id); clearTimeout(timer); reject(new NotDelivered(\"The relay connection closed\")); return; }\n socket.send(JSON.stringify([\"EVENT\", event]));\n });\n }\n\n close() {\n this.closed = true;\n for (const [id, ack] of this.acks) { this.acks.delete(id); ack.fail(new Error(\"The wallet connection is closed\")); }\n this.subs.clear();\n try { this.socket?.close(); } catch { /* already closed */ }\n this.socket = undefined;\n }\n\n private write(message: unknown[]) {\n if (this.socket?.readyState === 1) this.socket.send(JSON.stringify(message));\n }\n\n private receive(data: unknown) {\n if (typeof data !== \"string\" || data.length > MAX_MESSAGE) return;\n let message: unknown;\n try { message = JSON.parse(data); } catch { return; }\n if (!Array.isArray(message) || typeof message[1] !== \"string\") return;\n const [type, id] = message as [string, string];\n if (type === \"EVENT\") this.subs.get(id)?.event(message[2]);\n else if (type === \"EOSE\") this.subs.get(id)?.eose?.();\n else if (type === \"OK\") {\n const ack = this.acks.get(id);\n if (!ack) return;\n this.acks.delete(id);\n const reason = typeof message[3] === \"string\" ? message[3].slice(0, 120) : \"\";\n // \"duplicate:\" is a relay saying it already has it: delivered.\n if (message[2] === true || reason.startsWith(\"duplicate:\")) ack.ok();\n else ack.fail(new NotDelivered(`The relay refused the request${reason ? ` (${reason})` : \"\"}`));\n }\n }\n}\n\n// -- the wallet ----------------------------------------------------------------------------------------\n\n/** What `lookup_invoice` (and `make_invoice`) answer, as far as it is read. Amounts in millisats. */\ninterface NwcTransaction {\n type?: string;\n state?: string;\n invoice?: string;\n payment_hash?: string;\n preimage?: string;\n amount?: number;\n fees_paid?: number;\n settled_at?: number | null;\n expires_at?: number | null;\n}\n\nexport interface NwcOptions {\n signal?: AbortSignal;\n /** For tests: time limits, and a WebSocket other than the global one. */\n requestMs?: number;\n /** How long to wait for the wallet's info event (a new app connection publishes it a moment later). */\n infoMs?: number;\n payMs?: number;\n WebSocket?: typeof WebSocket;\n}\n\ninterface Pending { method: string; resolve(result: Record<string, unknown>): void; reject(error: Error): void; timer: ReturnType<typeof setTimeout> }\n\nexport class NwcLightning implements LightningProvider {\n /** From the info event, then narrowed to what this connection may do (`get_info`). */\n capabilities: LightningCapabilities;\n private readonly clientPubkey: string;\n private readonly subscription = `nwc${hex(crypto.getRandomValues(new Uint8Array(6)))}`;\n private readonly pending = new Map<string, Pending>();\n private conversationKey?: Uint8Array;\n private network: ProviderNetwork = \"bitcoin\";\n private alias?: string;\n private closed = false;\n\n private constructor(private readonly connection: NwcConnection, private readonly relay: RelayConnection, readonly encryption: \"nip44_v2\" | \"nip04\", methods: ReadonlySet<string>, private readonly options: NwcOptions) {\n this.clientPubkey = getPublicKey(connection.secret);\n if (encryption === \"nip44_v2\") this.conversationKey = nip44.v2.utils.getConversationKey(connection.secret, connection.walletPubkey);\n this.capabilities = this.capabilitiesOf(methods);\n }\n\n /**\n * Reaches the wallet through the first relay that answers, reads its info event (the methods and the\n * encryption it offers), listens for its answers, and asks `get_info` for its network.\n */\n static async connect(uri: string, options: NwcOptions = {}): Promise<NwcLightning> {\n const connection = parseNwcUri(uri);\n options.signal?.throwIfAborted();\n let relay: RelayConnection | undefined, lastError: unknown;\n for (const url of connection.relays) {\n const candidate = new RelayConnection(url, options.WebSocket);\n try { await candidate.open(); relay = candidate; break; } catch (error) { candidate.close(); lastError = error; }\n }\n if (!relay) throw lastError instanceof Error ? lastError : new Error(\"Could not reach the wallet's relay\");\n let wallet: NwcLightning | undefined;\n try {\n const info = NwcLightning.newestInfo(await relay.fetch({ kinds: [KIND.info], authors: [connection.walletPubkey], limit: 5 }, { waitForOne: true, ms: options.infoMs }), connection.walletPubkey);\n if (!info) throw new Error(`The wallet has not published its NWC info on ${new URL(relay.url).host}: check the URI, or that the wallet is running`);\n const offered = (info.tags.find((t) => t[0] === \"encryption\")?.slice(1).join(\" \") ?? \"\").split(/\\s+/).filter(Boolean);\n // NIP-47: no `encryption` tag means a wallet that only speaks NIP-04.\n const encryption = offered.includes(\"nip44_v2\") ? \"nip44_v2\" : !offered.length || offered.includes(\"nip04\") ? \"nip04\" : undefined;\n if (!encryption) throw new Error(\"The wallet offers no encryption Ghostly speaks (NIP-44 or NIP-04)\");\n const methods = new Set(info.content.split(/\\s+/).filter(Boolean));\n wallet = new NwcLightning(connection, relay, encryption, methods, options);\n wallet.listen();\n if (options.signal) {\n const opened = wallet;\n if (options.signal.aborted) throw options.signal.reason;\n options.signal.addEventListener(\"abort\", () => void opened.close(), { once: true });\n }\n await wallet.readInfo(methods);\n return wallet;\n } catch (error) {\n if (wallet) await wallet.close(); else relay.close();\n throw error;\n }\n }\n\n private static newestInfo(events: unknown[], walletPubkey: string): Event | undefined {\n return (events as Event[])\n .filter((e) => e && e.kind === KIND.info && e.pubkey === walletPubkey && typeof e.content === \"string\" && e.content.length <= MAX_INFO && Array.isArray(e.tags) && verifyEvent(e))\n .sort((a, b) => b.created_at - a.created_at)[0];\n }\n\n private capabilitiesOf(methods: ReadonlySet<string>): LightningCapabilities {\n const lookup = methods.has(\"lookup_invoice\");\n // Paying needs looking up: a payment whose answer is lost could never be settled, and would hold the source.\n return { receive: methods.has(\"make_invoice\"), send: methods.has(\"pay_invoice\") && lookup, balance: methods.has(\"get_balance\"), lookup };\n }\n\n /**\n * `get_info` says the network and the methods this connection may use (the info event lists the\n * service's). Without it the wallet is taken to be on Bitcoin: a test wallet is then refused in the\n * Testnet mode and its invoices in the Mainnet one, while a real-money wallet never passes for a test one.\n */\n private async readInfo(offered: ReadonlySet<string>) {\n if (!offered.has(\"get_info\")) return;\n let info: Record<string, unknown>;\n try { info = await this.request(\"get_info\", {}); }\n catch (error) {\n // The service has it, this connection may not use it: the same as a wallet without it.\n if (error instanceof NwcError && [\"RESTRICTED\", \"UNAUTHORIZED\", \"NOT_IMPLEMENTED\"].includes(error.code)) return;\n throw error;\n }\n if (info.network !== undefined) {\n const network = typeof info.network === \"string\" ? NETWORKS[info.network.toLowerCase()] : undefined;\n if (!network) throw new Error(\"The wallet is on a network Ghostly does not know\");\n this.network = network;\n }\n if (typeof info.alias === \"string\" && info.alias.trim()) this.alias = info.alias.trim().slice(0, 40);\n if (Array.isArray(info.methods) && info.methods.every((m) => typeof m === \"string\")) {\n this.capabilities = this.capabilitiesOf(new Set(info.methods as string[]));\n }\n }\n\n private listen() {\n this.relay.subscribe(this.subscription, { kinds: [KIND.response], authors: [this.connection.walletPubkey], \"#p\": [this.clientPubkey], since: now() - 60 }, { event: (e) => this.answer(e) });\n }\n\n // -- requests and answers --\n\n private encrypt(text: string) {\n return this.conversationKey ? nip44.v2.encrypt(text, this.conversationKey) : nip04.encrypt(this.connection.secret, this.connection.walletPubkey, text);\n }\n\n private decrypt(content: string) {\n if (this.conversationKey && !content.includes(\"?iv=\")) return nip44.v2.decrypt(content, this.conversationKey);\n return nip04.decrypt(this.connection.secret, this.connection.walletPubkey, content);\n }\n\n /**\n * Sends one request and waits for its answer. `NotDelivered` when it never reached the relay; `NwcError`\n * for an error the wallet answered; `NoAnswer` (or a relay error) when the outcome is unknown.\n */\n async request(method: string, params: Record<string, unknown>, { ms = this.options.requestMs ?? REQUEST_MS, expiresIn }: { ms?: number; expiresIn?: number } = {}): Promise<Record<string, unknown>> {\n if (this.closed) throw new NotDelivered(\"The wallet connection is closed\");\n const tags = [[\"p\", this.connection.walletPubkey]];\n if (this.conversationKey) tags.push([\"encryption\", \"nip44_v2\"]);\n if (expiresIn) tags.push([\"expiration\", String(now() + expiresIn)]);\n const event = finalizeEvent({ kind: KIND.request, created_at: now(), tags, content: this.encrypt(JSON.stringify({ method, params })) }, this.connection.secret);\n const answer = new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => { this.pending.delete(event.id); reject(new NoAnswer(method)); }, ms);\n this.pending.set(event.id, { method, resolve, reject, timer });\n });\n // The answer can come before the relay's acknowledgement (or without one): whichever decides first wins.\n const delivered = this.relay.publish(event).then(() => undefined, (error: unknown) => {\n const waiting = this.pending.get(event.id);\n if (!(error instanceof NotDelivered) || !waiting) return undefined;\n clearTimeout(waiting.timer); this.pending.delete(event.id);\n return error;\n });\n return Promise.race([answer, delivered.then((error) => (error ? Promise.reject(error) : answer))]);\n }\n\n /** Reads an answer: from the wallet, signed, about a request of ours, of the method asked. Anything else is dropped. */\n private answer(raw: unknown) {\n const event = raw as Event;\n if (!event || typeof event !== \"object\" || event.kind !== KIND.response || event.pubkey !== this.connection.walletPubkey) return;\n if (typeof event.content !== \"string\" || event.content.length > MAX_CONTENT || !Array.isArray(event.tags)) return;\n const ref = event.tags.find((t) => Array.isArray(t) && t[0] === \"e\")?.[1];\n const pending = typeof ref === \"string\" ? this.pending.get(ref) : undefined;\n if (!pending || !event.tags.some((t) => Array.isArray(t) && t[0] === \"p\" && t[1] === this.clientPubkey)) return;\n if (!verifyEvent(event)) return;\n let body: { result_type?: unknown; error?: { code?: unknown; message?: unknown } | null; result?: unknown };\n try { body = JSON.parse(this.decrypt(event.content)); } catch { return; }\n if (!body || typeof body !== \"object\" || body.result_type !== pending.method) return;\n clearTimeout(pending.timer);\n this.pending.delete(ref!);\n if (body.error) {\n const code = typeof body.error.code === \"string\" ? body.error.code.slice(0, 40) : \"OTHER\";\n const message = typeof body.error.message === \"string\" && body.error.message.trim() ? body.error.message.trim().slice(0, 200) : code;\n pending.reject(new NwcError(code, message));\n } else if (body.result && typeof body.result === \"object\" && !Array.isArray(body.result)) pending.resolve(body.result as Record<string, unknown>);\n else pending.reject(new NwcError(\"OTHER\", \"The wallet sent an empty answer\"));\n }\n\n private async lookup(paymentHash: string): Promise<NwcTransaction> {\n const tx = await this.request(\"lookup_invoice\", { payment_hash: paymentHash }) as NwcTransaction;\n if (tx.payment_hash !== undefined && String(tx.payment_hash).toLowerCase() !== paymentHash) throw new Error(\"The wallet answered about another invoice\");\n return tx;\n }\n\n // -- LightningProvider --\n\n async info(): Promise<LightningInfo> {\n let balance: number | undefined;\n if (this.capabilities.balance) {\n const result = await this.request(\"get_balance\", {});\n if (!isMsat(result.balance)) throw new Error(\"The wallet returned an invalid balance\");\n balance = Math.floor(result.balance / 1000);\n }\n return { network: this.network, alias: `${this.alias ?? \"NWC wallet\"} via ${new URL(this.relay.url).host}`, balance };\n }\n\n async createInvoice(amount: number, memo?: string): Promise<LightningInvoice> {\n if (!Number.isSafeInteger(amount) || amount <= 0 || !Number.isSafeInteger(amount * 1000)) throw new Error(\"Invalid amount\");\n const result = await this.request(\"make_invoice\", { amount: amount * 1000, ...(memo ? { description: memo.slice(0, 200) } : {}), expiry: INVOICE_EXPIRY_S }) as NwcTransaction;\n const text = typeof result.invoice === \"string\" && result.invoice.length <= MAX_INVOICE ? result.invoice : \"\";\n const decoded = decodeBolt11(text);\n if (!decoded?.paymentHash || decoded.amountMsat !== BigInt(amount) * 1000n) throw new Error(\"The wallet returned an invoice that does not match the request\");\n if (result.payment_hash !== undefined && String(result.payment_hash).toLowerCase() !== decoded.paymentHash) throw new Error(\"The wallet returned an invoice that does not match its payment hash\");\n return { invoice: decoded.invoice, paymentHash: decoded.paymentHash, amount, expiresAt: decoded.expiresAt * 1000 };\n }\n\n async invoiceStatus(invoice: LightningInvoice): Promise<InvoiceStatus> {\n let tx: NwcTransaction;\n try { tx = await this.lookup(invoice.paymentHash); }\n catch (error) {\n if (error instanceof NwcError && error.code === \"NOT_FOUND\" && invoice.expiresAt < Date.now()) return { state: \"expired\" };\n throw error;\n }\n const expired = invoice.expiresAt < Date.now();\n if (tx.type === \"outgoing\") return { state: expired ? \"expired\" : \"open\" };\n // An incoming invoice's preimage is known before it is paid: only `state` or `settled_at` say it was.\n const state = tx.state ?? (tx.settled_at ? \"settled\" : \"pending\");\n if (state === \"settled\") return { state: \"paid\", amount: isMsat(tx.amount) ? Math.floor(tx.amount / 1000) : invoice.amount };\n if (state === \"expired\" || state === \"failed\") return { state: \"expired\" };\n return { state: expired ? \"expired\" : \"open\" };\n }\n\n /**\n * Pays through the wallet. NIP-47 carries no fee limit: the wallet applies its own, and the fee it\n * reports is passed on as it is.\n */\n async payInvoice(invoice: string, _maxFee: number): Promise<LightningPayResult> {\n const decoded = decodeBolt11(invoice);\n if (!decoded?.paymentHash || decoded.amountSat === null) throw new NothingSpentError(\"That invoice cannot be paid through NWC\");\n if (!this.capabilities.send) throw new NothingSpentError(\"This wallet connection may not pay and look up invoices\");\n let result: Record<string, unknown>;\n try {\n result = await this.request(\"pay_invoice\", { invoice: decoded.invoice }, { ms: this.options.payMs ?? PAY_MS, expiresIn: PAY_EXPIRY_S });\n } catch (error) {\n if (error instanceof NotDelivered) throw new NothingSpentError(`The payment did not reach the wallet: ${error.message}`);\n if (error instanceof NwcError && REFUSED_BEFORE_PAYING.has(error.code)) throw new NothingSpentError(`The wallet refused the payment: ${error.message}`);\n // Any other code may come after the wallet tried (Alby Hub answers INTERNAL with LND's failure reason).\n if (error instanceof NwcError) return this.confirmFailure(decoded.invoice, decoded.paymentHash, error);\n throw error;\n }\n const preimage = typeof result.preimage === \"string\" ? result.preimage.toLowerCase() : \"\";\n // \"Paid\" without a proof that pays this invoice is not taken at its word: it is looked up instead.\n if (!HEX64.test(preimage) || hex(sha256(bytes(preimage))) !== decoded.paymentHash) throw new Error(\"The wallet said it paid, without a proof that matches the invoice\");\n return { state: \"paid\", preimage, fee: isMsat(result.fees_paid) ? Math.ceil(result.fees_paid / 1000) : undefined };\n }\n\n /**\n * An error after the wallet may have tried (`PAYMENT_FAILED` \"may be due to a timeout\", `INTERNAL`,\n * `OTHER`…): its own record decides. Only a payment it records as failed is `NothingSpentError`; one it\n * records as paid is paid; anything else is pending, or unknown when it cannot be asked.\n */\n private async confirmFailure(invoice: string, paymentHash: string, failure: NwcError): Promise<LightningPayResult> {\n let status: LightningPaymentStatus;\n try { status = await this.paymentStatus({ invoice, paymentHash }); }\n catch { throw new Error(`The wallet said the payment failed (${failure.message}), and cannot confirm it yet`); }\n if (status.state === \"failed\") throw new NothingSpentError(`The payment failed: ${failure.message}`);\n return status.state === \"paid\" ? { state: \"paid\", fee: status.fee, preimage: status.preimage } : { state: \"pending\" };\n }\n\n async paymentStatus(payment: LightningPaymentRef): Promise<LightningPaymentStatus> {\n let tx: NwcTransaction;\n try { tx = await this.lookup(payment.paymentHash); }\n catch (error) {\n if (!(error instanceof NwcError && error.code === \"NOT_FOUND\")) throw error;\n // The wallet never heard of it: failed once nobody can pay that invoice anymore, until then it may still start.\n const expiresAt = (decodeBolt11(payment.invoice)?.expiresAt ?? Infinity) * 1000;\n return { state: expiresAt + EXPIRED_MARGIN_MS < Date.now() ? \"failed\" : \"pending\" };\n }\n // Our own invoice (a wallet paying itself): not an answer about the payment.\n if (tx.type === \"incoming\") return { state: \"pending\" };\n const preimage = typeof tx.preimage === \"string\" && HEX64.test(tx.preimage.toLowerCase()) ? tx.preimage.toLowerCase() : undefined;\n const proven = !!preimage && hex(sha256(bytes(preimage))) === payment.paymentHash;\n const state = tx.state ?? (tx.settled_at || proven ? \"settled\" : \"pending\");\n const fee = isMsat(tx.fees_paid) ? Math.ceil(tx.fees_paid / 1000) : undefined;\n if (state === \"settled\") {\n if (preimage && !proven) throw new Error(\"The wallet's proof of payment does not match the invoice\");\n return { state: \"paid\", fee, preimage };\n }\n if (state === \"failed\" || state === \"expired\") return { state: \"failed\" };\n return { state: \"pending\" };\n }\n\n async close() {\n if (this.closed) return;\n this.closed = true;\n for (const [id, pending] of this.pending) { clearTimeout(pending.timer); this.pending.delete(id); pending.reject(new Error(\"The wallet connection is closed\")); }\n this.relay.close();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nwc-z0pa5zql.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/providers/nwc.ts"],"sourcesContent":["import { decodeBolt11 } from \"@ghostly/core\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport * as nip04 from \"nostr-tools/nip04\";\nimport * as nip44 from \"nostr-tools/nip44\";\nimport { finalizeEvent, getPublicKey, verifyEvent, type Event } from \"nostr-tools/pure\";\nimport type { InvoiceStatus, LightningCapabilities, LightningInfo, LightningInvoice, LightningPayResult, LightningPaymentRef, LightningPaymentStatus, LightningProvider } from \"./lightning\";\nimport { parseNwcUri, type NwcConnection } from \"./nwcProvider\";\nimport { NothingSpentError, type ProviderNetwork } from \"./types\";\n\n/**\n * Lightning through a wallet reached over Nostr Wallet Connect (NIP-47): Alby Hub, a node's NWC service, a\n * hosted wallet. The person pastes the wallet's `nostr+walletconnect://` URI; requests are signed with the\n * key it carries, encrypted to the wallet (NIP-44, or NIP-04 when its info event offers nothing else) and\n * sent through its relay; the answers come back the same way. That wallet holds the sats, applies its own\n * fee limit, and is custodial or not depending on what it is.\n *\n * Money safety (PROVIDERS.md): a request that never reached the relay, or an error code the wallet answers\n * before it tries to pay, is `NothingSpentError`. A `pay_invoice` whose answer does not come back in time,\n * or any other error, is an unknown outcome, and `paymentStatus` asks `lookup_invoice` until it ends.\n */\n\nconst KIND = { info: 13194, request: 23194, response: 23195 } as const;\n/** A relay message, an encrypted answer, an info event, an invoice: nothing bigger is read. */\nconst MAX_MESSAGE = 256 * 1024;\nconst MAX_CONTENT = 64 * 1024;\nconst MAX_INFO = 4096;\nconst MAX_INVOICE = 7089;\nconst CONNECT_MS = 10_000;\nconst ACK_MS = 10_000;\nconst REQUEST_MS = 20_000;\n/** A payment may take a while to route; an answer after this is an unknown outcome, looked up later. */\nconst PAY_MS = 90_000;\n/** The wallet must not start a payment it receives after this (NIP-47 `expiration`). */\nconst PAY_EXPIRY_S = 60;\n/** A payment the wallet never heard of is failed once its invoice can no longer be paid, with room for clocks. */\nconst EXPIRED_MARGIN_MS = 10 * 60_000;\nconst INVOICE_EXPIRY_S = 3600;\n\n/** Error codes a wallet answers before it tries to pay: nothing can have left it. (`BAD_REQUEST`: Alby Hub, an invoice it cannot read.) */\nconst REFUSED_BEFORE_PAYING = new Set([\"RATE_LIMITED\", \"NOT_IMPLEMENTED\", \"INSUFFICIENT_BALANCE\", \"QUOTA_EXCEEDED\", \"RESTRICTED\", \"UNAUTHORIZED\", \"UNSUPPORTED_ENCRYPTION\", \"BAD_REQUEST\"]);\nconst NETWORKS: Record<string, ProviderNetwork> = { mainnet: \"bitcoin\", bitcoin: \"bitcoin\", testnet: \"testnet\", testnet3: \"testnet\", testnet4: \"testnet\", signet: \"signet\", mutinynet: \"mutinynet\", regtest: \"regtest\" };\n\nconst HEX64 = /^[0-9a-f]{64}$/;\nconst hex = (bytes: Uint8Array) => Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\nconst bytes = (text: string) => Uint8Array.from(text.match(/../g)!, (b) => parseInt(b, 16));\nconst now = () => Math.floor(Date.now() / 1000);\nconst isMsat = (value: unknown): value is number => Number.isSafeInteger(value) && (value as number) >= 0;\n\n// -- one relay -----------------------------------------------------------------------------------------\n\n/** The request never reached the relay (not connected, refused by it): the wallet cannot have seen it. */\nexport class NotDelivered extends Error {\n constructor(message: string) { super(message); this.name = \"NotDelivered\"; }\n}\n/** An error the wallet answered, with its NIP-47 code. */\nexport class NwcError extends Error {\n constructor(readonly code: string, message: string) { super(message); this.name = \"NwcError\"; }\n}\n/** No answer in time. The request may or may not have been acted on. */\nexport class NoAnswer extends Error {\n constructor(method: string) { super(`The wallet did not answer ${method} in time`); this.name = \"NoAnswer\"; }\n}\n\ninterface Filter { kinds: number[]; authors: string[]; \"#p\"?: string[]; since?: number; limit?: number }\ninterface Subscription { filter: Filter; event(event: unknown): void; eose?(): void }\n\n/**\n * A minimal NIP-01 client for one relay: it knows exactly whether an event was written to an open socket\n * and whether the relay acknowledged it, which is what tells \"nothing sent\" from \"unknown\" apart.\n * It reconnects when asked to send again, and subscriptions follow it.\n */\nexport class RelayConnection {\n private socket?: WebSocket;\n private opening?: Promise<WebSocket>;\n private readonly subs = new Map<string, Subscription>();\n private readonly acks = new Map<string, { ok(): void; fail(error: Error): void }>();\n private closed = false;\n\n constructor(readonly url: string, private readonly WebSocketImpl: typeof WebSocket = globalThis.WebSocket) {}\n\n open(): Promise<WebSocket> {\n if (this.closed) return Promise.reject(new Error(\"The wallet connection is closed\"));\n if (this.socket?.readyState === 1) return Promise.resolve(this.socket);\n if (!this.opening) {\n const opening = this.connectSocket();\n this.opening = opening;\n opening.catch(() => {}).finally(() => { if (this.opening === opening) this.opening = undefined; });\n }\n return this.opening;\n }\n\n private connectSocket(): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n let settled = false;\n const socket = new this.WebSocketImpl(this.url);\n const done = (error?: Error) => {\n if (settled) return;\n settled = true; clearTimeout(timer);\n if (error) { try { socket.close(); } catch { /* already closed */ } reject(error); return; }\n if (this.closed) { socket.close(); reject(new Error(\"The wallet connection is closed\")); return; }\n this.socket = socket;\n for (const [id, sub] of this.subs) this.write([\"REQ\", id, sub.filter]);\n resolve(socket);\n };\n const timer = setTimeout(() => done(new Error(\"The wallet's relay did not answer\")), CONNECT_MS);\n socket.onopen = () => done();\n socket.onerror = () => done(new Error(\"Could not reach the wallet's relay\"));\n socket.onclose = () => {\n done(new Error(\"The wallet's relay closed the connection\"));\n if (this.socket !== socket) return;\n this.socket = undefined;\n // Written, not acknowledged: whether the relay kept it is unknown.\n for (const [id, ack] of this.acks) { this.acks.delete(id); ack.fail(new Error(\"The relay connection dropped before it confirmed the request\")); }\n };\n socket.onmessage = (message) => { if (this.socket === socket) this.receive(message.data); };\n });\n }\n\n subscribe(id: string, filter: Filter, sub: Omit<Subscription, \"filter\">) {\n this.subs.set(id, { ...sub, filter });\n this.write([\"REQ\", id, filter]);\n }\n\n unsubscribe(id: string) {\n if (this.subs.delete(id)) this.write([\"CLOSE\", id]);\n }\n\n /**\n * Events matching `filter` the relay has stored, until it says that is all (or `ms` pass). With\n * `waitForOne`, a relay that has none yet is listened to until one arrives live, within `ms`.\n */\n async fetch(filter: Filter, { ms = CONNECT_MS, waitForOne = false }: { ms?: number; waitForOne?: boolean } = {}): Promise<unknown[]> {\n await this.open();\n const id = `q${hex(crypto.getRandomValues(new Uint8Array(6)))}`, events: unknown[] = [];\n try {\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, ms);\n let stored = false;\n const finish = () => { clearTimeout(timer); resolve(); };\n this.subscribe(id, filter, {\n event: (e) => { if (events.length < 20) events.push(e); if (stored) finish(); },\n eose: () => { stored = true; if (events.length || !waitForOne) finish(); },\n });\n });\n } finally { this.unsubscribe(id); }\n return events;\n }\n\n /**\n * Resolves once the relay accepted the event. `NotDelivered` when it certainly did not reach it (no open\n * socket, refused); any other rejection means it may have.\n */\n async publish(event: Event): Promise<void> {\n let socket: WebSocket;\n try { socket = await this.open(); } catch (error) { throw new NotDelivered(error instanceof Error ? error.message : \"Could not reach the wallet's relay\"); }\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => { this.acks.delete(event.id); reject(new Error(\"The relay did not confirm the request\")); }, ACK_MS);\n this.acks.set(event.id, { ok: () => { clearTimeout(timer); resolve(); }, fail: (error) => { clearTimeout(timer); reject(error); } });\n // A socket that is not open anymore drops what it is given without a word: nothing was sent.\n if (socket.readyState !== 1 || socket !== this.socket) { this.acks.delete(event.id); clearTimeout(timer); reject(new NotDelivered(\"The relay connection closed\")); return; }\n socket.send(JSON.stringify([\"EVENT\", event]));\n });\n }\n\n close() {\n this.closed = true;\n for (const [id, ack] of this.acks) { this.acks.delete(id); ack.fail(new Error(\"The wallet connection is closed\")); }\n this.subs.clear();\n try { this.socket?.close(); } catch { /* already closed */ }\n this.socket = undefined;\n }\n\n private write(message: unknown[]) {\n if (this.socket?.readyState === 1) this.socket.send(JSON.stringify(message));\n }\n\n private receive(data: unknown) {\n if (typeof data !== \"string\" || data.length > MAX_MESSAGE) return;\n let message: unknown;\n try { message = JSON.parse(data); } catch { return; }\n if (!Array.isArray(message) || typeof message[1] !== \"string\") return;\n const [type, id] = message as [string, string];\n if (type === \"EVENT\") this.subs.get(id)?.event(message[2]);\n else if (type === \"EOSE\") this.subs.get(id)?.eose?.();\n else if (type === \"OK\") {\n const ack = this.acks.get(id);\n if (!ack) return;\n this.acks.delete(id);\n const reason = typeof message[3] === \"string\" ? message[3].slice(0, 120) : \"\";\n // \"duplicate:\" is a relay saying it already has it: delivered.\n if (message[2] === true || reason.startsWith(\"duplicate:\")) ack.ok();\n else ack.fail(new NotDelivered(`The relay refused the request${reason ? ` (${reason})` : \"\"}`));\n }\n }\n}\n\n// -- the wallet ----------------------------------------------------------------------------------------\n\n/** What `lookup_invoice` (and `make_invoice`) answer, as far as it is read. Amounts in millisats. */\ninterface NwcTransaction {\n type?: string;\n state?: string;\n invoice?: string;\n payment_hash?: string;\n preimage?: string;\n amount?: number;\n fees_paid?: number;\n settled_at?: number | null;\n expires_at?: number | null;\n}\n\nexport interface NwcOptions {\n signal?: AbortSignal;\n /** For tests: time limits, and a WebSocket other than the global one. */\n requestMs?: number;\n /** How long to wait for the wallet's info event (a new app connection publishes it a moment later). */\n infoMs?: number;\n payMs?: number;\n WebSocket?: typeof WebSocket;\n}\n\ninterface Pending { method: string; resolve(result: Record<string, unknown>): void; reject(error: Error): void; timer: ReturnType<typeof setTimeout> }\n\nexport class NwcLightning implements LightningProvider {\n /** From the info event, then narrowed to what this connection may do (`get_info`). */\n capabilities: LightningCapabilities;\n private readonly clientPubkey: string;\n private readonly subscription = `nwc${hex(crypto.getRandomValues(new Uint8Array(6)))}`;\n private readonly pending = new Map<string, Pending>();\n private conversationKey?: Uint8Array;\n private network: ProviderNetwork = \"bitcoin\";\n private alias?: string;\n private closed = false;\n\n private constructor(private readonly connection: NwcConnection, private readonly relay: RelayConnection, readonly encryption: \"nip44_v2\" | \"nip04\", methods: ReadonlySet<string>, private readonly options: NwcOptions) {\n this.clientPubkey = getPublicKey(connection.secret);\n if (encryption === \"nip44_v2\") this.conversationKey = nip44.v2.utils.getConversationKey(connection.secret, connection.walletPubkey);\n this.capabilities = this.capabilitiesOf(methods);\n }\n\n /**\n * Reaches the wallet through the first relay that answers, reads its info event (the methods and the\n * encryption it offers), listens for its answers, and asks `get_info` for its network.\n */\n static async connect(uri: string, options: NwcOptions = {}): Promise<NwcLightning> {\n const connection = parseNwcUri(uri);\n options.signal?.throwIfAborted();\n let relay: RelayConnection | undefined, lastError: unknown;\n for (const url of connection.relays) {\n const candidate = new RelayConnection(url, options.WebSocket);\n try { await candidate.open(); relay = candidate; break; } catch (error) { candidate.close(); lastError = error; }\n }\n if (!relay) throw lastError instanceof Error ? lastError : new Error(\"Could not reach the wallet's relay\");\n let wallet: NwcLightning | undefined;\n try {\n const info = NwcLightning.newestInfo(await relay.fetch({ kinds: [KIND.info], authors: [connection.walletPubkey], limit: 5 }, { waitForOne: true, ms: options.infoMs }), connection.walletPubkey);\n if (!info) throw new Error(`The wallet has not published its NWC info on ${new URL(relay.url).host}: check the URI, or that the wallet is running`);\n const offered = (info.tags.find((t) => t[0] === \"encryption\")?.slice(1).join(\" \") ?? \"\").split(/\\s+/).filter(Boolean);\n // NIP-47: no `encryption` tag means a wallet that only speaks NIP-04.\n const encryption = offered.includes(\"nip44_v2\") ? \"nip44_v2\" : !offered.length || offered.includes(\"nip04\") ? \"nip04\" : undefined;\n if (!encryption) throw new Error(\"The wallet offers no encryption Ghostly speaks (NIP-44 or NIP-04)\");\n const methods = new Set(info.content.split(/\\s+/).filter(Boolean));\n wallet = new NwcLightning(connection, relay, encryption, methods, options);\n wallet.listen();\n if (options.signal) {\n const opened = wallet;\n if (options.signal.aborted) throw options.signal.reason;\n options.signal.addEventListener(\"abort\", () => void opened.close(), { once: true });\n }\n await wallet.readInfo(methods);\n return wallet;\n } catch (error) {\n if (wallet) await wallet.close(); else relay.close();\n throw error;\n }\n }\n\n private static newestInfo(events: unknown[], walletPubkey: string): Event | undefined {\n return (events as Event[])\n .filter((e) => e && e.kind === KIND.info && e.pubkey === walletPubkey && typeof e.content === \"string\" && e.content.length <= MAX_INFO && Array.isArray(e.tags) && verifyEvent(e))\n .sort((a, b) => b.created_at - a.created_at)[0];\n }\n\n private capabilitiesOf(methods: ReadonlySet<string>): LightningCapabilities {\n const lookup = methods.has(\"lookup_invoice\");\n // Paying needs looking up: a payment whose answer is lost could never be settled, and would hold the source.\n return { receive: methods.has(\"make_invoice\"), send: methods.has(\"pay_invoice\") && lookup, balance: methods.has(\"get_balance\"), lookup };\n }\n\n /**\n * `get_info` says the network and the methods this connection may use (the info event lists the\n * service's). Without it the wallet is taken to be on Bitcoin: a test wallet is then refused in the\n * Testnet mode and its invoices in the Mainnet one, while a real-money wallet never passes for a test one.\n */\n private async readInfo(offered: ReadonlySet<string>) {\n if (!offered.has(\"get_info\")) return;\n let info: Record<string, unknown>;\n try { info = await this.request(\"get_info\", {}); }\n catch (error) {\n // The service has it, this connection may not use it: the same as a wallet without it.\n if (error instanceof NwcError && [\"RESTRICTED\", \"UNAUTHORIZED\", \"NOT_IMPLEMENTED\"].includes(error.code)) return;\n throw error;\n }\n if (info.network !== undefined) {\n const network = typeof info.network === \"string\" ? NETWORKS[info.network.toLowerCase()] : undefined;\n if (!network) throw new Error(\"The wallet is on a network Ghostly does not know\");\n this.network = network;\n }\n if (typeof info.alias === \"string\" && info.alias.trim()) this.alias = info.alias.trim().slice(0, 40);\n if (Array.isArray(info.methods) && info.methods.every((m) => typeof m === \"string\")) {\n this.capabilities = this.capabilitiesOf(new Set(info.methods as string[]));\n }\n }\n\n private listen() {\n this.relay.subscribe(this.subscription, { kinds: [KIND.response], authors: [this.connection.walletPubkey], \"#p\": [this.clientPubkey], since: now() - 60 }, { event: (e) => this.answer(e) });\n }\n\n // -- requests and answers --\n\n private encrypt(text: string) {\n return this.conversationKey ? nip44.v2.encrypt(text, this.conversationKey) : nip04.encrypt(this.connection.secret, this.connection.walletPubkey, text);\n }\n\n private decrypt(content: string) {\n if (this.conversationKey && !content.includes(\"?iv=\")) return nip44.v2.decrypt(content, this.conversationKey);\n return nip04.decrypt(this.connection.secret, this.connection.walletPubkey, content);\n }\n\n /**\n * Sends one request and waits for its answer. `NotDelivered` when it never reached the relay; `NwcError`\n * for an error the wallet answered; `NoAnswer` (or a relay error) when the outcome is unknown.\n */\n async request(method: string, params: Record<string, unknown>, { ms = this.options.requestMs ?? REQUEST_MS, expiresIn }: { ms?: number; expiresIn?: number } = {}): Promise<Record<string, unknown>> {\n if (this.closed) throw new NotDelivered(\"The wallet connection is closed\");\n const tags = [[\"p\", this.connection.walletPubkey]];\n if (this.conversationKey) tags.push([\"encryption\", \"nip44_v2\"]);\n if (expiresIn) tags.push([\"expiration\", String(now() + expiresIn)]);\n const event = finalizeEvent({ kind: KIND.request, created_at: now(), tags, content: this.encrypt(JSON.stringify({ method, params })) }, this.connection.secret);\n const answer = new Promise<Record<string, unknown>>((resolve, reject) => {\n const timer = setTimeout(() => { this.pending.delete(event.id); reject(new NoAnswer(method)); }, ms);\n this.pending.set(event.id, { method, resolve, reject, timer });\n });\n // The answer can come before the relay's acknowledgement (or without one): whichever decides first wins.\n const delivered = this.relay.publish(event).then(() => undefined, (error: unknown) => {\n const waiting = this.pending.get(event.id);\n if (!(error instanceof NotDelivered) || !waiting) return undefined;\n clearTimeout(waiting.timer); this.pending.delete(event.id);\n return error;\n });\n return Promise.race([answer, delivered.then((error) => (error ? Promise.reject(error) : answer))]);\n }\n\n /** Reads an answer: from the wallet, signed, about a request of ours, of the method asked. Anything else is dropped. */\n private answer(raw: unknown) {\n const event = raw as Event;\n if (!event || typeof event !== \"object\" || event.kind !== KIND.response || event.pubkey !== this.connection.walletPubkey) return;\n if (typeof event.content !== \"string\" || event.content.length > MAX_CONTENT || !Array.isArray(event.tags)) return;\n const ref = event.tags.find((t) => Array.isArray(t) && t[0] === \"e\")?.[1];\n const pending = typeof ref === \"string\" ? this.pending.get(ref) : undefined;\n if (!pending || !event.tags.some((t) => Array.isArray(t) && t[0] === \"p\" && t[1] === this.clientPubkey)) return;\n if (!verifyEvent(event)) return;\n let body: { result_type?: unknown; error?: { code?: unknown; message?: unknown } | null; result?: unknown };\n try { body = JSON.parse(this.decrypt(event.content)); } catch { return; }\n if (!body || typeof body !== \"object\" || body.result_type !== pending.method) return;\n clearTimeout(pending.timer);\n this.pending.delete(ref!);\n if (body.error) {\n const code = typeof body.error.code === \"string\" ? body.error.code.slice(0, 40) : \"OTHER\";\n const message = typeof body.error.message === \"string\" && body.error.message.trim() ? body.error.message.trim().slice(0, 200) : code;\n pending.reject(new NwcError(code, message));\n } else if (body.result && typeof body.result === \"object\" && !Array.isArray(body.result)) pending.resolve(body.result as Record<string, unknown>);\n else pending.reject(new NwcError(\"OTHER\", \"The wallet sent an empty answer\"));\n }\n\n private async lookup(paymentHash: string): Promise<NwcTransaction> {\n const tx = await this.request(\"lookup_invoice\", { payment_hash: paymentHash }) as NwcTransaction;\n if (tx.payment_hash !== undefined && String(tx.payment_hash).toLowerCase() !== paymentHash) throw new Error(\"The wallet answered about another invoice\");\n return tx;\n }\n\n // -- LightningProvider --\n\n async info(): Promise<LightningInfo> {\n let balance: number | undefined;\n if (this.capabilities.balance) {\n const result = await this.request(\"get_balance\", {});\n if (!isMsat(result.balance)) throw new Error(\"The wallet returned an invalid balance\");\n balance = Math.floor(result.balance / 1000);\n }\n return { network: this.network, alias: `${this.alias ?? \"NWC wallet\"} via ${new URL(this.relay.url).host}`, balance };\n }\n\n async createInvoice(amount: number, memo?: string): Promise<LightningInvoice> {\n if (!Number.isSafeInteger(amount) || amount <= 0 || !Number.isSafeInteger(amount * 1000)) throw new Error(\"Invalid amount\");\n const result = await this.request(\"make_invoice\", { amount: amount * 1000, ...(memo ? { description: memo.slice(0, 200) } : {}), expiry: INVOICE_EXPIRY_S }) as NwcTransaction;\n const text = typeof result.invoice === \"string\" && result.invoice.length <= MAX_INVOICE ? result.invoice : \"\";\n const decoded = decodeBolt11(text);\n if (!decoded?.paymentHash || decoded.amountMsat !== BigInt(amount) * 1000n) throw new Error(\"The wallet returned an invoice that does not match the request\");\n if (result.payment_hash !== undefined && String(result.payment_hash).toLowerCase() !== decoded.paymentHash) throw new Error(\"The wallet returned an invoice that does not match its payment hash\");\n return { invoice: decoded.invoice, paymentHash: decoded.paymentHash, amount, expiresAt: decoded.expiresAt * 1000 };\n }\n\n async invoiceStatus(invoice: LightningInvoice): Promise<InvoiceStatus> {\n let tx: NwcTransaction;\n try { tx = await this.lookup(invoice.paymentHash); }\n catch (error) {\n if (error instanceof NwcError && error.code === \"NOT_FOUND\" && invoice.expiresAt < Date.now()) return { state: \"expired\" };\n throw error;\n }\n const expired = invoice.expiresAt < Date.now();\n if (tx.type === \"outgoing\") return { state: expired ? \"expired\" : \"open\" };\n // An incoming invoice's preimage is known before it is paid: only `state` or `settled_at` say it was.\n const state = tx.state ?? (tx.settled_at ? \"settled\" : \"pending\");\n if (state === \"settled\") return { state: \"paid\", amount: isMsat(tx.amount) ? Math.floor(tx.amount / 1000) : invoice.amount };\n if (state === \"expired\" || state === \"failed\") return { state: \"expired\" };\n return { state: expired ? \"expired\" : \"open\" };\n }\n\n /**\n * Pays through the wallet. NIP-47 carries no fee limit: the wallet applies its own, and the fee it\n * reports is passed on as it is.\n */\n async payInvoice(invoice: string, _maxFee: number): Promise<LightningPayResult> {\n const decoded = decodeBolt11(invoice);\n if (!decoded?.paymentHash || decoded.amountSat === null) throw new NothingSpentError(\"That invoice cannot be paid through NWC\");\n if (!this.capabilities.send) throw new NothingSpentError(\"This wallet connection may not pay and look up invoices\");\n let result: Record<string, unknown>;\n try {\n result = await this.request(\"pay_invoice\", { invoice: decoded.invoice }, { ms: this.options.payMs ?? PAY_MS, expiresIn: PAY_EXPIRY_S });\n } catch (error) {\n if (error instanceof NotDelivered) throw new NothingSpentError(`The payment did not reach the wallet: ${error.message}`);\n if (error instanceof NwcError && REFUSED_BEFORE_PAYING.has(error.code)) throw new NothingSpentError(`The wallet refused the payment: ${error.message}`);\n // Any other code may come after the wallet tried (Alby Hub answers INTERNAL with LND's failure reason).\n if (error instanceof NwcError) return this.confirmFailure(decoded.invoice, decoded.paymentHash, error);\n throw error;\n }\n const preimage = typeof result.preimage === \"string\" ? result.preimage.toLowerCase() : \"\";\n // \"Paid\" without a proof that pays this invoice is not taken at its word: it is looked up instead.\n if (!HEX64.test(preimage) || hex(sha256(bytes(preimage))) !== decoded.paymentHash) throw new Error(\"The wallet said it paid, without a proof that matches the invoice\");\n return { state: \"paid\", preimage, fee: isMsat(result.fees_paid) ? Math.ceil(result.fees_paid / 1000) : undefined };\n }\n\n /**\n * An error after the wallet may have tried (`PAYMENT_FAILED` \"may be due to a timeout\", `INTERNAL`,\n * `OTHER`…): its own record decides. Only a payment it records as failed is `NothingSpentError`; one it\n * records as paid is paid; anything else is pending, or unknown when it cannot be asked.\n */\n private async confirmFailure(invoice: string, paymentHash: string, failure: NwcError): Promise<LightningPayResult> {\n let status: LightningPaymentStatus;\n try { status = await this.paymentStatus({ invoice, paymentHash }); }\n catch { throw new Error(`The wallet said the payment failed (${failure.message}), and cannot confirm it yet`); }\n if (status.state === \"failed\") throw new NothingSpentError(`The payment failed: ${failure.message}`);\n return status.state === \"paid\" ? { state: \"paid\", fee: status.fee, preimage: status.preimage } : { state: \"pending\" };\n }\n\n async paymentStatus(payment: LightningPaymentRef): Promise<LightningPaymentStatus> {\n let tx: NwcTransaction;\n try { tx = await this.lookup(payment.paymentHash); }\n catch (error) {\n if (!(error instanceof NwcError && error.code === \"NOT_FOUND\")) throw error;\n // The wallet never heard of it: failed once nobody can pay that invoice anymore, until then it may still start.\n const expiresAt = (decodeBolt11(payment.invoice)?.expiresAt ?? Infinity) * 1000;\n return { state: expiresAt + EXPIRED_MARGIN_MS < Date.now() ? \"failed\" : \"pending\" };\n }\n // Our own invoice (a wallet paying itself): not an answer about the payment.\n if (tx.type === \"incoming\") return { state: \"pending\" };\n const preimage = typeof tx.preimage === \"string\" && HEX64.test(tx.preimage.toLowerCase()) ? tx.preimage.toLowerCase() : undefined;\n const proven = !!preimage && hex(sha256(bytes(preimage))) === payment.paymentHash;\n const state = tx.state ?? (tx.settled_at || proven ? \"settled\" : \"pending\");\n const fee = isMsat(tx.fees_paid) ? Math.ceil(tx.fees_paid / 1000) : undefined;\n if (state === \"settled\") {\n if (preimage && !proven) throw new Error(\"The wallet's proof of payment does not match the invoice\");\n return { state: \"paid\", fee, preimage };\n }\n if (state === \"failed\" || state === \"expired\") return { state: \"failed\" };\n return { state: \"pending\" };\n }\n\n async close() {\n if (this.closed) return;\n this.closed = true;\n for (const [id, pending] of this.pending) { clearTimeout(pending.timer); this.pending.delete(id); pending.reject(new Error(\"The wallet connection is closed\")); }\n this.relay.close();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAM,OAAO;CAAE,MAAM;CAAO,SAAS;CAAO,UAAU;AAAM;;AAE5D,IAAM,cAAc;AACpB,IAAM,cAAc;AACpB,IAAM,WAAW;AACjB,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,SAAS;AACf,IAAM,aAAa;;AAEnB,IAAM,SAAS;;AAEf,IAAM,eAAe;;AAErB,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;;AAGzB,IAAM,wCAAwB,IAAI,IAAI;CAAC;CAAgB;CAAmB;CAAwB;CAAkB;CAAc;CAAgB;CAA0B;AAAa,CAAC;AAC1L,IAAM,WAA4C;CAAE,SAAS;CAAW,SAAS;CAAW,SAAS;CAAW,UAAU;CAAW,UAAU;CAAW,QAAQ;CAAU,WAAW;CAAa,SAAS;AAAU;AAEvN,IAAM,QAAQ;AACd,IAAM,OAAO,UAAsB,MAAM,KAAK,QAAQ,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AACpG,IAAM,SAAS,SAAiB,WAAW,KAAK,KAAK,MAAM,KAAK,IAAK,MAAM,SAAS,GAAG,EAAE,CAAC;AAC1F,IAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,IAAM,UAAU,UAAoC,OAAO,cAAc,KAAK,KAAM,SAAoB;;AAKxG,IAAa,eAAb,cAAkC,MAAM;CACtC,YAAY,SAAiB;EAAE,MAAM,OAAO;EAAG,KAAK,OAAO;CAAgB;AAC7E;;AAEA,IAAa,WAAb,cAA8B,MAAM;CACb;CAArB,YAAY,MAAuB,SAAiB;EAAE,MAAM,OAAO;EAA9C,KAAA,OAAA;EAAiD,KAAK,OAAO;CAAY;AAChG;;AAEA,IAAa,WAAb,cAA8B,MAAM;CAClC,YAAY,QAAgB;EAAE,MAAM,6BAA6B,OAAO,SAAS;EAAG,KAAK,OAAO;CAAY;AAC9G;;;;;;AAUA,IAAa,kBAAb,MAA6B;CAON;CAA8B;CANnD;CACA;CACA,uBAAwB,IAAI,IAA0B;CACtD,uBAAwB,IAAI,IAAsD;CAClF,SAAiB;CAEjB,YAAY,KAAsB,gBAAmD,WAAW,WAAW;EAAtF,KAAA,MAAA;EAA8B,KAAA,gBAAA;CAAyD;CAE5G,OAA2B;EACzB,IAAI,KAAK,QAAQ,OAAO,QAAQ,uBAAO,IAAI,MAAM,iCAAiC,CAAC;EACnF,IAAI,KAAK,QAAQ,eAAe,GAAG,OAAO,QAAQ,QAAQ,KAAK,MAAM;EACrE,IAAI,CAAC,KAAK,SAAS;GACjB,MAAM,UAAU,KAAK,cAAc;GACnC,KAAK,UAAU;GACf,QAAQ,YAAY,CAAC,CAAC,CAAC,CAAC,cAAc;IAAE,IAAI,KAAK,YAAY,SAAS,KAAK,UAAU,KAAA;GAAW,CAAC;EACnG;EACA,OAAO,KAAK;CACd;CAEA,gBAA4C;EAC1C,OAAO,IAAI,SAAoB,SAAS,WAAW;GACjD,IAAI,UAAU;GACd,MAAM,SAAS,IAAI,KAAK,cAAc,KAAK,GAAG;GAC9C,MAAM,QAAQ,UAAkB;IAC9B,IAAI,SAAS;IACb,UAAU;IAAM,aAAa,KAAK;IAClC,IAAI,OAAO;KAAE,IAAI;MAAE,OAAO,MAAM;KAAG,QAAQ,CAAuB;KAAE,OAAO,KAAK;KAAG;IAAQ;IAC3F,IAAI,KAAK,QAAQ;KAAE,OAAO,MAAM;KAAG,uBAAO,IAAI,MAAM,iCAAiC,CAAC;KAAG;IAAQ;IACjG,KAAK,SAAS;IACd,KAAK,MAAM,CAAC,IAAI,QAAQ,KAAK,MAAM,KAAK,MAAM;KAAC;KAAO;KAAI,IAAI;IAAM,CAAC;IACrE,QAAQ,MAAM;GAChB;GACA,MAAM,QAAQ,iBAAiB,qBAAK,IAAI,MAAM,mCAAmC,CAAC,GAAG,UAAU;GAC/F,OAAO,eAAe,KAAK;GAC3B,OAAO,gBAAgB,qBAAK,IAAI,MAAM,oCAAoC,CAAC;GAC3E,OAAO,gBAAgB;IACrB,qBAAK,IAAI,MAAM,0CAA0C,CAAC;IAC1D,IAAI,KAAK,WAAW,QAAQ;IAC5B,KAAK,SAAS,KAAA;IAEd,KAAK,MAAM,CAAC,IAAI,QAAQ,KAAK,MAAM;KAAE,KAAK,KAAK,OAAO,EAAE;KAAG,IAAI,qBAAK,IAAI,MAAM,8DAA8D,CAAC;IAAG;GAClJ;GACA,OAAO,aAAa,YAAY;IAAE,IAAI,KAAK,WAAW,QAAQ,KAAK,QAAQ,QAAQ,IAAI;GAAG;EAC5F,CAAC;CACH;CAEA,UAAU,IAAY,QAAgB,KAAmC;EACvE,KAAK,KAAK,IAAI,IAAI;GAAE,GAAG;GAAK;EAAO,CAAC;EACpC,KAAK,MAAM;GAAC;GAAO;GAAI;EAAM,CAAC;CAChC;CAEA,YAAY,IAAY;EACtB,IAAI,KAAK,KAAK,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;CACpD;;;;;CAMA,MAAM,MAAM,QAAgB,EAAE,KAAK,YAAY,aAAa,UAAiD,CAAC,GAAuB;EACnI,MAAM,KAAK,KAAK;EAChB,MAAM,KAAK,IAAI,IAAI,OAAO,gCAAgB,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,SAAoB,CAAC;EACtF,IAAI;GACF,MAAM,IAAI,SAAe,YAAY;IACnC,MAAM,QAAQ,WAAW,SAAS,EAAE;IACpC,IAAI,SAAS;IACb,MAAM,eAAe;KAAE,aAAa,KAAK;KAAG,QAAQ;IAAG;IACvD,KAAK,UAAU,IAAI,QAAQ;KACzB,QAAQ,MAAM;MAAE,IAAI,OAAO,SAAS,IAAI,OAAO,KAAK,CAAC;MAAG,IAAI,QAAQ,OAAO;KAAG;KAC9E,YAAY;MAAE,SAAS;MAAM,IAAI,OAAO,UAAU,CAAC,YAAY,OAAO;KAAG;IAC3E,CAAC;GACH,CAAC;EACH,UAAU;GAAE,KAAK,YAAY,EAAE;EAAG;EAClC,OAAO;CACT;;;;;CAMA,MAAM,QAAQ,OAA6B;EACzC,IAAI;EACJ,IAAI;GAAE,SAAS,MAAM,KAAK,KAAK;EAAG,SAAS,OAAO;GAAE,MAAM,IAAI,aAAa,iBAAiB,QAAQ,MAAM,UAAU,oCAAoC;EAAG;EAC3J,OAAO,IAAI,SAAe,SAAS,WAAW;GAC5C,MAAM,QAAQ,iBAAiB;IAAE,KAAK,KAAK,OAAO,MAAM,EAAE;IAAG,uBAAO,IAAI,MAAM,uCAAuC,CAAC;GAAG,GAAG,MAAM;GAClI,KAAK,KAAK,IAAI,MAAM,IAAI;IAAE,UAAU;KAAE,aAAa,KAAK;KAAG,QAAQ;IAAG;IAAG,OAAO,UAAU;KAAE,aAAa,KAAK;KAAG,OAAO,KAAK;IAAG;GAAE,CAAC;GAEnI,IAAI,OAAO,eAAe,KAAK,WAAW,KAAK,QAAQ;IAAE,KAAK,KAAK,OAAO,MAAM,EAAE;IAAG,aAAa,KAAK;IAAG,OAAO,IAAI,aAAa,6BAA6B,CAAC;IAAG;GAAQ;GAC3K,OAAO,KAAK,KAAK,UAAU,CAAC,SAAS,KAAK,CAAC,CAAC;EAC9C,CAAC;CACH;CAEA,QAAQ;EACN,KAAK,SAAS;EACd,KAAK,MAAM,CAAC,IAAI,QAAQ,KAAK,MAAM;GAAE,KAAK,KAAK,OAAO,EAAE;GAAG,IAAI,qBAAK,IAAI,MAAM,iCAAiC,CAAC;EAAG;EACnH,KAAK,KAAK,MAAM;EAChB,IAAI;GAAE,KAAK,QAAQ,MAAM;EAAG,QAAQ,CAAuB;EAC3D,KAAK,SAAS,KAAA;CAChB;CAEA,MAAc,SAAoB;EAChC,IAAI,KAAK,QAAQ,eAAe,GAAG,KAAK,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC;CAC7E;CAEA,QAAgB,MAAe;EAC7B,IAAI,OAAO,SAAS,YAAY,KAAK,SAAS,aAAa;EAC3D,IAAI;EACJ,IAAI;GAAE,UAAU,KAAK,MAAM,IAAI;EAAG,QAAQ;GAAE;EAAQ;EACpD,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,OAAO,QAAQ,OAAO,UAAU;EAC/D,MAAM,CAAC,MAAM,MAAM;EACnB,IAAI,SAAS,SAAS,KAAK,KAAK,IAAI,EAAE,CAAC,EAAE,MAAM,QAAQ,EAAE;OACpD,IAAI,SAAS,QAAQ,KAAK,KAAK,IAAI,EAAE,CAAC,EAAE,OAAO;OAC/C,IAAI,SAAS,MAAM;GACtB,MAAM,MAAM,KAAK,KAAK,IAAI,EAAE;GAC5B,IAAI,CAAC,KAAK;GACV,KAAK,KAAK,OAAO,EAAE;GACnB,MAAM,SAAS,OAAO,QAAQ,OAAO,WAAW,QAAQ,EAAE,CAAC,MAAM,GAAG,GAAG,IAAI;GAE3E,IAAI,QAAQ,OAAO,QAAQ,OAAO,WAAW,YAAY,GAAG,IAAI,GAAG;QAC9D,IAAI,KAAK,IAAI,aAAa,gCAAgC,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC;EAChG;CACF;AACF;AA6BA,IAAa,eAAb,MAAa,aAA0C;CAWhB;CAA4C;CAAiC;CAAiF;;CATnM;CACA;CACA,eAAgC,MAAM,IAAI,OAAO,gCAAgB,IAAI,WAAW,CAAC,CAAC,CAAC;CACnF,0BAA2B,IAAI,IAAqB;CACpD;CACA,UAAmC;CACnC;CACA,SAAiB;CAEjB,YAAoB,YAA4C,OAAyC,YAA2C,SAA8B,SAAsC;EAAnL,KAAA,aAAA;EAA4C,KAAA,QAAA;EAAiC,KAAA,aAAA;EAAiF,KAAA,UAAA;EACjM,KAAK,eAAe,aAAa,WAAW,MAAM;EAClD,IAAI,eAAe,YAAY,KAAK,kBAAkB,MAAM,GAAG,MAAM,mBAAmB,WAAW,QAAQ,WAAW,YAAY;EAClI,KAAK,eAAe,KAAK,eAAe,OAAO;CACjD;;;;;CAMA,aAAa,QAAQ,KAAa,UAAsB,CAAC,GAA0B;EACjF,MAAM,aAAa,YAAY,GAAG;EAClC,QAAQ,QAAQ,eAAe;EAC/B,IAAI,OAAoC;EACxC,KAAK,MAAM,OAAO,WAAW,QAAQ;GACnC,MAAM,YAAY,IAAI,gBAAgB,KAAK,QAAQ,SAAS;GAC5D,IAAI;IAAE,MAAM,UAAU,KAAK;IAAG,QAAQ;IAAW;GAAO,SAAS,OAAO;IAAE,UAAU,MAAM;IAAG,YAAY;GAAO;EAClH;EACA,IAAI,CAAC,OAAO,MAAM,qBAAqB,QAAQ,4BAAY,IAAI,MAAM,oCAAoC;EACzG,IAAI;EACJ,IAAI;GACF,MAAM,OAAO,aAAa,WAAW,MAAM,MAAM,MAAM;IAAE,OAAO,CAAC,KAAK,IAAI;IAAG,SAAS,CAAC,WAAW,YAAY;IAAG,OAAO;GAAE,GAAG;IAAE,YAAY;IAAM,IAAI,QAAQ;GAAO,CAAC,GAAG,WAAW,YAAY;GAC/L,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,gDAAgD,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,KAAK,+CAA+C;GAClJ,MAAM,WAAW,KAAK,KAAK,MAAM,MAAM,EAAE,OAAO,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,GAAA,CAAI,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;GAEpH,MAAM,aAAa,QAAQ,SAAS,UAAU,IAAI,aAAa,CAAC,QAAQ,UAAU,QAAQ,SAAS,OAAO,IAAI,UAAU,KAAA;GACxH,IAAI,CAAC,YAAY,MAAM,IAAI,MAAM,mEAAmE;GACpG,MAAM,UAAU,IAAI,IAAI,KAAK,QAAQ,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,CAAC;GACjE,SAAS,IAAI,aAAa,YAAY,OAAO,YAAY,SAAS,OAAO;GACzE,OAAO,OAAO;GACd,IAAI,QAAQ,QAAQ;IAClB,MAAM,SAAS;IACf,IAAI,QAAQ,OAAO,SAAS,MAAM,QAAQ,OAAO;IACjD,QAAQ,OAAO,iBAAiB,eAAe,KAAK,OAAO,MAAM,GAAG,EAAE,MAAM,KAAK,CAAC;GACpF;GACA,MAAM,OAAO,SAAS,OAAO;GAC7B,OAAO;EACT,SAAS,OAAO;GACd,IAAI,QAAQ,MAAM,OAAO,MAAM;QAAQ,MAAM,MAAM;GACnD,MAAM;EACR;CACF;CAEA,OAAe,WAAW,QAAmB,cAAyC;EACpF,OAAQ,OACL,QAAQ,MAAM,KAAK,EAAE,SAAS,KAAK,QAAQ,EAAE,WAAW,gBAAgB,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,UAAU,YAAY,MAAM,QAAQ,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CACjL,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;CACjD;CAEA,eAAuB,SAAqD;EAC1E,MAAM,SAAS,QAAQ,IAAI,gBAAgB;EAE3C,OAAO;GAAE,SAAS,QAAQ,IAAI,cAAc;GAAG,MAAM,QAAQ,IAAI,aAAa,KAAK;GAAQ,SAAS,QAAQ,IAAI,aAAa;GAAG;EAAO;CACzI;;;;;;CAOA,MAAc,SAAS,SAA8B;EACnD,IAAI,CAAC,QAAQ,IAAI,UAAU,GAAG;EAC9B,IAAI;EACJ,IAAI;GAAE,OAAO,MAAM,KAAK,QAAQ,YAAY,CAAC,CAAC;EAAG,SAC1C,OAAO;GAEZ,IAAI,iBAAiB,YAAY;IAAC;IAAc;IAAgB;GAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG;GACzG,MAAM;EACR;EACA,IAAI,KAAK,YAAY,KAAA,GAAW;GAC9B,MAAM,UAAU,OAAO,KAAK,YAAY,WAAW,SAAS,KAAK,QAAQ,YAAY,KAAK,KAAA;GAC1F,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,kDAAkD;GAChF,KAAK,UAAU;EACjB;EACA,IAAI,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,GAAG,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;EACnG,IAAI,MAAM,QAAQ,KAAK,OAAO,KAAK,KAAK,QAAQ,OAAO,MAAM,OAAO,MAAM,QAAQ,GAChF,KAAK,eAAe,KAAK,eAAe,IAAI,IAAI,KAAK,OAAmB,CAAC;CAE7E;CAEA,SAAiB;EACf,KAAK,MAAM,UAAU,KAAK,cAAc;GAAE,OAAO,CAAC,KAAK,QAAQ;GAAG,SAAS,CAAC,KAAK,WAAW,YAAY;GAAG,MAAM,CAAC,KAAK,YAAY;GAAG,OAAO,IAAI,IAAI;EAAG,GAAG,EAAE,QAAQ,MAAM,KAAK,OAAO,CAAC,EAAE,CAAC;CAC7L;CAIA,QAAgB,MAAc;EAC5B,OAAO,KAAK,kBAAkB,MAAM,GAAG,QAAQ,MAAM,KAAK,eAAe,IAAI,MAAM,QAAQ,KAAK,WAAW,QAAQ,KAAK,WAAW,cAAc,IAAI;CACvJ;CAEA,QAAgB,SAAiB;EAC/B,IAAI,KAAK,mBAAmB,CAAC,QAAQ,SAAS,MAAM,GAAG,OAAO,MAAM,GAAG,QAAQ,SAAS,KAAK,eAAe;EAC5G,OAAO,MAAM,QAAQ,KAAK,WAAW,QAAQ,KAAK,WAAW,cAAc,OAAO;CACpF;;;;;CAMA,MAAM,QAAQ,QAAgB,QAAiC,EAAE,KAAK,KAAK,QAAQ,aAAa,YAAY,cAAmD,CAAC,GAAqC;EACnM,IAAI,KAAK,QAAQ,MAAM,IAAI,aAAa,iCAAiC;EACzE,MAAM,OAAO,CAAC,CAAC,KAAK,KAAK,WAAW,YAAY,CAAC;EACjD,IAAI,KAAK,iBAAiB,KAAK,KAAK,CAAC,cAAc,UAAU,CAAC;EAC9D,IAAI,WAAW,KAAK,KAAK,CAAC,cAAc,OAAO,IAAI,IAAI,SAAS,CAAC,CAAC;EAClE,MAAM,QAAQ,cAAc;GAAE,MAAM,KAAK;GAAS,YAAY,IAAI;GAAG;GAAM,SAAS,KAAK,QAAQ,KAAK,UAAU;IAAE;IAAQ;GAAO,CAAC,CAAC;EAAE,GAAG,KAAK,WAAW,MAAM;EAC9J,MAAM,SAAS,IAAI,SAAkC,SAAS,WAAW;GACvE,MAAM,QAAQ,iBAAiB;IAAE,KAAK,QAAQ,OAAO,MAAM,EAAE;IAAG,OAAO,IAAI,SAAS,MAAM,CAAC;GAAG,GAAG,EAAE;GACnG,KAAK,QAAQ,IAAI,MAAM,IAAI;IAAE;IAAQ;IAAS;IAAQ;GAAM,CAAC;EAC/D,CAAC;EAED,MAAM,YAAY,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC,WAAW,KAAA,IAAY,UAAmB;GACpF,MAAM,UAAU,KAAK,QAAQ,IAAI,MAAM,EAAE;GACzC,IAAI,EAAE,iBAAiB,iBAAiB,CAAC,SAAS,OAAO,KAAA;GACzD,aAAa,QAAQ,KAAK;GAAG,KAAK,QAAQ,OAAO,MAAM,EAAE;GACzD,OAAO;EACT,CAAC;EACD,OAAO,QAAQ,KAAK,CAAC,QAAQ,UAAU,MAAM,UAAW,QAAQ,QAAQ,OAAO,KAAK,IAAI,MAAO,CAAC,CAAC;CACnG;;CAGA,OAAe,KAAc;EAC3B,MAAM,QAAQ;EACd,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,YAAY,MAAM,WAAW,KAAK,WAAW,cAAc;EAC1H,IAAI,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,SAAS,eAAe,CAAC,MAAM,QAAQ,MAAM,IAAI,GAAG;EAC3G,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG;EACvE,MAAM,UAAU,OAAO,QAAQ,WAAW,KAAK,QAAQ,IAAI,GAAG,IAAI,KAAA;EAClE,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,MAAM,MAAM,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK,YAAY,GAAG;EACzG,IAAI,CAAC,YAAY,KAAK,GAAG;EACzB,IAAI;EACJ,IAAI;GAAE,OAAO,KAAK,MAAM,KAAK,QAAQ,MAAM,OAAO,CAAC;EAAG,QAAQ;GAAE;EAAQ;EACxE,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,KAAK,gBAAgB,QAAQ,QAAQ;EAC9E,aAAa,QAAQ,KAAK;EAC1B,KAAK,QAAQ,OAAO,GAAI;EACxB,IAAI,KAAK,OAAO;GACd,MAAM,OAAO,OAAO,KAAK,MAAM,SAAS,WAAW,KAAK,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI;GAClF,MAAM,UAAU,OAAO,KAAK,MAAM,YAAY,YAAY,KAAK,MAAM,QAAQ,KAAK,IAAI,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI;GAChI,QAAQ,OAAO,IAAI,SAAS,MAAM,OAAO,CAAC;EAC5C,OAAO,IAAI,KAAK,UAAU,OAAO,KAAK,WAAW,YAAY,CAAC,MAAM,QAAQ,KAAK,MAAM,GAAG,QAAQ,QAAQ,KAAK,MAAiC;OAC3I,QAAQ,OAAO,IAAI,SAAS,SAAS,iCAAiC,CAAC;CAC9E;CAEA,MAAc,OAAO,aAA8C;EACjE,MAAM,KAAK,MAAM,KAAK,QAAQ,kBAAkB,EAAE,cAAc,YAAY,CAAC;EAC7E,IAAI,GAAG,iBAAiB,KAAA,KAAa,OAAO,GAAG,YAAY,CAAC,CAAC,YAAY,MAAM,aAAa,MAAM,IAAI,MAAM,2CAA2C;EACvJ,OAAO;CACT;CAIA,MAAM,OAA+B;EACnC,IAAI;EACJ,IAAI,KAAK,aAAa,SAAS;GAC7B,MAAM,SAAS,MAAM,KAAK,QAAQ,eAAe,CAAC,CAAC;GACnD,IAAI,CAAC,OAAO,OAAO,OAAO,GAAG,MAAM,IAAI,MAAM,wCAAwC;GACrF,UAAU,KAAK,MAAM,OAAO,UAAU,GAAI;EAC5C;EACA,OAAO;GAAE,SAAS,KAAK;GAAS,OAAO,GAAG,KAAK,SAAS,aAAa,OAAO,IAAI,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC;GAAQ;EAAQ;CACtH;CAEA,MAAM,cAAc,QAAgB,MAA0C;EAC5E,IAAI,CAAC,OAAO,cAAc,MAAM,KAAK,UAAU,KAAK,CAAC,OAAO,cAAc,SAAS,GAAI,GAAG,MAAM,IAAI,MAAM,gBAAgB;EAC1H,MAAM,SAAS,MAAM,KAAK,QAAQ,gBAAgB;GAAE,QAAQ,SAAS;GAAM,GAAI,OAAO,EAAE,aAAa,KAAK,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;GAAI,QAAQ;EAAiB,CAAC;EAC3J,MAAM,OAAO,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,UAAU,cAAc,OAAO,UAAU;EAC3G,MAAM,UAAU,aAAa,IAAI;EACjC,IAAI,CAAC,SAAS,eAAe,QAAQ,eAAe,OAAO,MAAM,IAAI,OAAO,MAAM,IAAI,MAAM,gEAAgE;EAC5J,IAAI,OAAO,iBAAiB,KAAA,KAAa,OAAO,OAAO,YAAY,CAAC,CAAC,YAAY,MAAM,QAAQ,aAAa,MAAM,IAAI,MAAM,qEAAqE;EACjM,OAAO;GAAE,SAAS,QAAQ;GAAS,aAAa,QAAQ;GAAa;GAAQ,WAAW,QAAQ,YAAY;EAAK;CACnH;CAEA,MAAM,cAAc,SAAmD;EACrE,IAAI;EACJ,IAAI;GAAE,KAAK,MAAM,KAAK,OAAO,QAAQ,WAAW;EAAG,SAC5C,OAAO;GACZ,IAAI,iBAAiB,YAAY,MAAM,SAAS,eAAe,QAAQ,YAAY,KAAK,IAAI,GAAG,OAAO,EAAE,OAAO,UAAU;GACzH,MAAM;EACR;EACA,MAAM,UAAU,QAAQ,YAAY,KAAK,IAAI;EAC7C,IAAI,GAAG,SAAS,YAAY,OAAO,EAAE,OAAO,UAAU,YAAY,OAAO;EAEzE,MAAM,QAAQ,GAAG,UAAU,GAAG,aAAa,YAAY;EACvD,IAAI,UAAU,WAAW,OAAO;GAAE,OAAO;GAAQ,QAAQ,OAAO,GAAG,MAAM,IAAI,KAAK,MAAM,GAAG,SAAS,GAAI,IAAI,QAAQ;EAAO;EAC3H,IAAI,UAAU,aAAa,UAAU,UAAU,OAAO,EAAE,OAAO,UAAU;EACzE,OAAO,EAAE,OAAO,UAAU,YAAY,OAAO;CAC/C;;;;;CAMA,MAAM,WAAW,SAAiB,SAA8C;EAC9E,MAAM,UAAU,aAAa,OAAO;EACpC,IAAI,CAAC,SAAS,eAAe,QAAQ,cAAc,MAAM,MAAM,IAAI,kBAAkB,yCAAyC;EAC9H,IAAI,CAAC,KAAK,aAAa,MAAM,MAAM,IAAI,kBAAkB,yDAAyD;EAClH,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,KAAK,QAAQ,eAAe,EAAE,SAAS,QAAQ,QAAQ,GAAG;IAAE,IAAI,KAAK,QAAQ,SAAS;IAAQ,WAAW;GAAa,CAAC;EACxI,SAAS,OAAO;GACd,IAAI,iBAAiB,cAAc,MAAM,IAAI,kBAAkB,yCAAyC,MAAM,SAAS;GACvH,IAAI,iBAAiB,YAAY,sBAAsB,IAAI,MAAM,IAAI,GAAG,MAAM,IAAI,kBAAkB,mCAAmC,MAAM,SAAS;GAEtJ,IAAI,iBAAiB,UAAU,OAAO,KAAK,eAAe,QAAQ,SAAS,QAAQ,aAAa,KAAK;GACrG,MAAM;EACR;EACA,MAAM,WAAW,OAAO,OAAO,aAAa,WAAW,OAAO,SAAS,YAAY,IAAI;EAEvF,IAAI,CAAC,MAAM,KAAK,QAAQ,KAAK,IAAI,OAAO,MAAM,QAAQ,CAAC,CAAC,MAAM,QAAQ,aAAa,MAAM,IAAI,MAAM,mEAAmE;EACtK,OAAO;GAAE,OAAO;GAAQ;GAAU,KAAK,OAAO,OAAO,SAAS,IAAI,KAAK,KAAK,OAAO,YAAY,GAAI,IAAI,KAAA;EAAU;CACnH;;;;;;CAOA,MAAc,eAAe,SAAiB,aAAqB,SAAgD;EACjH,IAAI;EACJ,IAAI;GAAE,SAAS,MAAM,KAAK,cAAc;IAAE;IAAS;GAAY,CAAC;EAAG,QAC7D;GAAE,MAAM,IAAI,MAAM,uCAAuC,QAAQ,QAAQ,6BAA6B;EAAG;EAC/G,IAAI,OAAO,UAAU,UAAU,MAAM,IAAI,kBAAkB,uBAAuB,QAAQ,SAAS;EACnG,OAAO,OAAO,UAAU,SAAS;GAAE,OAAO;GAAQ,KAAK,OAAO;GAAK,UAAU,OAAO;EAAS,IAAI,EAAE,OAAO,UAAU;CACtH;CAEA,MAAM,cAAc,SAA+D;EACjF,IAAI;EACJ,IAAI;GAAE,KAAK,MAAM,KAAK,OAAO,QAAQ,WAAW;EAAG,SAC5C,OAAO;GACZ,IAAI,EAAE,iBAAiB,YAAY,MAAM,SAAS,cAAc,MAAM;GAGtE,OAAO,EAAE,QADU,aAAa,QAAQ,OAAO,CAAC,EAAE,aAAa,YAAY,MAC/C,oBAAoB,KAAK,IAAI,IAAI,WAAW,UAAU;EACpF;EAEA,IAAI,GAAG,SAAS,YAAY,OAAO,EAAE,OAAO,UAAU;EACtD,MAAM,WAAW,OAAO,GAAG,aAAa,YAAY,MAAM,KAAK,GAAG,SAAS,YAAY,CAAC,IAAI,GAAG,SAAS,YAAY,IAAI,KAAA;EACxH,MAAM,SAAS,CAAC,CAAC,YAAY,IAAI,OAAO,MAAM,QAAQ,CAAC,CAAC,MAAM,QAAQ;EACtE,MAAM,QAAQ,GAAG,UAAU,GAAG,cAAc,SAAS,YAAY;EACjE,MAAM,MAAM,OAAO,GAAG,SAAS,IAAI,KAAK,KAAK,GAAG,YAAY,GAAI,IAAI,KAAA;EACpE,IAAI,UAAU,WAAW;GACvB,IAAI,YAAY,CAAC,QAAQ,MAAM,IAAI,MAAM,0DAA0D;GACnG,OAAO;IAAE,OAAO;IAAQ;IAAK;GAAS;EACxC;EACA,IAAI,UAAU,YAAY,UAAU,WAAW,OAAO,EAAE,OAAO,SAAS;EACxE,OAAO,EAAE,OAAO,UAAU;CAC5B;CAEA,MAAM,QAAQ;EACZ,IAAI,KAAK,QAAQ;EACjB,KAAK,SAAS;EACd,KAAK,MAAM,CAAC,IAAI,YAAY,KAAK,SAAS;GAAE,aAAa,QAAQ,KAAK;GAAG,KAAK,QAAQ,OAAO,EAAE;GAAG,QAAQ,uBAAO,IAAI,MAAM,iCAAiC,CAAC;EAAG;EAChK,KAAK,MAAM,MAAM;CACnB;AACF"}
@@ -67,11 +67,11 @@ var nwc = {
67
67
  parseNwcUri(secrets.uri ?? "");
68
68
  },
69
69
  async create({ secrets }, host) {
70
- const { NwcLightning } = await import("./nwc-0JYm8Vys.js");
70
+ const { NwcLightning } = await import("./nwc-z0pa5zql.js");
71
71
  return NwcLightning.connect(secrets.uri, { signal: host.signal });
72
72
  }
73
73
  };
74
74
  //#endregion
75
75
  export { parseNwcUri as n, nwc as t };
76
76
 
77
- //# sourceMappingURL=nwcProvider-2coJAsqr.js.map
77
+ //# sourceMappingURL=nwcProvider-C1AhPoFW.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nwcProvider-2coJAsqr.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/providers/nwcProvider.ts"],"sourcesContent":["import type { LightningProviderDescriptor } from \"./lightning\";\nimport { PROVIDER_PLATFORMS } from \"./types\";\n\n/**\n * Nostr Wallet Connect as the source picker lists it, and its connection URI. The client (`./nwc`) and its NIP-04 /\n * NIP-44 encryption load when a wallet connects, not with the app.\n */\n\nconst MAX_URI = 2048;\nconst MAX_RELAYS = 5;\nconst HEX64 = /^[0-9a-f]{64}$/;\nconst bytes = (text: string) => Uint8Array.from(text.match(/../g)!, (b) => parseInt(b, 16));\n\nexport interface NwcConnection {\n walletPubkey: string;\n relays: string[];\n /** The client key the wallet granted: a secret. */\n secret: Uint8Array;\n}\n\n/** Only secure relays, except on this machine (a local test relay). */\nfunction checkRelay(address: string): string {\n let relay: URL;\n try { relay = new URL(address); } catch { throw new Error(\"The connection URI has a relay that is not a URL\"); }\n if (relay.username || relay.password || relay.hash) throw new Error(\"The connection URI has a relay with credentials in it\");\n const loopback = [\"127.0.0.1\", \"localhost\", \"[::1]\"].includes(relay.hostname);\n if (!(relay.protocol === \"wss:\" || (relay.protocol === \"ws:\" && loopback))) throw new Error(\"Use a wallet whose relay is secure (wss://)\");\n return relay.href;\n}\n\n/** Reads a `nostr+walletconnect://` URI. Its errors never repeat it: it holds a secret. */\nexport function parseNwcUri(input: string): NwcConnection {\n const text = (input ?? \"\").trim();\n if (text.length > MAX_URI) throw new Error(\"That connection URI is too long\");\n const match = /^(?:nostr\\+walletconnect|nostrwalletconnect):(?:\\/\\/)?([0-9a-fA-F]{64})\\/?\\?([^#]*)$/.exec(text);\n if (!match) throw new Error(\"That is not a Nostr Wallet Connect URI (nostr+walletconnect://…)\");\n const params = new URLSearchParams(match[2]);\n const secret = (params.get(\"secret\") ?? \"\").toLowerCase();\n if (!HEX64.test(secret) || /^0+$/.test(secret)) throw new Error(\"The connection URI has no valid secret\");\n const relays = [...new Set(params.getAll(\"relay\").map(checkRelay))];\n if (!relays.length) throw new Error(\"The connection URI names no relay\");\n if (relays.length > MAX_RELAYS) throw new Error(\"The connection URI names too many relays\");\n return { walletPubkey: match[1].toLowerCase(), relays, secret: bytes(secret) };\n}\n\nexport const nwc: LightningProviderDescriptor = {\n id: \"nwc\",\n label: \"Nostr Wallet Connect\",\n kind: \"lightning\",\n description: \"A wallet you connect with its NWC URI (Alby Hub, a node's NWC service, a hosted wallet). That wallet holds the sats and sets its own fee limit: custodial or not depends on the wallet.\",\n networks: [\"bitcoin\", \"testnet\", \"signet\", \"mutinynet\", \"regtest\"],\n platforms: PROVIDER_PLATFORMS,\n fields: [{\n name: \"uri\", label: \"Connection URI\", kind: \"secret\", placeholder: \"nostr+walletconnect://…\",\n help: \"From your wallet's app connections. Allow making, paying and looking up invoices, and reading the balance.\",\n }],\n validate({ secrets }) { parseNwcUri(secrets.uri ?? \"\"); },\n async create({ secrets }, host) {\n const { NwcLightning } = await import(\"./nwc\");\n return NwcLightning.connect(secrets.uri, { signal: host.signal });\n },\n};\n"],"mappings":";;;;;;AAQA,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,QAAQ;AACd,IAAM,SAAS,SAAiB,WAAW,KAAK,KAAK,MAAM,KAAK,IAAK,MAAM,SAAS,GAAG,EAAE,CAAC;;AAU1F,SAAS,WAAW,SAAyB;CAC3C,IAAI;CACJ,IAAI;EAAE,QAAQ,IAAI,IAAI,OAAO;CAAG,QAAQ;EAAE,MAAM,IAAI,MAAM,kDAAkD;CAAG;CAC/G,IAAI,MAAM,YAAY,MAAM,YAAY,MAAM,MAAM,MAAM,IAAI,MAAM,uDAAuD;CAC3H,MAAM,WAAW;EAAC;EAAa;EAAa;CAAO,CAAC,CAAC,SAAS,MAAM,QAAQ;CAC5E,IAAI,EAAE,MAAM,aAAa,UAAW,MAAM,aAAa,SAAS,WAAY,MAAM,IAAI,MAAM,6CAA6C;CACzI,OAAO,MAAM;AACf;;AAGA,SAAgB,YAAY,OAA8B;CACxD,MAAM,QAAQ,SAAS,GAAA,CAAI,KAAK;CAChC,IAAI,KAAK,SAAS,SAAS,MAAM,IAAI,MAAM,iCAAiC;CAC5E,MAAM,QAAQ,uFAAuF,KAAK,IAAI;CAC9G,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,kEAAkE;CAC9F,MAAM,SAAS,IAAI,gBAAgB,MAAM,EAAE;CAC3C,MAAM,UAAU,OAAO,IAAI,QAAQ,KAAK,GAAA,CAAI,YAAY;CACxD,IAAI,CAAC,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,GAAG,MAAM,IAAI,MAAM,wCAAwC;CACxG,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,OAAO,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;CAClE,IAAI,CAAC,OAAO,QAAQ,MAAM,IAAI,MAAM,mCAAmC;CACvE,IAAI,OAAO,SAAS,YAAY,MAAM,IAAI,MAAM,0CAA0C;CAC1F,OAAO;EAAE,cAAc,MAAM,EAAE,CAAC,YAAY;EAAG;EAAQ,QAAQ,MAAM,MAAM;CAAE;AAC/E;AAEA,IAAa,MAAmC;CAC9C,IAAI;CACJ,OAAO;CACP,MAAM;CACN,aAAa;CACb,UAAU;EAAC;EAAW;EAAW;EAAU;EAAa;CAAS;CACjE,WAAW;CACX,QAAQ,CAAC;EACP,MAAM;EAAO,OAAO;EAAkB,MAAM;EAAU,aAAa;EACnE,MAAM;CACR,CAAC;CACD,SAAS,EAAE,WAAW;EAAE,YAAY,QAAQ,OAAO,EAAE;CAAG;CACxD,MAAM,OAAO,EAAE,WAAW,MAAM;EAC9B,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,OAAO,aAAa,QAAQ,QAAQ,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;CAClE;AACF"}
1
+ {"version":3,"file":"nwcProvider-C1AhPoFW.js","names":[],"sources":["../../../browser/src/engine/paymentAdapters/providers/nwcProvider.ts"],"sourcesContent":["import type { LightningProviderDescriptor } from \"./lightning\";\nimport { PROVIDER_PLATFORMS } from \"./types\";\n\n/**\n * Nostr Wallet Connect as the source picker lists it, and its connection URI. The client (`./nwc`) and its NIP-04 /\n * NIP-44 encryption load when a wallet connects, not with the app.\n */\n\nconst MAX_URI = 2048;\nconst MAX_RELAYS = 5;\nconst HEX64 = /^[0-9a-f]{64}$/;\nconst bytes = (text: string) => Uint8Array.from(text.match(/../g)!, (b) => parseInt(b, 16));\n\nexport interface NwcConnection {\n walletPubkey: string;\n relays: string[];\n /** The client key the wallet granted: a secret. */\n secret: Uint8Array;\n}\n\n/** Only secure relays, except on this machine (a local test relay). */\nfunction checkRelay(address: string): string {\n let relay: URL;\n try { relay = new URL(address); } catch { throw new Error(\"The connection URI has a relay that is not a URL\"); }\n if (relay.username || relay.password || relay.hash) throw new Error(\"The connection URI has a relay with credentials in it\");\n const loopback = [\"127.0.0.1\", \"localhost\", \"[::1]\"].includes(relay.hostname);\n if (!(relay.protocol === \"wss:\" || (relay.protocol === \"ws:\" && loopback))) throw new Error(\"Use a wallet whose relay is secure (wss://)\");\n return relay.href;\n}\n\n/** Reads a `nostr+walletconnect://` URI. Its errors never repeat it: it holds a secret. */\nexport function parseNwcUri(input: string): NwcConnection {\n const text = (input ?? \"\").trim();\n if (text.length > MAX_URI) throw new Error(\"That connection URI is too long\");\n const match = /^(?:nostr\\+walletconnect|nostrwalletconnect):(?:\\/\\/)?([0-9a-fA-F]{64})\\/?\\?([^#]*)$/.exec(text);\n if (!match) throw new Error(\"That is not a Nostr Wallet Connect URI (nostr+walletconnect://…)\");\n const params = new URLSearchParams(match[2]);\n const secret = (params.get(\"secret\") ?? \"\").toLowerCase();\n if (!HEX64.test(secret) || /^0+$/.test(secret)) throw new Error(\"The connection URI has no valid secret\");\n const relays = [...new Set(params.getAll(\"relay\").map(checkRelay))];\n if (!relays.length) throw new Error(\"The connection URI names no relay\");\n if (relays.length > MAX_RELAYS) throw new Error(\"The connection URI names too many relays\");\n return { walletPubkey: match[1].toLowerCase(), relays, secret: bytes(secret) };\n}\n\nexport const nwc: LightningProviderDescriptor = {\n id: \"nwc\",\n label: \"Nostr Wallet Connect\",\n kind: \"lightning\",\n description: \"A wallet you connect with its NWC URI (Alby Hub, a node's NWC service, a hosted wallet). That wallet holds the sats and sets its own fee limit: custodial or not depends on the wallet.\",\n networks: [\"bitcoin\", \"testnet\", \"signet\", \"mutinynet\", \"regtest\"],\n platforms: PROVIDER_PLATFORMS,\n fields: [{\n name: \"uri\", label: \"Connection URI\", kind: \"secret\", placeholder: \"nostr+walletconnect://…\",\n help: \"From your wallet's app connections. Allow making, paying and looking up invoices, and reading the balance.\",\n }],\n validate({ secrets }) { parseNwcUri(secrets.uri ?? \"\"); },\n async create({ secrets }, host) {\n const { NwcLightning } = await import(\"./nwc\");\n return NwcLightning.connect(secrets.uri, { signal: host.signal });\n },\n};\n"],"mappings":";;;;;;AAQA,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,QAAQ;AACd,IAAM,SAAS,SAAiB,WAAW,KAAK,KAAK,MAAM,KAAK,IAAK,MAAM,SAAS,GAAG,EAAE,CAAC;;AAU1F,SAAS,WAAW,SAAyB;CAC3C,IAAI;CACJ,IAAI;EAAE,QAAQ,IAAI,IAAI,OAAO;CAAG,QAAQ;EAAE,MAAM,IAAI,MAAM,kDAAkD;CAAG;CAC/G,IAAI,MAAM,YAAY,MAAM,YAAY,MAAM,MAAM,MAAM,IAAI,MAAM,uDAAuD;CAC3H,MAAM,WAAW;EAAC;EAAa;EAAa;CAAO,CAAC,CAAC,SAAS,MAAM,QAAQ;CAC5E,IAAI,EAAE,MAAM,aAAa,UAAW,MAAM,aAAa,SAAS,WAAY,MAAM,IAAI,MAAM,6CAA6C;CACzI,OAAO,MAAM;AACf;;AAGA,SAAgB,YAAY,OAA8B;CACxD,MAAM,QAAQ,SAAS,GAAA,CAAI,KAAK;CAChC,IAAI,KAAK,SAAS,SAAS,MAAM,IAAI,MAAM,iCAAiC;CAC5E,MAAM,QAAQ,uFAAuF,KAAK,IAAI;CAC9G,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,kEAAkE;CAC9F,MAAM,SAAS,IAAI,gBAAgB,MAAM,EAAE;CAC3C,MAAM,UAAU,OAAO,IAAI,QAAQ,KAAK,GAAA,CAAI,YAAY;CACxD,IAAI,CAAC,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,GAAG,MAAM,IAAI,MAAM,wCAAwC;CACxG,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,OAAO,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;CAClE,IAAI,CAAC,OAAO,QAAQ,MAAM,IAAI,MAAM,mCAAmC;CACvE,IAAI,OAAO,SAAS,YAAY,MAAM,IAAI,MAAM,0CAA0C;CAC1F,OAAO;EAAE,cAAc,MAAM,EAAE,CAAC,YAAY;EAAG;EAAQ,QAAQ,MAAM,MAAM;CAAE;AAC/E;AAEA,IAAa,MAAmC;CAC9C,IAAI;CACJ,OAAO;CACP,MAAM;CACN,aAAa;CACb,UAAU;EAAC;EAAW;EAAW;EAAU;EAAa;CAAS;CACjE,WAAW;CACX,QAAQ,CAAC;EACP,MAAM;EAAO,OAAO;EAAkB,MAAM;EAAU,aAAa;EACnE,MAAM;CACR,CAAC;CACD,SAAS,EAAE,WAAW;EAAE,YAAY,QAAQ,OAAO,EAAE;CAAG;CACxD,MAAM,OAAO,EAAE,WAAW,MAAM;EAC9B,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,OAAO,aAAa,QAAQ,QAAQ,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;CAClE;AACF"}
@@ -1,2 +1,2 @@
1
- import { n as identityProvider, r as identityProviders, t as IDENTITY_PROVIDERS } from "./registry-BptCF3tL.js";
1
+ import { n as identityProvider, r as identityProviders, t as IDENTITY_PROVIDERS } from "./registry-JrnwUWmh.js";
2
2
  export { IDENTITY_PROVIDERS, identityProvider, identityProviders };
@@ -1,5 +1,5 @@
1
- import { An as pubkyProofFile, At as verifyAtprotoRecordProof, Bt as didWebDocumentUrl, Cl as randomBytes, Ct as atprotoProofRkey, Di as domainTxtRecord, Dl as utf8Encode, Dn as newPubkyProofFolder, Ei as dnsProofName, El as utf8Decode, En as isPubkyProofFolder, Et as normalizeAtprotoHandle, Ft as checkDidJws, Gi as IdentityCheckUnavailable, Gt as normalizeDid, Ht as didWebFileNames, It as checkDidSignature, Jt as parseDidSignaturePaste, Kt as parseDid, Li as wellKnownUrl, Lt as didGhostlyServiceEntry, Mi as normalizeDomain, Mn as homeserverWebEndpoint, Mt as DID_FILE_MAX_BYTES, Nn as pubkyHomeserverOf, Oi as domainWellKnownFile, On as normalizePubkyKey, Ot as shortAtprotoDid, Pt as DidError, Rt as didJwsAlg, St as atprotoProofRecord, Tn as isPubkyKey, Tt as isAtprotoDid, Ut as didWebFileUrl, Vt as didWebFile, Wt as didWebHost, Xt as staticDidDocument, Yt as signingKeys, Zt as strictBase64Url, _t as ATPROTO_DECLARED_SCOPE, bt as ATPROTO_PROOF_SCOPE, ct as SshSigError, dt as sameSshKey, ft as sshSignCommand, gt as decodeAnyBitcoinAddress, ht as BitcoinAddressError, jn as pubkyProofPath, jt as DID_DOCUMENT_MAX_BYTES, kn as pubkyProofCapability, kt as AtprotoProofError, lt as parseSshPublicKey, mt as verifyBitcoinMessage, nn as resolveDidDht, pt as verifySshSignature, qt as parseDidDocument, sl as RELAY_PAYLOAD_MAX_BYTES, st as SSHSIG_NAMESPACE, ul as openRelayPayload, ut as parseSshSignature, vt as ATPROTO_FULL_SCOPE, wl as toBase64Url, wn as PUBKY_PROOF_MAX_BYTES, wt as checkAtprotoProofRecord, xl as fromBase64Url, yt as ATPROTO_PROOF_COLLECTION, zt as didSignedMessages } from "./src-BLzG4Sfv.js";
2
- import { _ as reserveAdapterIds, a as DomainCheckError, b as testBuild, c as assertPublicHost, d as ownDid, i as verifiedAtprotoHandle, l as chosenResolver, m as registeredIdentityProviders, n as resolveAtprotoDid, o as assertDomainRecord, r as resolveAtprotoHandle, s as assertNip05, t as assertPublicServer, u as resolverById, v as boundedIdentityFetch } from "./resolve-2hGrvTen.js";
1
+ import { An as pubkyProofFile, At as verifyAtprotoRecordProof, Bt as didWebDocumentUrl, Cl as randomBytes, Ct as atprotoProofRkey, Di as domainTxtRecord, Dl as utf8Encode, Dn as newPubkyProofFolder, Ei as dnsProofName, El as utf8Decode, En as isPubkyProofFolder, Et as normalizeAtprotoHandle, Ft as checkDidJws, Gi as IdentityCheckUnavailable, Gt as normalizeDid, Ht as didWebFileNames, It as checkDidSignature, Jt as parseDidSignaturePaste, Kt as parseDid, Li as wellKnownUrl, Lt as didGhostlyServiceEntry, Mi as normalizeDomain, Mn as homeserverWebEndpoint, Mt as DID_FILE_MAX_BYTES, Nn as pubkyHomeserverOf, Oi as domainWellKnownFile, On as normalizePubkyKey, Ot as shortAtprotoDid, Pt as DidError, Rt as didJwsAlg, St as atprotoProofRecord, Tn as isPubkyKey, Tt as isAtprotoDid, Ut as didWebFileUrl, Vt as didWebFile, Wt as didWebHost, Xt as staticDidDocument, Yt as signingKeys, Zt as strictBase64Url, _t as ATPROTO_DECLARED_SCOPE, bt as ATPROTO_PROOF_SCOPE, ct as SshSigError, dt as sameSshKey, ft as sshSignCommand, gt as decodeAnyBitcoinAddress, ht as BitcoinAddressError, jn as pubkyProofPath, jt as DID_DOCUMENT_MAX_BYTES, kn as pubkyProofCapability, kt as AtprotoProofError, lt as parseSshPublicKey, mt as verifyBitcoinMessage, nn as resolveDidDht, pt as verifySshSignature, qt as parseDidDocument, sl as RELAY_PAYLOAD_MAX_BYTES, st as SSHSIG_NAMESPACE, ul as openRelayPayload, ut as parseSshSignature, vt as ATPROTO_FULL_SCOPE, wl as toBase64Url, wn as PUBKY_PROOF_MAX_BYTES, wt as checkAtprotoProofRecord, xl as fromBase64Url, yt as ATPROTO_PROOF_COLLECTION, zt as didSignedMessages } from "./src-XhjSWnp-.js";
2
+ import { _ as reserveAdapterIds, a as DomainCheckError, b as testBuild, c as assertPublicHost, d as ownDid, i as verifiedAtprotoHandle, l as chosenResolver, m as registeredIdentityProviders, n as resolveAtprotoDid, o as assertDomainRecord, r as resolveAtprotoHandle, s as assertNip05, t as assertPublicServer, u as resolverById, v as boundedIdentityFetch } from "./resolve-Ssq1nDy4.js";
3
3
  import { ed25519 } from "@noble/curves/ed25519.js";
4
4
  import { sha256 } from "@noble/hashes/sha2.js";
5
5
  import { schnorr } from "@noble/curves/secp256k1.js";
@@ -3775,4 +3775,4 @@ function identityProvider(id, providers = identityProviders()) {
3775
3775
  //#endregion
3776
3776
  export { identityProvider as n, identityProviders as r, IDENTITY_PROVIDERS as t };
3777
3777
 
3778
- //# sourceMappingURL=registry-BptCF3tL.js.map
3778
+ //# sourceMappingURL=registry-JrnwUWmh.js.map