From eae7e39b573f09f1b7a776f16c9b9972419372af Mon Sep 17 00:00:00 2001 From: Michael Bumann Date: Mon, 24 Apr 2023 09:56:47 +0200 Subject: [PATCH] Implement new NIP47 spec (#6) * Implement new NIP47 spec * Refactor defaults and make it extensible * add websocket-polifyll as dev dependency for testing * Add getInfo call * Return NIP47 error code in sendPayment response * No more 23196 error kind * Catch JSON errors in the response * Default to adding the secret to the URL --- package.json | 5 +- repl.js | 6 ++ src/webln/NostrWeblnProvider.ts | 157 +++++++++++++++------------- yarn.lock | 180 ++++++++++++++++++++++++-------- 4 files changed, 233 insertions(+), 115 deletions(-) diff --git a/package.json b/package.json index 47bb9f7..b76e19b 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,15 @@ "dependencies": { "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", - "nostr-tools": "^1.7.5" + "nostr-tools": "^1.10.0" }, "devDependencies": { "@types/crypto-js": "^4.1.1", "@types/node": "^18.11.0", "express": "^4.18.2", "microbundle": "^0.15.1", - "typescript": "^4.8.4" + "typescript": "^4.8.4", + "websocket-polyfill": "^0.0.3" }, "engines": { "node": ">=14" diff --git a/repl.js b/repl.js index ba773d0..13fcf4c 100644 --- a/repl.js +++ b/repl.js @@ -1,5 +1,11 @@ import * as repl from 'node:repl'; import { auth, Client, webln } from "./dist/index.module.js"; +import 'websocket-polyfill'; +try { + globalThis.crypto = await import('node:crypto'); +} catch (err) { + console.error('crypto not found!'); +} const authClient = new auth.OAuth2User({ client_id: process.env.CLIENT_ID, diff --git a/src/webln/NostrWeblnProvider.ts b/src/webln/NostrWeblnProvider.ts index 48c918c..f404683 100644 --- a/src/webln/NostrWeblnProvider.ts +++ b/src/webln/NostrWeblnProvider.ts @@ -11,43 +11,31 @@ import { UnsignedEvent } from 'nostr-tools'; -const DEFAULT_OPTIONS = { - relayUrl: "wss://relay.getalby.com/v1", - walletPubkey: '69effe7b49a6dd5cf525bd0905917a5005ffe480b58eeb8e861418cf3ae760d9' // Alby -}; - -const NWC_URLS = { - alby: "https://nwc.getalby.com/apps/new" -}; - -interface Nostr { - signEvent: (event: UnsignedEvent) => Promise; - nip04: { - decrypt: (pubkey: string, content: string) => Promise; - encrypt: (pubkey: string, content: string) => Promise; - }; -}; - -declare global { - var nostr: Nostr | undefined; +const NWCs: Record = { + alby: { + connectUrl: "https://nwc.getalby.com/apps/new", + relayUrl: "wss://relay.getalby.com/v1", + walletPubkey: '69effe7b49a6dd5cf525bd0905917a5005ffe480b58eeb8e861418cf3ae760d9' + } }; interface NostrWebLNOptions { + connectUrl?: string; // the URL to the NWC interface for the user to confirm the session relayUrl: string; walletPubkey: string; secret?: string; }; - export class NostrWebLNProvider { relay: Relay; relayUrl: string; secret: string | undefined; walletPubkey: string; + options: NostrWebLNOptions; subscribers: Record void>; static parseWalletConnectUrl(walletConnectUrl: string) { - walletConnectUrl = walletConnectUrl.replace('nostrwalletconnect://', 'http://'); // makes it possible to parse with URL in the different environments (browser/node/...) + walletConnectUrl = walletConnectUrl.replace('nostr+walletconnect://', 'http://'); // makes it possible to parse with URL in the different environments (browser/node/...) const url = new URL(walletConnectUrl); const options = {} as NostrWebLNOptions; options.walletPubkey = url.host; @@ -68,20 +56,26 @@ export class NostrWebLNProvider { return new NostrWebLNProvider(options); } - constructor(options?: { relayUrl?: string, secret?: string, walletPubkey?: string, nostrWalletConnectUrl?: string }) { + constructor(options?: { providerName?: string, connectUrl?: string, relayUrl?: string, secret?: string, walletPubkey?: string, nostrWalletConnectUrl?: string }) { if (options && options.nostrWalletConnectUrl) { options = { ...NostrWebLNProvider.parseWalletConnectUrl(options.nostrWalletConnectUrl), ...options }; } - const _options = { ...DEFAULT_OPTIONS, ...(options || {}) } as NostrWebLNOptions; - this.relayUrl = _options.relayUrl; + const providerOptions = NWCs[options?.providerName || 'alby'] as NostrWebLNOptions; + this.options = { ...providerOptions, ...(options || {}) } as NostrWebLNOptions; + this.relayUrl = this.options.relayUrl; this.relay = relayInit(this.relayUrl); - if (_options.secret) { - this.secret = (_options.secret.toLowerCase().startsWith('nsec') ? nip19.decode(_options.secret).data : _options.secret) as string; + if (this.options.secret) { + this.secret = (this.options.secret.toLowerCase().startsWith('nsec') ? nip19.decode(this.options.secret).data : this.options.secret) as string; } - this.walletPubkey = (_options.walletPubkey.toLowerCase().startsWith('npub') ? nip19.decode(_options.walletPubkey).data : _options.walletPubkey) as string; + this.walletPubkey = (this.options.walletPubkey.toLowerCase().startsWith('npub') ? nip19.decode(this.options.walletPubkey).data : this.options.walletPubkey) as string; this.subscribers = {}; + + // @ts-ignore + if(globalThis.WebSocket === undefined) { + console.error("WebSocket is undefined. Make sure to `import websocket-polyfill` for nodejs environments"); + } } on(name: string, callback: () => void) { @@ -95,8 +89,8 @@ export class NostrWebLNProvider { } } - getNostrWalletConnectUrl(includeSecret = false) { - let url = `nostrwalletconnect://${this.walletPubkey}?relay=${this.relayUrl}&pubkey=${this.publicKey}`; + getNostrWalletConnectUrl(includeSecret = true) { + let url = `nostr+walletconnect://${this.walletPubkey}?relay=${this.relayUrl}&pubkey=${this.publicKey}`; if (includeSecret) { url = `${url}&secret=${this.secret}`; } @@ -141,56 +135,59 @@ export class NostrWebLNProvider { } async encrypt(pubkey: string, content: string) { - let encrypted; - if (globalThis.nostr && !this.secret) { - encrypted = await globalThis.nostr.nip04.encrypt(pubkey, content); - } else if (this.secret) { - encrypted = await nip04.encrypt(this.secret, pubkey, content); - } else { - throw new Error("Missing secret key"); + if (!this.secret) { + throw new Error('Missing secret'); } + const encrypted = await nip04.encrypt(this.secret, pubkey, content); return encrypted; } async decrypt(pubkey: string, content: string) { - let decrypted; - if (globalThis.nostr && !this.secret) { - decrypted = await globalThis.nostr.nip04.decrypt(pubkey, content); - } else if (this.secret) { - decrypted = await nip04.decrypt(this.secret, pubkey, content); - } else { - throw new Error("Missing secret key"); + if (!this.secret) { + throw new Error('Missing secret'); } + const decrypted = await nip04.decrypt(this.secret, pubkey, content); return decrypted; } + // WebLN compatible response + // TODO: use NIP-47 get_info call + async getInfo() { + return { + methods: ["getInfo", "sendPayment"], + node: {}, + supports: ["lightning"], + version: "NWC" + } + } + sendPayment(invoice: string) { this.checkConnected(); return new Promise(async (resolve, reject) => { - const encryptedInvoice = await this.encrypt(this.walletPubkey, invoice); + const command = { + "method": "pay_invoice", + "params": { + "invoice": invoice + } + }; + const encryptedCommand = await this.encrypt(this.walletPubkey, JSON.stringify(command)); let event: any = { kind: 23194, created_at: Math.floor(Date.now() / 1000), tags: [['p', this.walletPubkey]], - content: encryptedInvoice, + content: encryptedCommand, }; - if (globalThis.nostr && !this.secret) { - event = await globalThis.nostr.signEvent(event); - } else if (this.secret) { - event.pubkey = this.publicKey; - event.id = this.getEventHash(event); - event.sig = this.signEvent(event); - } else { - throw new Error("Missing secret key"); - } + event.pubkey = this.publicKey; + event.id = this.getEventHash(event); + event.sig = this.signEvent(event); // subscribe to NIP_47_SUCCESS_RESPONSE_KIND and NIP_47_ERROR_RESPONSE_KIND // that reference the request event (NIP_47_REQUEST_KIND) let sub = this.relay.sub([ { - kinds: [23195, 23196], + kinds: [23195], authors: [this.walletPubkey], "#e": [event.id], } @@ -209,12 +206,19 @@ export class NostrWebLNProvider { clearTimeout(replyTimeoutCheck); sub.unsub(); const decryptedContent = await this.decrypt(this.walletPubkey, event.content); + let response; + try { + response = JSON.parse(decryptedContent); + } catch(e) { + reject({ error: "invalid response", code: "INTERNAL" }); + return; + } // @ts-ignore // event is still unknown in nostr-tools - if (event.kind == 23195) { - resolve({ preimage: decryptedContent }); + if (event.kind == 23195 && response.result?.preimage) { + resolve({ preimage: response.result.preimage }); this.notify('sendPayment', event.content); } else { - reject({ error: decryptedContent }); + reject({ error: response.error?.message, code: response.error?.code }); } }); @@ -222,14 +226,14 @@ export class NostrWebLNProvider { function publishTimeout() { //console.error(`Publish timeout: event ${event.id}`); - reject(`Publish timeout: event ${event.id}`); + reject({ error: `Publish timeout: event ${event.id}` }); } let publishTimeoutCheck = setTimeout(publishTimeout, 5000); pub.on('failed', (reason: unknown) => { //console.debug(`failed to publish to ${this.relay.url}: ${reason}`) clearTimeout(publishTimeoutCheck) - reject(`Failed to publish request: ${reason}`); + reject({ error: `Failed to publish request: ${reason}` }); }); pub.on('ok', () => { @@ -239,20 +243,33 @@ export class NostrWebLNProvider { }); } - initNWC(providerNameOrUrl: string, options: { name: string, returnTo?: string }) { + getConnectUrl(options: { name?: string, returnTo?: string }) { + if (!this.options.connectUrl) { + throw new Error("Missing connectUrl option"); + } + const url = new URL(this.options.connectUrl); + if (options?.name) { + url.searchParams.set('c', options?.name); + } + url.searchParams.set('pubkey', this.publicKey); + if (options?.returnTo) { + url.searchParams.set('returnTo', options.returnTo); + } + return url; + } + + initNWC(options: { name?: string, returnTo?: string } = {}) { + // here we assume an browser context and window/document is available + // we set the location.host as a default name if none is given + if (!options.name) { + options.name = document.location.host; + } + const url = this.getConnectUrl(options); const height = 600; const width = 400; const top = window.outerHeight / 2 + window.screenY - height / 2; const left = window.outerWidth / 2 + window.screenX - width / 2; - - const urlStr = NWC_URLS[providerNameOrUrl as keyof typeof NWC_URLS] || providerNameOrUrl; - const url = new URL(urlStr); - url.searchParams.set('c', options.name); - url.searchParams.set('pubkey', this.publicKey); - url.searchParams.set('url', document.location.origin); - if (options.returnTo) { - url.searchParams.set('returnTo', options.returnTo); - } + return new Promise((resolve, reject) => { const popup = window.open( url.toString(), diff --git a/yarn.lock b/yarn.lock index e0a20b9..94b1b78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1042,29 +1042,12 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@noble/curves@~0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-0.8.3.tgz#ad6d48baf2599cf1d58dcb734c14d5225c8996e0" - integrity sha512-OqaOf4RWDaCRuBKJLDURrgVxjLmneGsiCXGuzYB5y95YithZMA6w4uk34DHSm0rKMrrYiaeZj48/81EvaAScLQ== - dependencies: - "@noble/hashes" "1.3.0" - -"@noble/hashes@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" - integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== - -"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" - integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== - -"@noble/hashes@~1.2.0": +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/secp256k1@^1.7.1": +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== @@ -1133,21 +1116,21 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@scure/base@^1.1.1", "@scure/base@~1.1.0": +"@scure/base@1.1.1", "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== -"@scure/bip32@^1.1.5": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.2.0.tgz#35692d8f8cc3207200239fc119f9e038e5f465df" - integrity sha512-O+vT/hBVk+ag2i6j2CDemwd1E1MtGt+7O1KzrPNsaNvSsiEK55MyPIxJIMI2PS8Ijj464B2VbQlpRoQXxw1uHg== +"@scure/bip32@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.4.tgz#2c91a7be0156b15f26dd0c843a06a1917f129efd" + integrity sha512-m925ACYK0wPELsF7Z/VdLGmKj1StIeHraPMYB9xiAFiq/PnvqWd/99I0TQ2OZhjjlMDsDJeZlyXMWi0beaA7NA== dependencies: - "@noble/curves" "~0.8.3" - "@noble/hashes" "~1.3.0" + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" -"@scure/bip39@^1.1.1": +"@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== @@ -1388,6 +1371,13 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + builtin-modules@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -1671,7 +1661,15 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" -debug@2.6.9: +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -1831,6 +1829,32 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -1918,6 +1942,13 @@ express@^4.18.2: utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + figures@^1.0.1: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -2329,6 +2360,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -2606,6 +2642,11 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -2613,6 +2654,11 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + node-releases@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -2628,17 +2674,16 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -nostr-tools@^1.7.5: - version "1.7.5" - resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.7.5.tgz#349f469ff2877deb99d71c63d4883af93ec9f9a5" - integrity sha512-FFaYOAn9lFyISClbBzPe2eQ2ZiKx8xFviwHmdgTAmuue+eLrtPEI3tCqPtP624HghX/X4VnaixoiMvDB8g2+tQ== +nostr-tools@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-1.10.0.tgz#58d4b713c3d499c177612e9ac66f73f36c9fb654" + integrity sha512-Bbkucv25M69TaV+slqz1Vfce8G5O3dqSQOqqOZd/LwhooBJp62qt5V3JvlCV55OUqxaucC2brggeIER5Wliy1w== dependencies: - "@noble/hashes" "1.0.0" - "@noble/secp256k1" "^1.7.1" - "@scure/base" "^1.1.1" - "@scure/bip32" "^1.1.5" - "@scure/bip39" "^1.1.1" - prettier "^2.8.4" + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/base" "1.1.1" + "@scure/bip32" "1.1.4" + "@scure/bip39" "1.1.1" nth-check@^2.0.1: version "2.1.1" @@ -3077,11 +3122,6 @@ postcss@^8.2.1: picocolors "^1.0.0" source-map-js "^1.0.2" -prettier@^2.8.4: - version "2.8.6" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.6.tgz#5c174b29befd507f14b83e3c19f83fdc0e974b71" - integrity sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ== - pretty-bytes@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf" @@ -3565,6 +3605,11 @@ tslib@^2.0.3, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tstl@^2.0.7: + version "2.5.13" + resolved "https://registry.yarnpkg.com/tstl/-/tstl-2.5.13.tgz#a5a5d27b79a12767e46a08525b3e045c5cdb1180" + integrity sha512-h9wayHHFI5+yqt8iau0vqH96cTNhezhZ/Fk/hrIdpfkiMu3lg9nzyvMfs5bIdX51IVzZO6DudLqhkL/rVXpT6g== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -3573,6 +3618,23 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typescript@^4.1.3, typescript@^4.8.4: version "4.8.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" @@ -3629,6 +3691,13 @@ update-browserslist-db@^1.0.9: escalade "^3.1.1" picocolors "^1.0.0" +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -3649,6 +3718,26 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +websocket-polyfill@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/websocket-polyfill/-/websocket-polyfill-0.0.3.tgz#7321ada0f5f17516290ba1cb587ac111b74ce6a5" + integrity sha512-pF3kR8Uaoau78MpUmFfzbIRxXj9PeQrCuPepGE6JIsfsJ/o/iXr07Q2iQNzKSSblQJ0FiGWlS64N4pVSm+O3Dg== + dependencies: + tstl "^2.0.7" + websocket "^1.0.28" + +websocket@^1.0.28: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -3687,6 +3776,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"