diff --git a/package.json b/package.json index 6536c77..1526d9a 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@fastify/view": "^8.2.0", "@inquirer/password": "^1.1.2", "@inquirer/prompts": "^1.2.3", + "@nostr-dev-kit/ndk": "3.0.3", "@prisma/client": "^6.19.0", "@scure/base": "^1.1.1", "@types/yargs": "^17.0.24", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57877fa..ae755ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@inquirer/prompts': specifier: ^1.2.3 version: 1.2.3 + '@nostr-dev-kit/ndk': + specifier: 3.0.3 + version: 3.0.3(nostr-tools@2.20.0(typescript@5.9.3)) '@prisma/client': specifier: ^6.19.0 version: 6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3) @@ -105,6 +108,12 @@ importers: packages: + '@codesandbox/nodebox@0.1.8': + resolution: {integrity: sha512-2VRS6JDSk+M+pg56GA6CryyUSGPjBEe8Pnae0QL3jJF1mJZJVMDKr93gJRtBbLkfZN6LD/DwMtf+2L0bpWrjqg==} + + '@codesandbox/sandpack-client@2.19.8': + resolution: {integrity: sha512-CMV4nr1zgKzVpx4I3FYvGRM5YT0VaQhALMW9vy4wZRhEyWAtJITQIqZzrTGWqB1JvV7V72dVEUCUPLfYz5hgJQ==} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -400,6 +409,10 @@ packages: '@noble/curves@1.2.0': resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + '@noble/curves@1.9.7': + resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} + engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.3.1': resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} engines: {node: '>= 16'} @@ -408,6 +421,13 @@ packages: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@noble/secp256k1@2.3.0': + resolution: {integrity: sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -420,6 +440,15 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@nostr-dev-kit/ndk@3.0.3': + resolution: {integrity: sha512-wGQOnvpKjhkq/j0pnRGTiHyrujww7N/iJQKOBrjsIxqTvcy6iyqh/3TijTKlaapdvexx2E2xCn9X+q0dxxISug==} + engines: {node: '>=16'} + peerDependencies: + nostr-tools: ^2.17.2 + + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} @@ -487,79 +516,66 @@ packages: resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.4': resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.4': resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.4': resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.4': resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.4': resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.4': resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.4': resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.4': resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.4': resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.4': resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.4': resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.4': resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.60.4': resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} @@ -606,6 +622,27 @@ packages: '@scure/bip39@1.2.1': resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} + '@shikijs/core@3.23.0': + resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} + + '@shikijs/engine-javascript@3.23.0': + resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -630,12 +667,18 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -648,6 +691,9 @@ packages: '@types/node@20.19.41': resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/wrap-ansi@3.0.0': resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} @@ -657,6 +703,9 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + '@ungap/structured-clone@1.3.1': + resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} + abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} @@ -798,6 +847,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bcrypt@5.1.1: resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} engines: {node: '>= 10.0.0'} @@ -817,6 +869,9 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bufferutil@4.1.0: resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} engines: {node: '>=6.14.2'} @@ -859,10 +914,19 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -911,6 +975,9 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1023,6 +1090,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + destr@2.0.5: resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} @@ -1034,6 +1105,9 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff@4.0.4: resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} @@ -1474,6 +1548,15 @@ packages: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -1490,6 +1573,9 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1681,6 +1767,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + light-bolt11-decoder@3.2.0: + resolution: {integrity: sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ==} + light-my-request@5.14.0: resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} @@ -1722,6 +1811,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -1740,6 +1832,21 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -1748,6 +1855,10 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} @@ -1916,6 +2027,12 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1924,6 +2041,9 @@ packages: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} + outvariant@1.4.0: + resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -2033,6 +2153,9 @@ packages: process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -2089,6 +2212,15 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + regexp.prototype.flags@1.5.4: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} @@ -2216,6 +2348,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shiki@3.23.0: + resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} + side-channel-list@1.0.1: resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} engines: {node: '>= 0.4'} @@ -2255,10 +2390,16 @@ packages: engines: {node: '>= 8'} deprecated: The work that was done in this beta branch won't be included in future versions + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + static-browser-server@1.0.3: + resolution: {integrity: sha512-ZUyfgGDdFRbZGGJQ1YhiM930Yczz5VlbJObrQLlk24+qNHVQx4OlLcYswEUo3bIyNAbQUIUR9Yr5/Hqjzqb4zA==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -2267,6 +2408,9 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + strict-event-emitter@0.4.6: + resolution: {integrity: sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2286,6 +2430,9 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2364,6 +2511,9 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -2384,6 +2534,9 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + tseep@1.3.1: + resolution: {integrity: sha512-ZPtfk1tQnZVyr7BPtbJ93qaAh2lZuIOpTMjhrYa4XctT8xe7t4SAW9LIxrySDuYMsfNNayE51E/WNGrNVgVicQ==} + tstl@2.5.16: resolution: {integrity: sha512-+O2ybLVLKcBwKm4HymCEwZIT0PpwS3gCYnxfSDEjJEKADvIFruaQjd3m7CAKNU1c7N3X3WjVz87re7TA2A5FUw==} @@ -2438,6 +2591,9 @@ packages: typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + typescript-lru-cache@2.0.0: + resolution: {integrity: sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA==} + typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} engines: {node: '>=4.2.0'} @@ -2463,6 +2619,21 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -2488,6 +2659,12 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -2594,8 +2771,25 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: + '@codesandbox/nodebox@0.1.8': + dependencies: + outvariant: 1.4.0 + strict-event-emitter: 0.4.6 + + '@codesandbox/sandpack-client@2.19.8': + dependencies: + '@codesandbox/nodebox': 0.1.8 + buffer: 6.0.3 + dequal: 2.0.3 + mime-db: 1.54.0 + outvariant: 1.4.0 + static-browser-server: 1.0.3 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -2903,10 +3097,18 @@ snapshots: dependencies: '@noble/hashes': 1.3.2 + '@noble/curves@1.9.7': + dependencies: + '@noble/hashes': 1.8.0 + '@noble/hashes@1.3.1': {} '@noble/hashes@1.3.2': {} + '@noble/hashes@1.8.0': {} + + '@noble/secp256k1@2.3.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2919,6 +3121,24 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@nostr-dev-kit/ndk@3.0.3(nostr-tools@2.20.0(typescript@5.9.3))': + dependencies: + '@codesandbox/sandpack-client': 2.19.8 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@noble/secp256k1': 2.3.0 + '@scure/base': 1.2.6 + debug: 4.4.3 + light-bolt11-decoder: 3.2.0 + nostr-tools: 2.20.0(typescript@5.9.3) + shiki: 3.23.0 + tseep: 1.3.1 + typescript-lru-cache: 2.0.0 + transitivePeerDependencies: + - supports-color + + '@open-draft/deferred-promise@2.2.0': {} + '@pinojs/redact@0.4.0': {} '@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3)': @@ -3048,6 +3268,39 @@ snapshots: '@noble/hashes': 1.3.1 '@scure/base': 1.1.1 + '@shikijs/core@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + '@standard-schema/spec@1.1.0': {} '@tsconfig/node10@1.0.12': {} @@ -3066,10 +3319,18 @@ snapshots: '@types/estree@1.0.9': {} + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + '@types/ms@2.1.0': {} '@types/mute-stream@0.0.4': @@ -3084,6 +3345,8 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/unist@3.0.3': {} + '@types/wrap-ansi@3.0.0': {} '@types/yargs-parser@21.0.3': {} @@ -3092,6 +3355,8 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 + '@ungap/structured-clone@1.3.1': {} + abbrev@1.1.1: {} abstract-logging@2.0.1: {} @@ -3254,6 +3519,8 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + bcrypt@5.1.1: dependencies: '@mapbox/node-pre-gyp': 1.0.11 @@ -3290,6 +3557,11 @@ snapshots: dependencies: fill-range: 7.1.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bufferutil@4.1.0: dependencies: node-gyp-build: 4.8.4 @@ -3337,11 +3609,17 @@ snapshots: callsites@3.1.0: {} + ccount@2.0.1: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + chardet@0.7.0: {} chokidar@3.6.0: @@ -3390,6 +3668,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} + commander@4.1.1: {} concat-map@0.0.1: {} @@ -3479,12 +3759,18 @@ snapshots: depd@2.0.0: {} + dequal@2.0.3: {} + destr@2.0.5: {} destroy@1.2.0: {} detect-libc@2.1.2: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + diff@4.0.4: {} dir-glob@3.0.1: @@ -4116,6 +4402,26 @@ snapshots: dependencies: function-bind: 1.1.2 + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + html-void-elements@3.0.0: {} + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -4137,6 +4443,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + ignore@5.3.2: {} import-fresh@3.3.1: @@ -4320,6 +4628,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + light-bolt11-decoder@3.2.0: + dependencies: + '@scure/base': 1.1.1 + light-my-request@5.14.0: dependencies: cookie: 0.7.2 @@ -4362,6 +4674,18 @@ snapshots: math-intrinsics@1.1.0: {} + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.1 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + media-typer@0.3.0: {} merge-descriptors@1.0.3: {} @@ -4372,6 +4696,23 @@ snapshots: methods@1.1.2: {} + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -4379,6 +4720,8 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 @@ -4538,6 +4881,14 @@ snapshots: dependencies: mimic-fn: 2.1.0 + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4549,6 +4900,8 @@ snapshots: os-tmpdir@1.0.2: {} + outvariant@1.4.0: {} + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -4641,6 +4994,8 @@ snapshots: process-warning@5.0.0: {} + property-information@7.1.0: {} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -4699,6 +5054,16 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.9 @@ -4868,6 +5233,17 @@ snapshots: shebang-regex@3.0.0: {} + shiki@3.23.0: + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/engine-javascript': 3.23.0 + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + side-channel-list@1.0.1: dependencies: es-errors: 1.3.0 @@ -4912,8 +5288,17 @@ snapshots: dependencies: whatwg-url: 7.1.0 + space-separated-tokens@2.0.2: {} + split2@4.2.0: {} + static-browser-server@1.0.3: + dependencies: + '@open-draft/deferred-promise': 2.2.0 + dotenv: 16.6.1 + mime-db: 1.54.0 + outvariant: 1.4.0 + statuses@2.0.2: {} stop-iteration-iterator@1.1.0: @@ -4921,6 +5306,8 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 + strict-event-emitter@0.4.6: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -4954,6 +5341,11 @@ snapshots: dependencies: safe-buffer: 5.2.1 + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -5028,6 +5420,8 @@ snapshots: tree-kill@1.2.2: {} + trim-lines@3.0.1: {} + ts-interface-checker@0.1.13: {} ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3): @@ -5055,6 +5449,8 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tseep@1.3.1: {} + tstl@2.5.16: {} tsup@7.3.0(ts-node@10.9.2(@types/node@18.19.130)(typescript@5.9.3))(typescript@5.9.3): @@ -5129,6 +5525,8 @@ snapshots: dependencies: is-typedarray: 1.0.0 + typescript-lru-cache@2.0.0: {} + typescript@4.9.5: {} typescript@5.9.3: {} @@ -5147,6 +5545,29 @@ snapshots: undici-types@6.21.0: {} + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + unpipe@1.0.0: {} uri-js@4.4.1: @@ -5165,6 +5586,16 @@ snapshots: vary@1.1.2: {} + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} @@ -5293,3 +5724,5 @@ snapshots: yn@3.1.1: {} yocto-queue@0.1.0: {} + + zwitch@2.0.4: {} diff --git a/src/client.ts b/src/client.ts index d38146c..89b1c0d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,8 +1,6 @@ -import { generateSecretKey, getPublicKey, nip05, nip19, verifyEvent, type Event } from 'nostr-tools'; +import "websocket-polyfill"; +import NDK, { NDKUser, NDKEvent, NDKPrivateKeySigner, NDKNip46Signer, NostrEvent } from '@nostr-dev-kit/ndk'; import fs from 'fs'; -import { RelayPool } from './daemon/lib/relay-pool.js'; -import { secretKeyBytes } from './daemon/nip46/transport.js'; -import { Nip46Client } from './nip46-client.js'; const args = process.argv; const command = process.argv[2]; @@ -10,6 +8,9 @@ let remotePubkey = process.argv[3]; let content = process.argv[4]; const dontPublish = process.argv.includes('--dont-publish'); const debug = process.argv.includes('--debug'); +let signer: NDKNip46Signer; +let ndk: NDK; +let remoteUser: NDKUser; const relaysIndex = args.findIndex(arg => arg === '--relays'); let relays: string[] = []; @@ -19,17 +20,37 @@ if (relaysIndex !== -1 && args[relaysIndex + 1]) { } if (!command) { - console.log('Usage: node src/client.js [--dont-publish] [--debug] [--relays ]'); + console.log('Usage: node src/client.js [--dont-publish] [--debug] [--pk ]'); console.log(''); - console.log(`\t: command to run (sign, create_account)`); - console.log(`\t: npub (or nip05) of the key to be published as`); - console.log(`\t: sign flow: event JSON to sign (no need for pubkey/id) | or kind:1 content string`); + console.log(`\t: command to run (ping, sign)`); + console.log(`\t: npub that should be published as`); + console.log(`\t: sign flow: event JSON to sign (no need for pubkey or id fields) | or kind:1 content string to sign\n`); console.log(`\t create_account flow: [desired-nip05[,desired-domain,[email]]]`); console.log('\t--debug: enable debug mode'); - console.log('\t--relays: list of relays to publish to (comma-separated)'); + console.log('\t--relays: list of relays to publish to (separated by commas)'); process.exit(1); } +async function createNDK(): Promise { + const ndk = new NDK({ + explicitRelayUrls: [ + 'wss://relay.nsecbunker.com', + ...relays + ], + enableOutboxModel: false + }); + if (debug) { + ndk.pool.on('relay:disconnect', () => console.log('❌ disconnected')); + } + await ndk.connect(5000); + + return ndk; +} + +// switch (command) { +// case 'ping': +// ping(remotePubkey); + function getPrivateKeyPath() { const home = process.env.HOME || process.env.USERPROFILE; return `${home}/.nsecbunker-client-private.key`; @@ -48,120 +69,134 @@ function loadPrivateKey(): string | undefined { if (!fs.existsSync(path)) { return undefined; } - return fs.readFileSync(`${path}/private.key`).toString().trim(); + return fs.readFileSync(`${path}/private.key`).toString(); } -/** Resolve an npub / nip05 / bare-domain into a hex pubkey. */ -async function resolvePubkey(input: string): Promise { - if (input.startsWith('npub')) { - return nip19.decode(input).data as string; - } - const addr = input.includes('@') ? input : `_@${input}`; - const profile = await nip05.queryProfile(addr); - if (!profile) { - console.log(`Invalid nip05 ${input}`); - process.exit(1); - } - return profile.pubkey; -} - -let client: Nip46Client; -let pool: RelayPool; (async () => { - // create_account against a domain: @ (or a bare domain). - if (command === 'create_account' && !remotePubkey.startsWith('npub')) { - let [username, domain] = remotePubkey.split('@'); + let remoteUser: NDKUser; + + ndk = await createNDK(); + + // if this is the create_account command and we have something that doesn't look like an npub as the remotePubkey, use NDKUser.fromNip05 to get the npub + if (command === 'create_account' && !remotePubkey.startsWith("npub")) { + // see if we have a username@domain + let [ username, domain ] = remotePubkey.split('@'); + if (!domain) { domain = username; username = Math.random().toString(36).substring(2, 15); } - content = `${username},${domain}`; - remotePubkey = await resolvePubkey(domain); + + content = `${username},${domain}` + + const u = await NDKUser.fromNip05(domain, ndk); + if (!u) { + console.log(`Invalid nip05 ${remotePubkey}`); + process.exit(1); + } + remoteUser = u; + remotePubkey = remoteUser.pubkey; } else { - remotePubkey = await resolvePubkey(remotePubkey); + // check if we have a @ so we try to get the npub from nip05 + if (remotePubkey.includes('@')) { + const u = await NDKUser.fromNip05(remotePubkey, ndk); + if (!u) { + console.log(`Invalid nip05 ${remotePubkey}`); + process.exit(1); + } + remoteUser = u; + remotePubkey = remoteUser.pubkey; + } else { + remoteUser = new NDKUser({npub: remotePubkey}); + } } - // Load or generate the local client key (hex). - let localHex = loadPrivateKey(); - if (!localHex) { - localHex = Buffer.from(generateSecretKey()).toString('hex'); - savePrivateKey(localHex); + + let localSigner: NDKPrivateKeySigner; + + const pk = loadPrivateKey(); + + if (pk) { + localSigner = new NDKPrivateKeySigner(pk); + } else { + localSigner = NDKPrivateKeySigner.generate(); + savePrivateKey(localSigner.privateKey!); } - const localSk = secretKeyBytes(localHex); - pool = new RelayPool(['wss://relay.nsecbunker.com', ...relays], { log: debug ? (...a) => console.log(...a) : undefined }); - pool.start(); - - client = new Nip46Client(localSk, remotePubkey, pool, (url) => - console.log(`Go to ${url} to authorize this request`), - ); - await client.start(); - - if (debug) console.log(`local pubkey`, nip19.npubEncode(getPublicKey(localSk))); + signer = new NDKNip46Signer(ndk, remoteUser.pubkey, localSigner); + if (debug) console.log(`local pubkey`, (await localSigner.user()).npub); if (debug) console.log(`remote pubkey`, remotePubkey); + ndk.signer = signer; + + signer.on("authUrl", (url) => { + console.log(`Go to ${url} to authorize this request`); + }); switch (command) { - case 'sign': return signFlow(); - case 'create_account': return createAccountFlow(); + case "sign": return signFlow(); + case "create_account": return createAccountFlow(); default: console.log(`Unknown command ${command}`); process.exit(1); } -})().catch((e) => { - console.log('error', e?.message ?? e); - process.exit(1); -}); +})(); async function createAccountFlow() { - const [username, domain, email] = content.split(',').map((s) => s.trim()); + const [ username, domain, email ] = content.split(',').map((s) => s.trim()); try { - const pubkey = await client.createAccount(username, domain, email); - console.log(`Hello`, nip19.npubEncode(pubkey)); - } catch (e: any) { - console.log('error', e?.message ?? e); - } finally { - pool.stop(); + const pubkey = await signer.createAccount(username, domain, email); + const user = new NDKUser({pubkey}); + console.log(`Hello`, user.npub); + } catch (e) { + console.log('error', e); } } -async function signFlow() { - try { - if (debug) console.log(`waiting for authorization (check your nsecBunker)...`); - await client.connect(); +function signFlow() { + setTimeout(async () => { + try { + if (debug) console.log(`waiting for authorization (check your nsecBunker)...`); + await signer.blockUntilReady(); + } catch(e) { + console.log('error:', e); + process.exit(1); + } if (debug) console.log(`authorized to sign as`, remotePubkey); - let template: Record; + let event; + try { - template = JSON.parse(content); - if (!template.tags) template.tags = []; - if (template.content === undefined) template.content = ''; - if (template.kind === undefined) throw new Error('No kind on the event to sign!'); - if (!template.created_at) template.created_at = Math.floor(Date.now() / 1000); - } catch { - template = { + const json = JSON.parse(content); + event = new NDKEvent(ndk, json); + if (!event.tags) { event.tags = []; } + if (!event.content) { event.content = ""; } + if (!event.kind) { throw "No kind on the event to sign!"; } + } catch (e) { + event = new NDKEvent(ndk, { kind: 1, - created_at: Math.floor(Date.now() / 1000), content, - tags: [['client', 'nsecbunker-client']], - }; + tags: [ + ['client', 'nsecbunker-client'] + ], + } as NostrEvent); } - const signed: Event = await client.signEvent(template); - if (!verifyEvent(signed)) throw new Error('signer returned an invalid event'); + try { + await event.sign(); + if (debug) { + console.log(event.rawEvent()); + } else { + console.log(event.sig); + } - if (debug) { - console.log(signed); - } else { - console.log(signed.sig); - } + if (!dontPublish) { + const relaysPublished = await event.publish(); + } - if (!dontPublish) { - await pool.publish(signed); + process.exit(0); + } catch(e) { + console.log('sign error', e); } - process.exit(0); - } catch (e: any) { - console.log('sign error', e?.message ?? e); - process.exit(1); - } + }, 2000); } diff --git a/src/nip46-client.ts b/src/nip46-client.ts deleted file mode 100644 index 8e76ce9..0000000 --- a/src/nip46-client.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { finalizeEvent, getPublicKey, nip44, verifyEvent, type Event } from "nostr-tools"; -import { RelayPool } from "./daemon/lib/relay-pool.js"; - -const NIP46_KIND = 24133; - -type Pending = { - resolve: (result: string) => void; - reject: (err: Error) => void; -}; - -/** - * Minimal NIP-46 *client* over the nostr-tools RelayPool — the inverse of the - * daemon's Nip46Transport, used by the standalone CLI (src/client.ts). Sends - * requests to a remote signer (the bunker key it wants to act as), matches - * responses by id, and surfaces `auth_url` prompts. nip44 envelope. - * - * Replaces NDK's NDKNip46Signer so nsecbunkerd carries no NDK at - * all (aiolabs/nsecbunkerd#44 follow-up). - */ -export class Nip46Client { - public readonly pubkey: string; - private sub: { close: () => void } | null = null; - private pending = new Map(); - - constructor( - private readonly sk: Uint8Array, - /** The remote-signer pubkey we send requests to (the key to act as). */ - private readonly remotePubkey: string, - private readonly pool: RelayPool, - private readonly onAuthUrl: (url: string) => void = (u) => console.log(`Authorize at: ${u}`), - ) { - this.pubkey = getPublicKey(sk); - } - - async start(): Promise { - this.sub = await this.pool.subscribeAwaitingEose( - [{ kinds: [NIP46_KIND], "#p": [this.pubkey] }], - (event: Event) => this.onEvent(event), - { id: `nip46-client:${this.pubkey}` }, - ); - } - - stop(): void { - this.sub?.close(); - this.sub = null; - } - - private onEvent(event: Event): void { - if (!verifyEvent(event)) return; - let msg: { id?: string; result?: string; error?: string }; - try { - const convKey = nip44.getConversationKey(this.sk, event.pubkey); - msg = JSON.parse(nip44.decrypt(event.content, convKey)); - } catch { - return; // not for us / not nip44 - } - if (!msg.id) return; - const p = this.pending.get(msg.id); - if (!p) return; - - // The signer asks the human to approve via a URL; keep waiting for the - // real response (same id) it sends once approved. - if (msg.result === "auth_url") { - this.onAuthUrl(msg.error ?? ""); - return; - } - this.pending.delete(msg.id); - if (msg.error) p.reject(new Error(msg.error)); - else p.resolve(msg.result ?? ""); - } - - /** Send a request to the remote signer and await its result. */ - request(method: string, params: string[], timeoutMs = 120_000): Promise { - const id = Math.random().toString(36).substring(2, 12); - const convKey = nip44.getConversationKey(this.sk, this.remotePubkey); - const content = nip44.encrypt(JSON.stringify({ id, method, params }), convKey); - const event = finalizeEvent( - { kind: NIP46_KIND, created_at: Math.floor(Date.now() / 1000), tags: [["p", this.remotePubkey]], content }, - this.sk, - ); - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - this.pending.delete(id); - reject(new Error(`${method} timed out`)); - }, timeoutMs); - this.pending.set(id, { - resolve: (r) => { clearTimeout(timer); resolve(r); }, - reject: (e) => { clearTimeout(timer); reject(e); }, - }); - void this.pool.publish(event); - }); - } - - /** NIP-46 connect handshake. Returns once the signer acks (or throws). */ - async connect(secret = ""): Promise { - const res = await this.request("connect", [this.remotePubkey, secret]); - if (res !== "ack") throw new Error(`unexpected connect response: ${res}`); - } - - /** Ask the signer to sign an event template; returns the full signed event. */ - async signEvent(template: Record): Promise { - const res = await this.request("sign_event", [JSON.stringify(template)]); - return JSON.parse(res) as Event; - } - - /** Ask the signer to create a new account; returns the new pubkey (hex). */ - async createAccount(username: string, domain: string, email?: string): Promise { - const params = email ? [username, domain, email] : [username, domain]; - return this.request("create_account", params); - } -}