Compare commits

..

No commits in common. "17540272496ed37e43580889e90786346e6cc082" and "d802ab0bb5dacdfa8e8056366a503d3a9fb39537" have entirely different histories.

4 changed files with 572 additions and 214 deletions

View file

@ -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",

459
pnpm-lock.yaml generated
View file

@ -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: {}

View file

@ -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 <command> <remote-npub> <content> [--dont-publish] [--debug] [--relays <r1,r2>]');
console.log('Usage: node src/client.js <command> <remote-npub> <content> [--dont-publish] [--debug] [--pk <key>]');
console.log('');
console.log(`\t<command>: command to run (sign, create_account)`);
console.log(`\t<remote-npub>: npub (or nip05) of the key to be published as`);
console.log(`\t<content>: sign flow: event JSON to sign (no need for pubkey/id) | or kind:1 content string`);
console.log(`\t<command>: command to run (ping, sign)`);
console.log(`\t<remote-npub>: npub that should be published as`);
console.log(`\t<content>: 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<NDK> {
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<string> {
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: <username>@<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() {
function signFlow() {
setTimeout(async () => {
try {
if (debug) console.log(`waiting for authorization (check your nsecBunker)...`);
await client.connect();
await signer.blockUntilReady();
} catch(e) {
console.log('error:', e);
process.exit(1);
}
if (debug) console.log(`authorized to sign as`, remotePubkey);
let template: Record<string, any>;
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(signed);
console.log(event.rawEvent());
} else {
console.log(signed.sig);
console.log(event.sig);
}
if (!dontPublish) {
await pool.publish(signed);
const relaysPublished = await event.publish();
}
process.exit(0);
} catch (e: any) {
console.log('sign error', e?.message ?? e);
process.exit(1);
} catch(e) {
console.log('sign error', e);
}
}, 2000);
}

View file

@ -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<string, Pending>();
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<void> {
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<string> {
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<string>((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<void> {
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<string, any>): Promise<Event> {
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<string> {
const params = email ? [username, domain, email] : [username, domain];
return this.request("create_account", params);
}
}