From 8fb495789469ff6dae4469a5faa13d7c06bb68c9 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Fri, 8 Dec 2023 14:50:46 +0100 Subject: [PATCH 01/12] npm install @getalby/bitcoin-connect-react --- package-lock.json | 401 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 402 insertions(+) diff --git a/package-lock.json b/package-lock.json index 33bb08b77..4d85faaa2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@apollo/server": "^4.9.4", "@as-integrations/next": "^2.0.2", "@auth/prisma-adapter": "^1.0.3", + "@getalby/bitcoin-connect-react": "^2.4.3", "@graphql-tools/schema": "^10.0.0", "@noble/curves": "^1.2.0", "@opensearch-project/opensearch": "^2.4.0", @@ -2671,6 +2672,62 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@getalby/bitcoin-connect": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-2.4.3.tgz", + "integrity": "sha512-siuRiB8S1wCqmhXvxhQLvWZFwG04spfPSdOvHdWv8pDhy3ixfGRvUd9JFQ0saavGS3kueiaDZ6xTSUDJ1hY08Q==", + "dependencies": { + "@getalby/lightning-tools": "^4.2.0", + "@getalby/sdk": "^2.7.0", + "@lightninglabs/lnc-web": "^0.2.6-alpha", + "qrcode-generator": "^1.4.4", + "zustand": "^4.4.1" + } + }, + "node_modules/@getalby/bitcoin-connect-react": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-2.4.3.tgz", + "integrity": "sha512-eljMNcTB4h+wlXl8DPPq3sDV6tgyQdZvW5Ka1nCAMRUCmcU4Ux7NurX2XulePPKJ/zcjigbltxrsE5gENCdqzg==", + "dependencies": { + "@getalby/bitcoin-connect": "2.4.3" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@getalby/lightning-tools": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-4.2.1.tgz", + "integrity": "sha512-QOLF5LwIw6cYuAG3LYkEvZoQi/o+pFJtrG3L0koDo0xI4PliFLU9Qw70wUYJwl5X80UQtlukCpJ3nN5gyUBpdw==", + "dependencies": { + "crypto-js": "^4.1.1", + "light-bolt11-decoder": "^3.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "lightning", + "url": "lightning:hello@getalby.com" + } + }, + "node_modules/@getalby/sdk": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-2.7.0.tgz", + "integrity": "sha512-4NoEgdjx0R8SYDmJfCAsgvuBs0w3d8wsOMGI4m0h2MVsSeCcWW93lrzCl8bRmHTF5N7EfleHwnieYwn5j9KZTA==", + "dependencies": { + "crypto-js": "^4.1.1", + "events": "^3.3.0", + "nostr-tools": "^1.17.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "lightning", + "url": "lightning:hello@getalby.com" + } + }, "node_modules/@graphql-tools/merge": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", @@ -2863,6 +2920,25 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@lightninglabs/lnc-core": { + "version": "0.2.6-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.6-alpha.tgz", + "integrity": "sha512-bw2EQG78pPKMZMFwV+TR99RUbYgPVUKQYMLGGKIOvhPds3dBWSDZpMoqOyW/WidWGXF/ugPHzud8lDbKKhNXgA==" + }, + "node_modules/@lightninglabs/lnc-web": { + "version": "0.2.6-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.6-alpha.tgz", + "integrity": "sha512-SrqR8xaDnFLgNzPe5om7REOAhSOP95jQNIHP0GY0Lv895eDjrI6CPkfCFcX97INoDWYHBvDT8DZeYkBvlznVNA==", + "dependencies": { + "@lightninglabs/lnc-core": "0.2.6-alpha", + "crypto-js": "4.1.1" + } + }, + "node_modules/@lightninglabs/lnc-web/node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "node_modules/@next/env": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", @@ -3020,6 +3096,14 @@ "semver": "bin/semver.js" } }, + "node_modules/@noble/ciphers": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", + "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@noble/curves": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", @@ -3364,6 +3448,64 @@ "rollup": "^1.20.0||^2.0.0" } }, + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "dependencies": { + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -5835,6 +5977,11 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -9491,6 +9638,14 @@ "node": ">= 0.8.0" } }, + "node_modules/light-bolt11-decoder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.0.0.tgz", + "integrity": "sha512-AKvOigD2pmC8ktnn2TIqdJu0K0qk6ukUmTvHwF3JNkm8uWCqt18Ijn33A/a7gaRZ4PghJ59X+8+MXrzLKdBTmQ==", + "dependencies": { + "@scure/base": "1.1.1" + } + }, "node_modules/lightning": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/lightning/-/lightning-10.1.4.tgz", @@ -11594,6 +11749,49 @@ "ws": "^8.8.1" } }, + "node_modules/nostr-tools": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz", + "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==", + "dependencies": { + "@noble/ciphers": "0.2.0", + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/nostr-tools/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/nostr-tools/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/nprogress": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", @@ -12818,6 +13016,11 @@ "bitcoin-ops": "^1.3.0" } }, + "node_modules/qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "node_modules/qrcode.react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", @@ -15720,6 +15923,14 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", @@ -16568,6 +16779,33 @@ "zen-observable": "0.8.15" } }, + "node_modules/zustand": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz", @@ -18243,6 +18481,45 @@ "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true }, + "@getalby/bitcoin-connect": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-2.4.3.tgz", + "integrity": "sha512-siuRiB8S1wCqmhXvxhQLvWZFwG04spfPSdOvHdWv8pDhy3ixfGRvUd9JFQ0saavGS3kueiaDZ6xTSUDJ1hY08Q==", + "requires": { + "@getalby/lightning-tools": "^4.2.0", + "@getalby/sdk": "^2.7.0", + "@lightninglabs/lnc-web": "^0.2.6-alpha", + "qrcode-generator": "^1.4.4", + "zustand": "^4.4.1" + } + }, + "@getalby/bitcoin-connect-react": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-2.4.3.tgz", + "integrity": "sha512-eljMNcTB4h+wlXl8DPPq3sDV6tgyQdZvW5Ka1nCAMRUCmcU4Ux7NurX2XulePPKJ/zcjigbltxrsE5gENCdqzg==", + "requires": { + "@getalby/bitcoin-connect": "2.4.3" + } + }, + "@getalby/lightning-tools": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-4.2.1.tgz", + "integrity": "sha512-QOLF5LwIw6cYuAG3LYkEvZoQi/o+pFJtrG3L0koDo0xI4PliFLU9Qw70wUYJwl5X80UQtlukCpJ3nN5gyUBpdw==", + "requires": { + "crypto-js": "^4.1.1", + "light-bolt11-decoder": "^3.0.0" + } + }, + "@getalby/sdk": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-2.7.0.tgz", + "integrity": "sha512-4NoEgdjx0R8SYDmJfCAsgvuBs0w3d8wsOMGI4m0h2MVsSeCcWW93lrzCl8bRmHTF5N7EfleHwnieYwn5j9KZTA==", + "requires": { + "crypto-js": "^4.1.1", + "events": "^3.3.0", + "nostr-tools": "^1.17.0" + } + }, "@graphql-tools/merge": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", @@ -18387,6 +18664,27 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@lightninglabs/lnc-core": { + "version": "0.2.6-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.6-alpha.tgz", + "integrity": "sha512-bw2EQG78pPKMZMFwV+TR99RUbYgPVUKQYMLGGKIOvhPds3dBWSDZpMoqOyW/WidWGXF/ugPHzud8lDbKKhNXgA==" + }, + "@lightninglabs/lnc-web": { + "version": "0.2.6-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.6-alpha.tgz", + "integrity": "sha512-SrqR8xaDnFLgNzPe5om7REOAhSOP95jQNIHP0GY0Lv895eDjrI6CPkfCFcX97INoDWYHBvDT8DZeYkBvlznVNA==", + "requires": { + "@lightninglabs/lnc-core": "0.2.6-alpha", + "crypto-js": "4.1.1" + }, + "dependencies": { + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + } + } + }, "@next/env": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", @@ -18460,6 +18758,11 @@ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==" }, + "@noble/ciphers": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", + "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==" + }, "@noble/curves": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", @@ -18724,6 +19027,45 @@ "picomatch": "^2.2.2" } }, + "@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" + }, + "@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "requires": { + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "dependencies": { + "@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "requires": { + "@noble/hashes": "1.3.1" + } + }, + "@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==" + } + } + }, + "@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "requires": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, "@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -20716,6 +21058,11 @@ "which": "^2.0.1" } }, + "crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -23351,6 +23698,14 @@ "type-check": "~0.4.0" } }, + "light-bolt11-decoder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.0.0.tgz", + "integrity": "sha512-AKvOigD2pmC8ktnn2TIqdJu0K0qk6ukUmTvHwF3JNkm8uWCqt18Ijn33A/a7gaRZ4PghJ59X+8+MXrzLKdBTmQ==", + "requires": { + "@scure/base": "1.1.1" + } + }, "lightning": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/lightning/-/lightning-10.1.4.tgz", @@ -24674,6 +25029,34 @@ "ws": "^8.8.1" } }, + "nostr-tools": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz", + "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==", + "requires": { + "@noble/ciphers": "0.2.0", + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + }, + "dependencies": { + "@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "requires": { + "@noble/hashes": "1.3.1" + } + }, + "@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==" + } + } + }, "nprogress": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", @@ -25555,6 +25938,11 @@ "bitcoin-ops": "^1.3.0" } }, + "qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "qrcode.react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", @@ -27660,6 +28048,11 @@ "use-isomorphic-layout-effect": "^1.1.1" } }, + "use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" + }, "util": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", @@ -28355,6 +28748,14 @@ "zen-observable": "0.8.15" } }, + "zustand": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "requires": { + "use-sync-external-store": "1.2.0" + } + }, "zwitch": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz", diff --git a/package.json b/package.json index a0128cb49..ca586274d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@apollo/server": "^4.9.4", "@as-integrations/next": "^2.0.2", "@auth/prisma-adapter": "^1.0.3", + "@getalby/bitcoin-connect-react": "^2.4.3", "@graphql-tools/schema": "^10.0.0", "@noble/curves": "^1.2.0", "@opensearch-project/opensearch": "^2.4.0", From cb4a40a5de3e9b6c6dc3f2c33736ac2d8285d3ad Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 25 Dec 2023 12:09:52 +0100 Subject: [PATCH 02/12] Update major version of bitcoin-connect-react --- package-lock.json | 144 +++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 54 insertions(+), 92 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d85faaa2..283153c84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@apollo/server": "^4.9.4", "@as-integrations/next": "^2.0.2", "@auth/prisma-adapter": "^1.0.3", - "@getalby/bitcoin-connect-react": "^2.4.3", + "@getalby/bitcoin-connect-react": "^3.1.0", "@graphql-tools/schema": "^10.0.0", "@noble/curves": "^1.2.0", "@opensearch-project/opensearch": "^2.4.0", @@ -2673,36 +2673,32 @@ } }, "node_modules/@getalby/bitcoin-connect": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-2.4.3.tgz", - "integrity": "sha512-siuRiB8S1wCqmhXvxhQLvWZFwG04spfPSdOvHdWv8pDhy3ixfGRvUd9JFQ0saavGS3kueiaDZ6xTSUDJ1hY08Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-3.1.0.tgz", + "integrity": "sha512-AH/iK1HbKeW0Jl29leQZa9wclGLAPEaCVLgohjfZ2W42mrCxmOXFnXbaYYQyMwhLdXgrt2M6u7yyDY1zWH43pw==", "dependencies": { - "@getalby/lightning-tools": "^4.2.0", - "@getalby/sdk": "^2.7.0", - "@lightninglabs/lnc-web": "^0.2.6-alpha", + "@getalby/lightning-tools": "^5.0.0", + "@getalby/sdk": "^3.0.0", + "@lightninglabs/lnc-web": "^0.2.8-alpha", "qrcode-generator": "^1.4.4", "zustand": "^4.4.1" } }, "node_modules/@getalby/bitcoin-connect-react": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-2.4.3.tgz", - "integrity": "sha512-eljMNcTB4h+wlXl8DPPq3sDV6tgyQdZvW5Ka1nCAMRUCmcU4Ux7NurX2XulePPKJ/zcjigbltxrsE5gENCdqzg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-3.1.0.tgz", + "integrity": "sha512-HCptUeoL/I/vDDDadrDu+IxF7zBDDirC7CnkoTxkKoJ7WPB+mWLCvhvRuLL2V9c8GLIAQ33xdbCj55p6c/vhGw==", "dependencies": { - "@getalby/bitcoin-connect": "2.4.3" + "@getalby/bitcoin-connect": "^3.1.0" }, "peerDependencies": { "react": "^18.2.0" } }, "node_modules/@getalby/lightning-tools": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-4.2.1.tgz", - "integrity": "sha512-QOLF5LwIw6cYuAG3LYkEvZoQi/o+pFJtrG3L0koDo0xI4PliFLU9Qw70wUYJwl5X80UQtlukCpJ3nN5gyUBpdw==", - "dependencies": { - "crypto-js": "^4.1.1", - "light-bolt11-decoder": "^3.0.0" - }, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-5.0.0.tgz", + "integrity": "sha512-j3x90CGclpyZTHJRVWvA95jQniu5A+xqvmJNPSkXyzYCdJiFG5oZFWNwC0N+q7Oa8cTvp7wB7FdDqxH+Le0/Nw==", "engines": { "node": ">=14" }, @@ -2712,11 +2708,10 @@ } }, "node_modules/@getalby/sdk": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-2.7.0.tgz", - "integrity": "sha512-4NoEgdjx0R8SYDmJfCAsgvuBs0w3d8wsOMGI4m0h2MVsSeCcWW93lrzCl8bRmHTF5N7EfleHwnieYwn5j9KZTA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-3.2.2.tgz", + "integrity": "sha512-G4Ooteo/5D6SXB+y8OK8gxXWALGh4HFgq8ZqT3rBMo3FV7U/fDjf+/jn/SMsJ7ub/nEzUBBTGdfARdVoYqMvSQ==", "dependencies": { - "crypto-js": "^4.1.1", "events": "^3.3.0", "nostr-tools": "^1.17.0" }, @@ -2921,24 +2916,19 @@ } }, "node_modules/@lightninglabs/lnc-core": { - "version": "0.2.6-alpha", - "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.6-alpha.tgz", - "integrity": "sha512-bw2EQG78pPKMZMFwV+TR99RUbYgPVUKQYMLGGKIOvhPds3dBWSDZpMoqOyW/WidWGXF/ugPHzud8lDbKKhNXgA==" + "version": "0.2.8-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.8-alpha.tgz", + "integrity": "sha512-2tHzmklIiQhJiK1aabX0R2AbbWi0mizWgniCUOb573XToYQN7L61Phh+hWUCxIFfAhHCkp2mnSmX+7eT/ikxOg==" }, "node_modules/@lightninglabs/lnc-web": { - "version": "0.2.6-alpha", - "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.6-alpha.tgz", - "integrity": "sha512-SrqR8xaDnFLgNzPe5om7REOAhSOP95jQNIHP0GY0Lv895eDjrI6CPkfCFcX97INoDWYHBvDT8DZeYkBvlznVNA==", + "version": "0.2.8-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.8-alpha.tgz", + "integrity": "sha512-Pe0Moupd7mglbvbVZk7GqPNxa/4lFFWWsnYtiSahzjhNCmTaoQkk/gUY8kk1u5mHaqUmrL1YgLCLsmbGbWPV/g==", "dependencies": { - "@lightninglabs/lnc-core": "0.2.6-alpha", + "@lightninglabs/lnc-core": "0.2.8-alpha", "crypto-js": "4.1.1" } }, - "node_modules/@lightninglabs/lnc-web/node_modules/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - }, "node_modules/@next/env": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", @@ -5978,9 +5968,9 @@ } }, "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, "node_modules/crypto-random-string": { "version": "2.0.0", @@ -9638,14 +9628,6 @@ "node": ">= 0.8.0" } }, - "node_modules/light-bolt11-decoder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.0.0.tgz", - "integrity": "sha512-AKvOigD2pmC8ktnn2TIqdJu0K0qk6ukUmTvHwF3JNkm8uWCqt18Ijn33A/a7gaRZ4PghJ59X+8+MXrzLKdBTmQ==", - "dependencies": { - "@scure/base": "1.1.1" - } - }, "node_modules/lightning": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/lightning/-/lightning-10.1.4.tgz", @@ -18482,40 +18464,35 @@ "dev": true }, "@getalby/bitcoin-connect": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-2.4.3.tgz", - "integrity": "sha512-siuRiB8S1wCqmhXvxhQLvWZFwG04spfPSdOvHdWv8pDhy3ixfGRvUd9JFQ0saavGS3kueiaDZ6xTSUDJ1hY08Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect/-/bitcoin-connect-3.1.0.tgz", + "integrity": "sha512-AH/iK1HbKeW0Jl29leQZa9wclGLAPEaCVLgohjfZ2W42mrCxmOXFnXbaYYQyMwhLdXgrt2M6u7yyDY1zWH43pw==", "requires": { - "@getalby/lightning-tools": "^4.2.0", - "@getalby/sdk": "^2.7.0", - "@lightninglabs/lnc-web": "^0.2.6-alpha", + "@getalby/lightning-tools": "^5.0.0", + "@getalby/sdk": "^3.0.0", + "@lightninglabs/lnc-web": "^0.2.8-alpha", "qrcode-generator": "^1.4.4", "zustand": "^4.4.1" } }, "@getalby/bitcoin-connect-react": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-2.4.3.tgz", - "integrity": "sha512-eljMNcTB4h+wlXl8DPPq3sDV6tgyQdZvW5Ka1nCAMRUCmcU4Ux7NurX2XulePPKJ/zcjigbltxrsE5gENCdqzg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@getalby/bitcoin-connect-react/-/bitcoin-connect-react-3.1.0.tgz", + "integrity": "sha512-HCptUeoL/I/vDDDadrDu+IxF7zBDDirC7CnkoTxkKoJ7WPB+mWLCvhvRuLL2V9c8GLIAQ33xdbCj55p6c/vhGw==", "requires": { - "@getalby/bitcoin-connect": "2.4.3" + "@getalby/bitcoin-connect": "^3.1.0" } }, "@getalby/lightning-tools": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-4.2.1.tgz", - "integrity": "sha512-QOLF5LwIw6cYuAG3LYkEvZoQi/o+pFJtrG3L0koDo0xI4PliFLU9Qw70wUYJwl5X80UQtlukCpJ3nN5gyUBpdw==", - "requires": { - "crypto-js": "^4.1.1", - "light-bolt11-decoder": "^3.0.0" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@getalby/lightning-tools/-/lightning-tools-5.0.0.tgz", + "integrity": "sha512-j3x90CGclpyZTHJRVWvA95jQniu5A+xqvmJNPSkXyzYCdJiFG5oZFWNwC0N+q7Oa8cTvp7wB7FdDqxH+Le0/Nw==" }, "@getalby/sdk": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-2.7.0.tgz", - "integrity": "sha512-4NoEgdjx0R8SYDmJfCAsgvuBs0w3d8wsOMGI4m0h2MVsSeCcWW93lrzCl8bRmHTF5N7EfleHwnieYwn5j9KZTA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@getalby/sdk/-/sdk-3.2.2.tgz", + "integrity": "sha512-G4Ooteo/5D6SXB+y8OK8gxXWALGh4HFgq8ZqT3rBMo3FV7U/fDjf+/jn/SMsJ7ub/nEzUBBTGdfARdVoYqMvSQ==", "requires": { - "crypto-js": "^4.1.1", "events": "^3.3.0", "nostr-tools": "^1.17.0" } @@ -18665,24 +18642,17 @@ } }, "@lightninglabs/lnc-core": { - "version": "0.2.6-alpha", - "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.6-alpha.tgz", - "integrity": "sha512-bw2EQG78pPKMZMFwV+TR99RUbYgPVUKQYMLGGKIOvhPds3dBWSDZpMoqOyW/WidWGXF/ugPHzud8lDbKKhNXgA==" + "version": "0.2.8-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-core/-/lnc-core-0.2.8-alpha.tgz", + "integrity": "sha512-2tHzmklIiQhJiK1aabX0R2AbbWi0mizWgniCUOb573XToYQN7L61Phh+hWUCxIFfAhHCkp2mnSmX+7eT/ikxOg==" }, "@lightninglabs/lnc-web": { - "version": "0.2.6-alpha", - "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.6-alpha.tgz", - "integrity": "sha512-SrqR8xaDnFLgNzPe5om7REOAhSOP95jQNIHP0GY0Lv895eDjrI6CPkfCFcX97INoDWYHBvDT8DZeYkBvlznVNA==", + "version": "0.2.8-alpha", + "resolved": "https://registry.npmjs.org/@lightninglabs/lnc-web/-/lnc-web-0.2.8-alpha.tgz", + "integrity": "sha512-Pe0Moupd7mglbvbVZk7GqPNxa/4lFFWWsnYtiSahzjhNCmTaoQkk/gUY8kk1u5mHaqUmrL1YgLCLsmbGbWPV/g==", "requires": { - "@lightninglabs/lnc-core": "0.2.6-alpha", + "@lightninglabs/lnc-core": "0.2.8-alpha", "crypto-js": "4.1.1" - }, - "dependencies": { - "crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - } } }, "@next/env": { @@ -21059,9 +21029,9 @@ } }, "crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, "crypto-random-string": { "version": "2.0.0", @@ -23698,14 +23668,6 @@ "type-check": "~0.4.0" } }, - "light-bolt11-decoder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/light-bolt11-decoder/-/light-bolt11-decoder-3.0.0.tgz", - "integrity": "sha512-AKvOigD2pmC8ktnn2TIqdJu0K0qk6ukUmTvHwF3JNkm8uWCqt18Ijn33A/a7gaRZ4PghJ59X+8+MXrzLKdBTmQ==", - "requires": { - "@scure/base": "1.1.1" - } - }, "lightning": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/lightning/-/lightning-10.1.4.tgz", diff --git a/package.json b/package.json index ca586274d..f3c751e19 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@apollo/server": "^4.9.4", "@as-integrations/next": "^2.0.2", "@auth/prisma-adapter": "^1.0.3", - "@getalby/bitcoin-connect-react": "^2.4.3", + "@getalby/bitcoin-connect-react": "^3.1.0", "@graphql-tools/schema": "^10.0.0", "@noble/curves": "^1.2.0", "@opensearch-project/opensearch": "^2.4.0", From 238d5821c5a23a978ab996b498c136e3f3440fc8 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 26 Dec 2023 14:24:02 +0100 Subject: [PATCH 03/12] Show default wallet connect button in /wallet --- pages/wallet.js | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pages/wallet.js b/pages/wallet.js index 9a3fcf4e8..39b795902 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -28,6 +28,7 @@ import { useShowModal } from '../components/modal' import { useField } from 'formik' import { useToast } from '../components/toast' import { WalletLimitBanner } from '../components/banners' +import dynamic from 'next/dynamic' export const getServerSideProps = getGetServerSideProps({ authRequired: true }) @@ -85,17 +86,35 @@ function WalletHistory () { export function WalletForm () { return (
- - - - or - - - +
+ + + + or + + + +
+
+ +
) } +const WalletConnectButton = dynamic( + () => import('@getalby/bitcoin-connect-react').then((mod) => mod.Button), + { + ssr: false + } +) + +function WalletConnect () { + return ( + + ) +} + export function FundForm () { const me = useMe() const [showAlert, setShowAlert] = useState(true) From 375d98b71179e10e792b05aec9dc17ec917bc188 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 26 Dec 2023 18:43:21 +0100 Subject: [PATCH 04/12] Use custom button to open modal --- pages/wallet.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pages/wallet.js b/pages/wallet.js index 39b795902..2d53ed7d4 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -28,7 +28,6 @@ import { useShowModal } from '../components/modal' import { useField } from 'formik' import { useToast } from '../components/toast' import { WalletLimitBanner } from '../components/banners' -import dynamic from 'next/dynamic' export const getServerSideProps = getGetServerSideProps({ authRequired: true }) @@ -102,16 +101,17 @@ export function WalletForm () { ) } -const WalletConnectButton = dynamic( - () => import('@getalby/bitcoin-connect-react').then((mod) => mod.Button), - { - ssr: false - } -) - function WalletConnect () { return ( - + ) } From ba05fbbbd1c9f3d3dc74b06d9bed74b5c3570e24 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 26 Dec 2023 20:49:33 +0100 Subject: [PATCH 05/12] Save provider in WebLN context * created WebLNContext * added weblnSats local ield with @client directive including local field resolver * sum sats (custodial + webLN) --- components/header.js | 3 +- components/hidden-wallet-summary.js | 4 +- components/me.js | 4 ++ components/webln.js | 106 ++++++++++++++++++++++++++++ fragments/users.js | 1 + lib/apollo.js | 9 +++ pages/_app.js | 51 ++++++------- pages/wallet.js | 31 +++++--- 8 files changed, 173 insertions(+), 36 deletions(-) create mode 100644 components/webln.js diff --git a/components/header.js b/components/header.js index 079ee0998..bedb8810a 100644 --- a/components/header.js +++ b/components/header.js @@ -33,7 +33,8 @@ function WalletSummary ({ me }) { if (me.privates?.hideWalletBalance) { return } - return `${abbrNum(me.privates?.sats)}` + const sats = me.privates?.sats + me.weblnSats + return `${abbrNum(sats)}` } function Back () { diff --git a/components/hidden-wallet-summary.js b/components/hidden-wallet-summary.js index 161f03b31..59ee1e7c5 100644 --- a/components/hidden-wallet-summary.js +++ b/components/hidden-wallet-summary.js @@ -13,12 +13,14 @@ export default function HiddenWalletSummary ({ abbreviate, fixedWidth }) { setWidth(ref.current?.offsetWidth) }, []) + const sats = me.privates?.sats + me.weblnSats + return ( setHover(true)} onPointerLeave={() => setHover(false)} > - {hover ? (abbreviate ? abbrNum(me.privates?.sats) : numWithUnits(me.privates?.sats, { abbreviate: false, format: true })) : '******'} + {hover ? (abbreviate ? abbrNum(sats) : numWithUnits(sats, { abbreviate: false, format: true })) : '******'} ) } diff --git a/components/me.js b/components/me.js index d3d61fae2..686846848 100644 --- a/components/me.js +++ b/components/me.js @@ -10,6 +10,10 @@ export const MeContext = React.createContext({ export function MeProvider ({ me, children }) { const { data } = useQuery(ME, SSR ? {} : { pollInterval: 1000, nextFetchPolicy: 'cache-and-network' }) + const futureMe = data?.me || me + // weblnSats is initially undefined on page load for some reason + if (futureMe.weblnSats === undefined) futureMe.weblnSats = 0 + return ( {children} diff --git a/components/webln.js b/components/webln.js new file mode 100644 index 000000000..ecc7aee6a --- /dev/null +++ b/components/webln.js @@ -0,0 +1,106 @@ +import { createContext, createRef, useContext, useEffect, useImperativeHandle, useState } from 'react' + +const WebLNContext = createContext({}) +export const WebLNContextRef = createRef() + +const fetchWebLNProvider = async () => { + // sync provider from local storage + // TODO check if there is a better, more secure option + const configJson = window.localStorage.getItem('bc:config') + if (configJson) { + const WebLNProviders = await import('@getalby/bitcoin-connect').then((mod) => mod.WebLNProviders) + const config = JSON.parse(configJson) + if (config.connectorType === 'lnbits') return new WebLNProviders.LnbitsWebLNProvider(config.lnbitsInstanceUrl, config.lnbitsAdminKey) + // TODO implement other connector types + } +} + +export function WebLNProvider ({ children }) { + const [provider, setProvider] = useState(null) + const [info, setInfo] = useState(null) + const [balance, setBalance] = useState(0) + + const initProvider = async (provider) => { + const WebLNProviders = await import('@getalby/bitcoin-connect').then((mod) => mod.WebLNProviders) + if (provider instanceof WebLNProviders.LnbitsWebLNProvider) { + const connector = 'lnbits' + // TODO + // we're reaching into private parts here. + // is there a better way to show to user which connection was used? + const { hostname: connection } = new URL(provider._instanceUrl) + setInfo(o => ({ ...o, connector, connection })) + } + setProvider(provider) + const info = await provider.getInfo() + setInfo(o => ({ ...o, ...info })) + const { balance } = await provider.getBalance() + setBalance(balance) + } + + const clearProvider = () => { + setProvider(null) + setInfo(null) + } + + useEffect(() => { + async function effect () { + const provider = await fetchWebLNProvider() + if (!provider) return + initProvider(provider) + } + effect().catch(console.error) + }, []) + + // event listeners + useEffect(() => { + let onConnectedUnsub + let onDisconnectedUnsub + async function effect () { + const onConnected = await import('@getalby/bitcoin-connect-react').then((mod) => mod.onConnected) + onConnectedUnsub = onConnected(async (provider) => { + // TODO + // why is this not fired on page load when there is a provider available in local storage? + // why do i have to do this myself? + // console.log('webln:: connected', provider) + // TODO do we need this? + // window.webln = provider + initProvider(provider) + }) + const onDisconnected = await import('@getalby/bitcoin-connect-react').then((mod) => mod.onDisconnected) + onDisconnectedUnsub = onDisconnected(() => { + // console.log('webln:: disconnected') + clearProvider() + }) + } + effect().catch(console.error) + return () => { + onConnectedUnsub?.() + onDisconnectedUnsub?.() + } + }, []) + + // poll balance + useEffect(() => { + if (!provider) return + const BALANCE_POLL = 15000 // 1 minute + const interval = setInterval(() => { + provider?.getBalance().then(({ balance }) => setBalance(balance)).catch(console.error) + }, BALANCE_POLL) + return () => clearInterval(interval) + }, [provider]) + + const value = { provider, setProvider, info, balance } + + // required to resolve fields marked with @client using values from WebLN context + useImperativeHandle(WebLNContextRef, () => value) + + return ( + + {children} + + ) +} + +export function useWebLN () { + return useContext(WebLNContext) +} diff --git a/fragments/users.js b/fragments/users.js index 0aee792c9..166731efc 100644 --- a/fragments/users.js +++ b/fragments/users.js @@ -8,6 +8,7 @@ export const ME = gql` id name bioId + weblnSats @client privates { autoDropBolt11s diagnostics diff --git a/lib/apollo.js b/lib/apollo.js index d8f45a2fb..ce385dc2b 100644 --- a/lib/apollo.js +++ b/lib/apollo.js @@ -1,6 +1,7 @@ import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client' import { decodeCursor, LIMIT } from './cursor' import { SSR } from './constants' +import { WebLNContextRef } from '../components/webln' function isFirstPage (cursor, existingThings, limit = LIMIT) { if (cursor) { @@ -188,6 +189,14 @@ function getClient (uri) { } } }), + resolvers: { + User: { + weblnSats: (user, args, { cache }) => { + const balance = WebLNContextRef.current?.balance + return balance + } + } + }, assumeImmutableResults: true, defaultOptions: { watchQuery: { diff --git a/pages/_app.js b/pages/_app.js index 8966f2bb8..d4e58d7e0 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -18,6 +18,7 @@ import NProgress from 'nprogress' import 'nprogress/nprogress.css' import { LoggerProvider } from '../components/logger' import { ChainFeeProvider } from '../components/chain-fee.js' +import { WebLNProvider } from '../components/webln' import dynamic from 'next/dynamic' const PWAPrompt = dynamic(() => import('react-ios-pwa-prompt'), { ssr: false }) @@ -91,30 +92,32 @@ export default function MyApp ({ Component, pageProps: { ...props } }) { - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pages/wallet.js b/pages/wallet.js index 2d53ed7d4..53cd17aa3 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -28,6 +28,7 @@ import { useShowModal } from '../components/modal' import { useField } from 'formik' import { useToast } from '../components/toast' import { WalletLimitBanner } from '../components/banners' +import { useWebLN } from '../components/webln' export const getServerSideProps = getGetServerSideProps({ authRequired: true }) @@ -67,7 +68,7 @@ function YouHaveSats () { {me && ( me.privates?.hideWalletBalance ? - : numWithUnits(me.privates?.sats, { abbreviate: false, format: true }) + : numWithUnits(me.privates?.sats + me.weblnSats, { abbreviate: false, format: true }) )} @@ -102,16 +103,26 @@ export function WalletForm () { } function WalletConnect () { + const { provider, info } = useWebLN() + const [label, setLabel] = useState('connect wallet') + + useEffect(() => { + setLabel(provider ? 'connected' : 'connect wallet') + }, [provider]) + return ( - + <> + + {info?.connection &&
{info.connection}
} + ) } From d9a79af188aea379b5f5975a5cb94e75873d59dd Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 28 Dec 2023 02:28:29 +0100 Subject: [PATCH 06/12] Use context provider to pay invoices --- components/qr.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/qr.js b/components/qr.js index 5a7f866a9..2ea56f1dd 100644 --- a/components/qr.js +++ b/components/qr.js @@ -1,18 +1,23 @@ import QRCode from 'qrcode.react' import { CopyInput, InputSkeleton } from './form' import InvoiceStatus from './invoice-status' -import { requestProvider } from 'webln' import { useEffect } from 'react' +import { useWebLN } from './webln' export default function Qr ({ asIs, value, webLn, statusVariant, description, status }) { const qrValue = asIs ? value : 'lightning:' + value.toUpperCase() + const { provider } = useWebLN() useEffect(() => { async function effect () { if (webLn) { try { - const provider = await requestProvider() - await provider.sendPayment(value) + if (provider) { + // TODO in strict mode, this tries to pay the invoice twice + // so an error is logged to the console for the second attempt. + // but the payment still succeeds. (only tested with LNbits so far) + await provider.sendPayment(value) + } } catch (e) { console.log(e.message) } From fcdb58538797e3b42169ce6c5e1ea7524e70ff4a Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 28 Dec 2023 03:13:16 +0100 Subject: [PATCH 07/12] Set balance to 0 on disconnect --- components/webln.js | 1 + 1 file changed, 1 insertion(+) diff --git a/components/webln.js b/components/webln.js index ecc7aee6a..6b8bb4134 100644 --- a/components/webln.js +++ b/components/webln.js @@ -40,6 +40,7 @@ export function WebLNProvider ({ children }) { const clearProvider = () => { setProvider(null) setInfo(null) + setBalance(0) } useEffect(() => { From 6d28b428f12e95ea47fcd2df328d2ff6afbfcc5d Mon Sep 17 00:00:00 2001 From: ekzyis Date: Thu, 28 Dec 2023 03:14:18 +0100 Subject: [PATCH 08/12] Add more TODO comments --- components/webln.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/webln.js b/components/webln.js index 6b8bb4134..72f4c52de 100644 --- a/components/webln.js +++ b/components/webln.js @@ -81,9 +81,11 @@ export function WebLNProvider ({ children }) { }, []) // poll balance + // TODO is there a better way? useEffect(() => { if (!provider) return - const BALANCE_POLL = 15000 // 1 minute + // TODO check rate limiting of services - is every 15 seconds too often? (it probably is) + const BALANCE_POLL = 15000 // 15 seconds const interval = setInterval(() => { provider?.getBalance().then(({ balance }) => setBalance(balance)).catch(console.error) }, BALANCE_POLL) From f1bf5ddb3ad99427c3a755db140abdf398247dc5 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 30 Dec 2023 22:50:47 +0100 Subject: [PATCH 09/12] Remove reliance on get_balance --- components/header.js | 3 +-- components/hidden-wallet-summary.js | 4 +--- components/me.js | 4 ---- components/webln.js | 25 ++----------------------- fragments/users.js | 1 - lib/apollo.js | 9 --------- pages/wallet.js | 2 +- 7 files changed, 5 insertions(+), 43 deletions(-) diff --git a/components/header.js b/components/header.js index bedb8810a..079ee0998 100644 --- a/components/header.js +++ b/components/header.js @@ -33,8 +33,7 @@ function WalletSummary ({ me }) { if (me.privates?.hideWalletBalance) { return } - const sats = me.privates?.sats + me.weblnSats - return `${abbrNum(sats)}` + return `${abbrNum(me.privates?.sats)}` } function Back () { diff --git a/components/hidden-wallet-summary.js b/components/hidden-wallet-summary.js index 59ee1e7c5..161f03b31 100644 --- a/components/hidden-wallet-summary.js +++ b/components/hidden-wallet-summary.js @@ -13,14 +13,12 @@ export default function HiddenWalletSummary ({ abbreviate, fixedWidth }) { setWidth(ref.current?.offsetWidth) }, []) - const sats = me.privates?.sats + me.weblnSats - return ( setHover(true)} onPointerLeave={() => setHover(false)} > - {hover ? (abbreviate ? abbrNum(sats) : numWithUnits(sats, { abbreviate: false, format: true })) : '******'} + {hover ? (abbreviate ? abbrNum(me.privates?.sats) : numWithUnits(me.privates?.sats, { abbreviate: false, format: true })) : '******'} ) } diff --git a/components/me.js b/components/me.js index 686846848..d3d61fae2 100644 --- a/components/me.js +++ b/components/me.js @@ -10,10 +10,6 @@ export const MeContext = React.createContext({ export function MeProvider ({ me, children }) { const { data } = useQuery(ME, SSR ? {} : { pollInterval: 1000, nextFetchPolicy: 'cache-and-network' }) - const futureMe = data?.me || me - // weblnSats is initially undefined on page load for some reason - if (futureMe.weblnSats === undefined) futureMe.weblnSats = 0 - return ( {children} diff --git a/components/webln.js b/components/webln.js index 72f4c52de..b1835485a 100644 --- a/components/webln.js +++ b/components/webln.js @@ -1,7 +1,6 @@ -import { createContext, createRef, useContext, useEffect, useImperativeHandle, useState } from 'react' +import { createContext, useContext, useEffect, useState } from 'react' const WebLNContext = createContext({}) -export const WebLNContextRef = createRef() const fetchWebLNProvider = async () => { // sync provider from local storage @@ -18,7 +17,6 @@ const fetchWebLNProvider = async () => { export function WebLNProvider ({ children }) { const [provider, setProvider] = useState(null) const [info, setInfo] = useState(null) - const [balance, setBalance] = useState(0) const initProvider = async (provider) => { const WebLNProviders = await import('@getalby/bitcoin-connect').then((mod) => mod.WebLNProviders) @@ -33,14 +31,11 @@ export function WebLNProvider ({ children }) { setProvider(provider) const info = await provider.getInfo() setInfo(o => ({ ...o, ...info })) - const { balance } = await provider.getBalance() - setBalance(balance) } const clearProvider = () => { setProvider(null) setInfo(null) - setBalance(0) } useEffect(() => { @@ -80,23 +75,7 @@ export function WebLNProvider ({ children }) { } }, []) - // poll balance - // TODO is there a better way? - useEffect(() => { - if (!provider) return - // TODO check rate limiting of services - is every 15 seconds too often? (it probably is) - const BALANCE_POLL = 15000 // 15 seconds - const interval = setInterval(() => { - provider?.getBalance().then(({ balance }) => setBalance(balance)).catch(console.error) - }, BALANCE_POLL) - return () => clearInterval(interval) - }, [provider]) - - const value = { provider, setProvider, info, balance } - - // required to resolve fields marked with @client using values from WebLN context - useImperativeHandle(WebLNContextRef, () => value) - + const value = { provider, setProvider, info } return ( {children} diff --git a/fragments/users.js b/fragments/users.js index 166731efc..0aee792c9 100644 --- a/fragments/users.js +++ b/fragments/users.js @@ -8,7 +8,6 @@ export const ME = gql` id name bioId - weblnSats @client privates { autoDropBolt11s diagnostics diff --git a/lib/apollo.js b/lib/apollo.js index ce385dc2b..d8f45a2fb 100644 --- a/lib/apollo.js +++ b/lib/apollo.js @@ -1,7 +1,6 @@ import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client' import { decodeCursor, LIMIT } from './cursor' import { SSR } from './constants' -import { WebLNContextRef } from '../components/webln' function isFirstPage (cursor, existingThings, limit = LIMIT) { if (cursor) { @@ -189,14 +188,6 @@ function getClient (uri) { } } }), - resolvers: { - User: { - weblnSats: (user, args, { cache }) => { - const balance = WebLNContextRef.current?.balance - return balance - } - } - }, assumeImmutableResults: true, defaultOptions: { watchQuery: { diff --git a/pages/wallet.js b/pages/wallet.js index 53cd17aa3..e951b8092 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -68,7 +68,7 @@ function YouHaveSats () { {me && ( me.privates?.hideWalletBalance ? - : numWithUnits(me.privates?.sats + me.weblnSats, { abbreviate: false, format: true }) + : numWithUnits(me.privates?.sats, { abbreviate: false, format: true }) )} From e06e86265c94b5725f503a9d52e87d18ec57ad59 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 31 Dec 2023 19:08:19 +0100 Subject: [PATCH 10/12] Check isConnected to init provider without prompt --- components/webln.js | 88 ++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 65 deletions(-) diff --git a/components/webln.js b/components/webln.js index b1835485a..2046de27c 100644 --- a/components/webln.js +++ b/components/webln.js @@ -2,80 +2,38 @@ import { createContext, useContext, useEffect, useState } from 'react' const WebLNContext = createContext({}) -const fetchWebLNProvider = async () => { - // sync provider from local storage - // TODO check if there is a better, more secure option - const configJson = window.localStorage.getItem('bc:config') - if (configJson) { - const WebLNProviders = await import('@getalby/bitcoin-connect').then((mod) => mod.WebLNProviders) - const config = JSON.parse(configJson) - if (config.connectorType === 'lnbits') return new WebLNProviders.LnbitsWebLNProvider(config.lnbitsInstanceUrl, config.lnbitsAdminKey) - // TODO implement other connector types - } -} - export function WebLNProvider ({ children }) { const [provider, setProvider] = useState(null) const [info, setInfo] = useState(null) - const initProvider = async (provider) => { - const WebLNProviders = await import('@getalby/bitcoin-connect').then((mod) => mod.WebLNProviders) - if (provider instanceof WebLNProviders.LnbitsWebLNProvider) { - const connector = 'lnbits' - // TODO - // we're reaching into private parts here. - // is there a better way to show to user which connection was used? - const { hostname: connection } = new URL(provider._instanceUrl) - setInfo(o => ({ ...o, connector, connection })) - } - setProvider(provider) - const info = await provider.getInfo() - setInfo(o => ({ ...o, ...info })) - } - - const clearProvider = () => { - setProvider(null) - setInfo(null) - } - useEffect(() => { + const unsub = [] async function effect () { - const provider = await fetchWebLNProvider() - if (!provider) return - initProvider(provider) + const [isConnected, onConnected, onDisconnected, requestProvider] = await import('@getalby/bitcoin-connect-react').then( + (mod) => [mod.isConnected, mod.onConnected, mod.onDisconnected, mod.requestProvider] + ) + if (isConnected()) { + // requestProvider will not launch a modal because a provider is already available. + // TODO but it might for wallets that must be unlocked? + const provider = await requestProvider() + setProvider(provider) + } + unsub.push(onConnected(async (provider) => { + setProvider(provider) + const info = await provider.getInfo() + setInfo(info) + })) + unsub.push(onDisconnected(() => { + setProvider(null) + setInfo(null) + })) } - effect().catch(console.error) - }, []) + effect() - // event listeners - useEffect(() => { - let onConnectedUnsub - let onDisconnectedUnsub - async function effect () { - const onConnected = await import('@getalby/bitcoin-connect-react').then((mod) => mod.onConnected) - onConnectedUnsub = onConnected(async (provider) => { - // TODO - // why is this not fired on page load when there is a provider available in local storage? - // why do i have to do this myself? - // console.log('webln:: connected', provider) - // TODO do we need this? - // window.webln = provider - initProvider(provider) - }) - const onDisconnected = await import('@getalby/bitcoin-connect-react').then((mod) => mod.onDisconnected) - onDisconnectedUnsub = onDisconnected(() => { - // console.log('webln:: disconnected') - clearProvider() - }) - } - effect().catch(console.error) - return () => { - onConnectedUnsub?.() - onDisconnectedUnsub?.() - } - }, []) + return () => unsub.forEach(fn => fn()) + }, [setProvider]) - const value = { provider, setProvider, info } + const value = { provider, info } return ( {children} From 59008b7673b20c61b0d81ce12a1af79ab4d5803d Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 1 Jan 2024 17:52:38 +0100 Subject: [PATCH 11/12] Wrap bitcoin-connect imports in WebLN context --- components/webln.js | 13 ++++++++++--- pages/wallet.js | 7 ++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/components/webln.js b/components/webln.js index 2046de27c..b04f3af73 100644 --- a/components/webln.js +++ b/components/webln.js @@ -5,13 +5,20 @@ const WebLNContext = createContext({}) export function WebLNProvider ({ children }) { const [provider, setProvider] = useState(null) const [info, setInfo] = useState(null) + // NOTE launchModal is undefined initially - can this be a problem? + const [launchModal, setLaunchModal] = useState() useEffect(() => { const unsub = [] async function effect () { - const [isConnected, onConnected, onDisconnected, requestProvider] = await import('@getalby/bitcoin-connect-react').then( - (mod) => [mod.isConnected, mod.onConnected, mod.onDisconnected, mod.requestProvider] + const [isConnected, onConnected, onDisconnected, requestProvider, launchModal] = await import('@getalby/bitcoin-connect-react').then( + (mod) => [mod.isConnected, mod.onConnected, mod.onDisconnected, mod.requestProvider, mod.launchModal] ) + + // if you want to store a function, you need to wrap it with another function because of updater functions + // see https://react.dev/reference/react/useState#updating-state-based-on-the-previous-state + setLaunchModal(() => launchModal) + if (isConnected()) { // requestProvider will not launch a modal because a provider is already available. // TODO but it might for wallets that must be unlocked? @@ -33,7 +40,7 @@ export function WebLNProvider ({ children }) { return () => unsub.forEach(fn => fn()) }, [setProvider]) - const value = { provider, info } + const value = { provider, info, launchModal } return ( {children} diff --git a/pages/wallet.js b/pages/wallet.js index e951b8092..9663ea5ed 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -103,7 +103,7 @@ export function WalletForm () { } function WalletConnect () { - const { provider, info } = useWebLN() + const { provider, info, launchModal } = useWebLN() const [label, setLabel] = useState('connect wallet') useEffect(() => { @@ -115,10 +115,7 @@ function WalletConnect () { {info?.connection &&
{info.connection}
} From 6ae338208bb1cdb3fbc91666b0585c3b2b826877 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 1 Jan 2024 21:39:20 +0100 Subject: [PATCH 12/12] Expose more bitcoin-connect functions via WebLN context --- components/webln.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/components/webln.js b/components/webln.js index b04f3af73..c42b5359d 100644 --- a/components/webln.js +++ b/components/webln.js @@ -5,19 +5,25 @@ const WebLNContext = createContext({}) export function WebLNProvider ({ children }) { const [provider, setProvider] = useState(null) const [info, setInfo] = useState(null) - // NOTE launchModal is undefined initially - can this be a problem? + // NOTE these functions are undefined initially - can this be a problem? const [launchModal, setLaunchModal] = useState() + const [launchPaymentModal, setLaunchPaymentModal] = useState() + const [closeModal, setCloseModal] = useState() + const [isConnected, setIsConnected] = useState() useEffect(() => { const unsub = [] async function effect () { - const [isConnected, onConnected, onDisconnected, requestProvider, launchModal] = await import('@getalby/bitcoin-connect-react').then( - (mod) => [mod.isConnected, mod.onConnected, mod.onDisconnected, mod.requestProvider, mod.launchModal] + const [isConnected, onConnected, onDisconnected, requestProvider, launchModal, launchPaymentModal, closeModal] = await import('@getalby/bitcoin-connect-react').then( + (mod) => [mod.isConnected, mod.onConnected, mod.onDisconnected, mod.requestProvider, mod.launchModal, mod.launchPaymentModal, mod.closeModal] ) // if you want to store a function, you need to wrap it with another function because of updater functions // see https://react.dev/reference/react/useState#updating-state-based-on-the-previous-state setLaunchModal(() => launchModal) + setLaunchPaymentModal(() => launchPaymentModal) + setCloseModal(() => closeModal) + setIsConnected(() => isConnected) if (isConnected()) { // requestProvider will not launch a modal because a provider is already available. @@ -40,7 +46,7 @@ export function WebLNProvider ({ children }) { return () => unsub.forEach(fn => fn()) }, [setProvider]) - const value = { provider, info, launchModal } + const value = { provider, info, launchModal, launchPaymentModal, closeModal, isConnected } return ( {children}