diff --git a/package.json b/package.json
index 576559a8c..2c3a995dc 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,7 @@
"format": "prettier --ignore-path .prettierignore -w ."
},
"dependencies": {
- "@cashu/cashu-ts": "2.0.0-rc1",
+ "@cashu/cashu-ts": "^2.1.0",
"@chakra-ui/anatomy": "^2.3.4",
"@chakra-ui/breakpoint-utils": "^2.0.8",
"@chakra-ui/icons": "^2.2.4",
@@ -93,7 +93,7 @@
"react-error-boundary": "^4.1.2",
"react-force-graph-2d": "^1.26.1",
"react-force-graph-3d": "^1.25.1",
- "react-hook-form": "^7.54.0",
+ "react-hook-form": "^7.54.1",
"react-markdown": "^9.0.1",
"react-mosaic-component": "^6.1.0",
"react-photo-album": "^2.4.1",
@@ -109,7 +109,7 @@
"rx-nostr": "^3.4.1",
"rxjs": "^7.8.1",
"three": "^0.170.0",
- "three-spritetext": "^1.9.2",
+ "three-spritetext": "^1.9.3",
"three-stdlib": "^2.35.2",
"tiny-lru": "^11.2.11",
"unified": "^11.0.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 07a9395f7..6a656cacc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,8 +13,8 @@ importers:
.:
dependencies:
'@cashu/cashu-ts':
- specifier: 2.0.0-rc1
- version: 2.0.0-rc1
+ specifier: ^2.1.0
+ version: 2.1.0
'@chakra-ui/anatomy':
specifier: ^2.3.4
version: 2.3.4
@@ -92,28 +92,28 @@ importers:
version: 4.9.2(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
applesauce-channel:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-content:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-core:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-factory:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-lists:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-net:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-react:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
applesauce-signer:
specifier: next
- version: 0.0.0-next-20241212192616(typescript@5.7.2)
+ version: 0.0.0-next-20241213171848(typescript@5.7.2)
bech32:
specifier: ^2.0.0
version: 2.0.0
@@ -244,8 +244,8 @@ importers:
specifier: ^1.25.1
version: 1.25.1(react@18.3.1)
react-hook-form:
- specifier: ^7.54.0
- version: 7.54.0(react@18.3.1)
+ specifier: ^7.54.1
+ version: 7.54.1(react@18.3.1)
react-markdown:
specifier: ^9.0.1
version: 9.0.1(@types/react@18.3.16)(react@18.3.1)
@@ -292,8 +292,8 @@ importers:
specifier: ^0.170.0
version: 0.170.0
three-spritetext:
- specifier: ^1.9.2
- version: 1.9.2(three@0.170.0)
+ specifier: ^1.9.3
+ version: 1.9.3(three@0.170.0)
three-stdlib:
specifier: ^2.35.2
version: 2.35.2(three@0.170.0)
@@ -403,8 +403,8 @@ importers:
packages:
- 3d-force-graph@1.74.2:
- resolution: {integrity: sha512-XBC1KB0vDvG616qfy11jE6pwp4SDQ4tBVof0GSHztjV1fVp7rhP5IGhwnbSjyp6FKAw+PjsWL/0tZuAcGFbXsA==}
+ 3d-force-graph@1.74.3:
+ resolution: {integrity: sha512-srzOasC6RMXVXCivorDhDSqJCFKz3t5+AUIggVYP2pp3vPJ8YlRH/BLiIybtmvEYLQLv+hKeEuWFDHRaCeJrnQ==}
engines: {node: '>=12'}
'@ampproject/remapping@2.3.0':
@@ -917,9 +917,15 @@ packages:
'@cashu/cashu-ts@2.0.0-rc1':
resolution: {integrity: sha512-39459l7x/fUMEgOsCdGLLl6rMekO4nbv+wEuavmyElh8hgN8t66wcb29AJvdFTb6K3lPACKF2rs/jAlPYrN7Ng==}
+ '@cashu/cashu-ts@2.1.0':
+ resolution: {integrity: sha512-qFfFz1dx9keJxumjk5FyTvI1j0Yp/P5LXDy0cGO4Xlp3WYKOI1nykNOTPd+bTY9vSkvIM+xuXRer9BtQxqHtwA==}
+
'@cashu/crypto@0.2.7':
resolution: {integrity: sha512-1aaDfUjiHNXoJqg8nW+341TLWV9W28DsVNXJUKcHL0yAmwLs5+56SSnb8LLDJzPamLVoYL0U0bda91klAzptig==}
+ '@cashu/crypto@0.3.4':
+ resolution: {integrity: sha512-mfv1Pj4iL1PXzUj9NKIJbmncCLMqYfnEDqh/OPxAX0nNBt6BOnVJJLjLWFlQeYxlnEfWABSNkrqPje1t5zcyhA==}
+
'@chakra-ui/anatomy@2.2.2':
resolution: {integrity: sha512-MV6D4VLRIHr4PkW4zMyqfrNS1mPlCTiCXwvYGtDFQYr+xHFfonhAuf9WjsSc0nyp2m0OdkSLnzmVKkZFLo25Tg==}
@@ -1905,29 +1911,29 @@ packages:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
- applesauce-channel@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-N7S0XIw+aYymBF5pllEMwKJkDJft9qZAnGMJzdTA400KR391eFbnmE3sVOFXvIvU3XzKP89RrysOWjaPRAdASA==}
+ applesauce-channel@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-4D+FApKZ/YDd/E2Jr26IRzl47wr5um9N7+Sgd6FjeGLYjCKnSKkrO/TZ2nX6/bAWS6pwOgo6e492EEn2xkKAyA==}
- applesauce-content@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-WUC5WJVDR9sMCJVp5c/3FKBDL6pCqGaBNS5UXeLY+sBXYs9pqLzxXrrILQKWZM+ghPfjCdfc6fDpjVxjyR4vcA==}
+ applesauce-content@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-BUtsmWGMUiw1RmY/xTsDUfLSS2u/rhODT2cDwnfc4ln7hy5CF3vibvn6amgO+7xWe/uK04TJGUmESbUIlKeWjg==}
- applesauce-core@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-QQjsU2CU0OtQZfnb8VYbz8q/mKC2tLDsxSqHKsa1wIj5m5i7zRgPRBUj2FZrFJmIwlrG73G7uj1Ip53F93SIEw==}
+ applesauce-core@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-2VTdwkfPCUJcykbP+4np9CUoZI4aKUOTX1vjN/DRSaq6Rjd3jC5FP2MNMdRi9u8d1FlAoJyqOs2CCMjnsfkLOg==}
- applesauce-factory@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-YhCaVGcVbqAzg7T2Cu6MG/iYRpfyC538GNZfG38wm6BD/5YCyygZ0LOmnNrIdhkD5mhxYwLxjlcQyY8n0meK9w==}
+ applesauce-factory@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-SBr57K1ZHyLFhvpn4xXDFZsyWG0X0k1FeTIf6vTcWwZ1FZ1e50eslt+zVLYfFhw55Tk8wT0chB4sToce25VbIw==}
- applesauce-lists@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-Yd4clwLOKegWs0nJRHcjlJvJtxXYXNSWMQiqVHos510r/0sXpkCL9dmY9Y2QMLbG65Rcwvlu4OfT1w9+iXB7gA==}
+ applesauce-lists@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-GmziucyndF2+xhV2JBqQE1ai683wd6iV0mtatdLeM3h4DfAyElLT4CzFEONH7TzGYwDNnNaB11o7LmE78ww2fg==}
- applesauce-net@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-LjGH+SCKTpGOYbdiybS0zJzdNpQMX0n1Zq3/S+JeQyfK0vPyeDPznQE0jvuIVT7SHyyCVf9cqSLIPm20qaxDXA==}
+ applesauce-net@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-xtu/QdSN1hv2oRobJ6NX3oewLKWcC/LlqwFjE/RwL+s0+n7U91vIfqIM6Cy2GnSuvEyL8kbdPdOTfdzbqu4/Pg==}
- applesauce-react@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-tDtXc5e23Y5i11icZge0fTfpYIUXFtj0MQfzBgUfF4FT6zwUw69Bsw4roAVhVezWfWh4fD8dcIFjhNzGyi79AA==}
+ applesauce-react@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-EVUEC4x5/mtXPs1V66FFb6Ke2Pw7gqF8gyBnzcoH9Dvt8DIysJqWbLgtiha+wscgfit9W+eO/YxXxpNbpMjArA==}
- applesauce-signer@0.0.0-next-20241212192616:
- resolution: {integrity: sha512-kzOCY+TrlGWJnDHpsIzyB/lxFTJfMhQIr6u1+tGro/bqfVBrdX1fJF7cxv7Ro0Tnf/1RGosE4nxjz1Z+9ifqMg==}
+ applesauce-signer@0.0.0-next-20241213171848:
+ resolution: {integrity: sha512-op99Gq8z7NvbNVX8lO8GjNi9JIINDbHmwygM6qO2VmavAE0a75EFpIQWEaarr9XACD3V/54GnHiBlqFNTl0skA==}
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
@@ -2029,8 +2035,8 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
- browserslist@4.24.2:
- resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==}
+ browserslist@4.24.3:
+ resolution: {integrity: sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
@@ -2372,8 +2378,8 @@ packages:
dnd-core@16.0.1:
resolution: {integrity: sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==}
- dnd-multi-backend@8.1.0:
- resolution: {integrity: sha512-Favl89icddeqKI9MzMOW5AH5WHlJhdTmfnHm3QrbviJSp87N4oE7JPcqAzbu2QSis40senFQSoehuLX3H/xadA==}
+ dnd-multi-backend@8.1.1:
+ resolution: {integrity: sha512-+uksZeT2J+yD3pwRDixJQgZZ6XJN9uc1PR7ENobUnow6Vg6rawFi524aAOVacNJJvat2trtUo6RRs358U5lEdg==}
peerDependencies:
dnd-core: ^16.0.1
@@ -2571,8 +2577,8 @@ packages:
for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
- force-graph@1.47.0:
- resolution: {integrity: sha512-2R6q3cLPuUzltGA+uYlmV/1cU4Fc/+jwU+0RiwLlUAh/geBmxfV3S1bpZxJ47UMMgD5Op+g0MlxNiJ62LAjQCQ==}
+ force-graph@1.47.1:
+ resolution: {integrity: sha512-NF0prpR8tNGq7oCE/aFImT/6/3wSk585bcp39UAj6SNSPjvKbX6ktCH6cZnjfsnPNx/DYj1rn+cvvjH814HCFA==}
engines: {node: '>=12'}
framer-motion@10.18.0:
@@ -2699,8 +2705,8 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hast-util-to-html@9.0.3:
- resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==}
+ hast-util-to-html@9.0.4:
+ resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==}
hast-util-to-jsx-runtime@2.3.2:
resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==}
@@ -2781,8 +2787,8 @@ packages:
inline-style-prefixer@7.0.1:
resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==}
- internal-slot@1.0.7:
- resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
+ internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
internmap@2.0.3:
@@ -2819,8 +2825,8 @@ packages:
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
engines: {node: '>= 0.4'}
- is-boolean-object@1.2.0:
- resolution: {integrity: sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==}
+ is-boolean-object@1.2.1:
+ resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==}
engines: {node: '>= 0.4'}
is-callable@1.2.7:
@@ -2835,8 +2841,8 @@ packages:
resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
engines: {node: '>= 0.4'}
- is-date-object@1.0.5:
- resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
is-decimal@1.0.4:
@@ -2922,8 +2928,8 @@ packages:
resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
engines: {node: '>=4'}
- is-symbol@1.1.0:
- resolution: {integrity: sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==}
+ is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
engines: {node: '>= 0.4'}
is-typed-array@1.1.13:
@@ -2934,8 +2940,9 @@ packages:
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
engines: {node: '>= 0.4'}
- is-weakref@1.0.2:
- resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ is-weakref@1.1.0:
+ resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==}
+ engines: {node: '>= 0.4'}
is-weakset@2.0.3:
resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==}
@@ -3440,8 +3447,8 @@ packages:
parse-entities@2.0.0:
resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==}
- parse-entities@4.0.1:
- resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
@@ -3553,8 +3560,8 @@ packages:
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
- rdndmb-html5-to-touch@8.1.0:
- resolution: {integrity: sha512-Ep19LSFHwRhq+kuGGSqB8/+LW9uLyjd1xyQG/WkZ8nPoFgIH/3XtbPD7BxF9jMiwPCJepSK+YNUPej4I97F7XA==}
+ rdndmb-html5-to-touch@8.1.1:
+ resolution: {integrity: sha512-edyTFE+V9q8aHA2/gKM86F4tjVSdzfEVxFo0kvvTGqIUO2biZJC1TFpr6D+YNA7/oKXHejK5IllyhVrsB6HEsw==}
react-chartjs-2@5.2.0:
resolution: {integrity: sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==}
@@ -3577,16 +3584,16 @@ packages:
react-dnd-html5-backend@16.0.1:
resolution: {integrity: sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==}
- react-dnd-multi-backend@8.1.0:
- resolution: {integrity: sha512-SOVXIDAyTp63weGWp6/nI8Km0PwzP/SAqYCz2ZZHp31pNgHtsnDhGkasBSIMG9HDzMNkVp3/X1IPKuDF2OvEwg==}
+ react-dnd-multi-backend@8.1.1:
+ resolution: {integrity: sha512-ctRbiLCYGxtXdXV6GbNML9XrvNFoR72AtrgWE3TZlpqwE8ZcaN+PJkARFVW9+99uU9z3BC+dx9FIfIgS9ParEw==}
peerDependencies:
dnd-core: ^16.0.1
react: ^16.14.0 || ^17.0.2 || ^18.0.0
react-dnd: ^16.0.1
react-dom: ^16.14.0 || ^17.0.2 || ^18.0.0
- react-dnd-preview@8.1.0:
- resolution: {integrity: sha512-bMSQb5KTCy58Mo2hDMf48ioNIiPyK87SajJigdd3WlGKXSV7EY/37qPNog1ox5an0iVFSunbQnv2huvZjy3CbA==}
+ react-dnd-preview@8.1.1:
+ resolution: {integrity: sha512-NXMxP+U2V5p8Fin3on7L6yfy1jCk2wekwcQw0Wtwhjo4K1lMYtID9tOBo7IKEgVmDdVCLXPQBC1wlGFwDa97Mg==}
peerDependencies:
react: ^16.14.0 || ^17.0.2 || ^18.0.0
react-dnd: ^16.0.1
@@ -3643,8 +3650,8 @@ packages:
peerDependencies:
react: '*'
- react-hook-form@7.54.0:
- resolution: {integrity: sha512-PS05+UQy/IdSbJNojBypxAo9wllhHgGmyr8/dyGQcPoiMf3e7Dfb9PWYVRco55bLbxH9S+1yDDJeTdlYCSxO3A==}
+ react-hook-form@7.54.1:
+ resolution: {integrity: sha512-PUNzFwQeQ5oHiiTUO7GO/EJXGEtuun2Y1A59rLnZBBj+vNEOWt/3ERTiG1/zt7dVeJEM+4vDX/7XQ/qanuvPMg==}
engines: {node: '>=18.0.0'}
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
@@ -3652,8 +3659,8 @@ packages:
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
- react-kapsule@2.5.2:
- resolution: {integrity: sha512-ptK3/0BBJwS958e0Akn5VkQjeVDA2tM8NrJvlctIPI3OA5zp6Q6AD/MWwvKiMCH/tTI04h8JfGsOztDwJdQHqw==}
+ react-kapsule@2.5.6:
+ resolution: {integrity: sha512-aE4Nq7dDG8R/LdNmvOL6Azjr97I2E7ycFDJRkoHJSp9OQgTJDT3MHTJtJDrOTwzCl6sllYSqrtcndaCzizyAjQ==}
engines: {node: '>=12'}
peerDependencies:
react: '>=16.13.1'
@@ -4114,20 +4121,20 @@ packages:
textarea-caret@3.0.2:
resolution: {integrity: sha512-gRzeti2YS4did7UJnPQ47wrjD+vp+CJIe9zbsu0bJ987d8QVLvLNG9757rqiQTIy4hGIeFauTTJt5Xkn51UkXg==}
- three-forcegraph@1.42.5:
- resolution: {integrity: sha512-39PVCtQ9Ayh0MxeE7/eiqKokCjRVE7seDKIRe47tTkImQDPMani6/Jzxawoy96JJyhdI8Kz3/gmlcfK6iB3EIQ==}
+ three-forcegraph@1.42.8:
+ resolution: {integrity: sha512-fhTQPC9lvYYUlsyVUUeJwijpUxHzbmurFSf5LEQI9W3Yp5kwI9oupS03g9HojpTUMd+bqiGvhVCnle5zmBMcAw==}
engines: {node: '>=12'}
peerDependencies:
three: '>=0.118.3'
- three-render-objects@1.32.0:
- resolution: {integrity: sha512-bTpyr8hp8PowFAi3pGjm/t0cMY7G8tecxgBTlOi9H/JNXxlAJBmvT6LF7oXeh7i2Q4Q6m9DNy+/Y72s+Varzww==}
+ three-render-objects@1.32.1:
+ resolution: {integrity: sha512-HcbVhMFwPxtxrrQYe+pD8HFZmx22lYuYZeHXcZlDdxqWyr5wAZgjD+vX23oALrmP3i1LW8udheXxbntwYmA9sw==}
engines: {node: '>=12'}
peerDependencies:
three: '>=0.168'
- three-spritetext@1.9.2:
- resolution: {integrity: sha512-muexs0ClLe1ppqtAbpwHIn6bcmGoGG4fRB5pnoWgKNmYRqURYfsPr6luMGSJ4MftE/rirZDuAgqUgwL/voGzyg==}
+ three-spritetext@1.9.3:
+ resolution: {integrity: sha512-p7iEQr7anABRUJNOH2logMf1aRuWb026IshUC4aJ8F+bbMTn5Z43/Jd7/W3VihE3ToCwrWMl6u6VwgFMTw0jvA==}
engines: {node: '>=12'}
peerDependencies:
three: '>=0.86.0'
@@ -4407,8 +4414,8 @@ packages:
resolution: {integrity: sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==}
engines: {node: '>= 0.4'}
- which-builtin-type@1.2.0:
- resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==}
+ which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
engines: {node: '>= 0.4'}
which-collection@1.0.2:
@@ -4536,13 +4543,13 @@ packages:
snapshots:
- 3d-force-graph@1.74.2:
+ 3d-force-graph@1.74.3:
dependencies:
accessor-fn: 1.5.1
kapsule: 1.16.0
three: 0.170.0
- three-forcegraph: 1.42.5(three@0.170.0)
- three-render-objects: 1.32.0(three@0.170.0)
+ three-forcegraph: 1.42.8(three@0.170.0)
+ three-render-objects: 1.32.1(three@0.170.0)
'@ampproject/remapping@2.3.0':
dependencies:
@@ -4600,7 +4607,7 @@ snapshots:
dependencies:
'@babel/compat-data': 7.26.3
'@babel/helper-validator-option': 7.25.9
- browserslist: 4.24.2
+ browserslist: 4.24.3
lru-cache: 5.1.1
semver: 6.3.1
@@ -5213,6 +5220,14 @@ snapshots:
'@scure/bip32': 1.6.0
buffer: 6.0.3
+ '@cashu/cashu-ts@2.1.0':
+ dependencies:
+ '@cashu/crypto': 0.3.4
+ '@noble/curves': 1.7.0
+ '@noble/hashes': 1.6.1
+ '@scure/bip32': 1.6.0
+ buffer: 6.0.3
+
'@cashu/crypto@0.2.7':
dependencies:
'@noble/curves': 1.7.0
@@ -5221,6 +5236,14 @@ snapshots:
'@scure/bip39': 1.5.0
buffer: 6.0.3
+ '@cashu/crypto@0.3.4':
+ dependencies:
+ '@noble/curves': 1.7.0
+ '@noble/hashes': 1.6.1
+ '@scure/bip32': 1.6.0
+ '@scure/bip39': 1.5.0
+ buffer: 6.0.3
+
'@chakra-ui/anatomy@2.2.2': {}
'@chakra-ui/anatomy@2.3.4': {}
@@ -6077,7 +6100,7 @@ snapshots:
'@shikijs/types': 1.24.2
'@shikijs/vscode-textmate': 9.3.1
'@types/hast': 3.0.4
- hast-util-to-html: 9.0.3
+ hast-util-to-html: 9.0.4
'@shikijs/engine-javascript@1.24.2':
dependencies:
@@ -6368,23 +6391,23 @@ snapshots:
dependencies:
color-convert: 2.0.1
- applesauce-channel@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-channel@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-factory: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-factory: 0.0.0-next-20241213171848(typescript@5.7.2)
nostr-tools: 2.10.4(typescript@5.7.2)
rxjs: 7.8.1
transitivePeerDependencies:
- supports-color
- typescript
- applesauce-content@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-content@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
'@cashu/cashu-ts': 2.0.0-rc1
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
'@types/unist': 3.0.3
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
mdast-util-find-and-replace: 3.0.1
nostr-tools: 2.10.4(typescript@5.7.2)
remark: 15.0.1
@@ -6395,7 +6418,7 @@ snapshots:
- supports-color
- typescript
- applesauce-core@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-core@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
'@scure/base': 1.2.1
debug: 4.4.0
@@ -6409,23 +6432,23 @@ snapshots:
- supports-color
- typescript
- applesauce-factory@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-factory@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
- applesauce-content: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-content: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
nostr-tools: 2.10.4(typescript@5.7.2)
transitivePeerDependencies:
- supports-color
- typescript
- applesauce-lists@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-lists@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
'@noble/hashes': 1.6.1
'@noble/secp256k1': 1.7.1
'@scure/base': 1.2.1
'@types/dom-serial': 1.0.6
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-factory: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-factory: 0.0.0-next-20241213171848(typescript@5.7.2)
debug: 4.4.0
nostr-tools: 2.10.4(typescript@5.7.2)
rxjs: 7.8.1
@@ -6433,9 +6456,9 @@ snapshots:
- supports-color
- typescript
- applesauce-net@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-net@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
nanoid: 5.0.9
nostr-tools: 2.10.4(typescript@5.7.2)
rxjs: 7.8.1
@@ -6443,11 +6466,11 @@ snapshots:
- supports-color
- typescript
- applesauce-react@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-react@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
- applesauce-content: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-factory: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-content: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-factory: 0.0.0-next-20241213171848(typescript@5.7.2)
nostr-tools: 2.10.4(typescript@5.7.2)
react: 18.3.1
rxjs: 7.8.1
@@ -6455,14 +6478,14 @@ snapshots:
- supports-color
- typescript
- applesauce-signer@0.0.0-next-20241212192616(typescript@5.7.2):
+ applesauce-signer@0.0.0-next-20241213171848(typescript@5.7.2):
dependencies:
'@noble/hashes': 1.6.1
'@noble/secp256k1': 1.7.1
'@scure/base': 1.2.1
'@types/dom-serial': 1.0.6
- applesauce-core: 0.0.0-next-20241212192616(typescript@5.7.2)
- applesauce-net: 0.0.0-next-20241212192616(typescript@5.7.2)
+ applesauce-core: 0.0.0-next-20241213171848(typescript@5.7.2)
+ applesauce-net: 0.0.0-next-20241213171848(typescript@5.7.2)
debug: 4.4.0
nanoid: 5.0.9
nostr-tools: 2.10.4(typescript@5.7.2)
@@ -6594,12 +6617,12 @@ snapshots:
dependencies:
fill-range: 7.1.1
- browserslist@4.24.2:
+ browserslist@4.24.3:
dependencies:
caniuse-lite: 1.0.30001688
electron-to-chromium: 1.5.73
node-releases: 2.0.19
- update-browserslist-db: 1.1.1(browserslist@4.24.2)
+ update-browserslist-db: 1.1.1(browserslist@4.24.3)
buffer-from@1.1.2: {}
@@ -6771,7 +6794,7 @@ snapshots:
core-js-compat@3.39.0:
dependencies:
- browserslist: 4.24.2
+ browserslist: 4.24.3
cosmiconfig@7.1.0:
dependencies:
@@ -6975,7 +6998,7 @@ snapshots:
'@react-dnd/invariant': 4.0.2
redux: 4.2.1
- dnd-multi-backend@8.1.0(dnd-core@16.0.1):
+ dnd-multi-backend@8.1.1(dnd-core@16.0.1):
dependencies:
dnd-core: 16.0.1
@@ -7072,7 +7095,7 @@ snapshots:
has-proto: 1.2.0
has-symbols: 1.1.0
hasown: 2.0.2
- internal-slot: 1.0.7
+ internal-slot: 1.1.0
is-array-buffer: 3.0.4
is-callable: 1.2.7
is-data-view: 1.0.2
@@ -7081,7 +7104,7 @@ snapshots:
is-shared-array-buffer: 1.0.3
is-string: 1.1.0
is-typed-array: 1.1.13
- is-weakref: 1.0.2
+ is-weakref: 1.1.0
object-inspect: 1.13.3
object-keys: 1.1.1
object.assign: 4.1.5
@@ -7115,8 +7138,8 @@ snapshots:
es-to-primitive@1.3.0:
dependencies:
is-callable: 1.2.7
- is-date-object: 1.0.5
- is-symbol: 1.1.0
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
esbuild@0.21.5:
optionalDependencies:
@@ -7225,7 +7248,7 @@ snapshots:
dependencies:
is-callable: 1.2.7
- force-graph@1.47.0:
+ force-graph@1.47.1:
dependencies:
'@tweenjs/tween.js': 25.0.0
accessor-fn: 1.5.1
@@ -7380,7 +7403,7 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hast-util-to-html@9.0.3:
+ hast-util-to-html@9.0.4:
dependencies:
'@types/hast': 3.0.4
'@types/unist': 3.0.3
@@ -7483,7 +7506,7 @@ snapshots:
dependencies:
css-in-js-utils: 3.1.0
- internal-slot@1.0.7:
+ internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
hasown: 2.0.2
@@ -7524,9 +7547,9 @@ snapshots:
dependencies:
has-bigints: 1.0.2
- is-boolean-object@1.2.0:
+ is-boolean-object@1.2.1:
dependencies:
- call-bind: 1.0.8
+ call-bound: 1.0.2
has-tostringtag: 1.0.2
is-callable@1.2.7: {}
@@ -7541,8 +7564,9 @@ snapshots:
get-intrinsic: 1.2.6
is-typed-array: 1.1.13
- is-date-object@1.0.5:
+ is-date-object@1.1.0:
dependencies:
+ call-bound: 1.0.2
has-tostringtag: 1.0.2
is-decimal@1.0.4: {}
@@ -7610,9 +7634,9 @@ snapshots:
dependencies:
better-path-resolve: 1.0.0
- is-symbol@1.1.0:
+ is-symbol@1.1.1:
dependencies:
- call-bind: 1.0.8
+ call-bound: 1.0.2
has-symbols: 1.1.0
safe-regex-test: 1.1.0
@@ -7622,9 +7646,9 @@ snapshots:
is-weakmap@2.0.2: {}
- is-weakref@1.0.2:
+ is-weakref@1.1.0:
dependencies:
- call-bind: 1.0.8
+ call-bound: 1.0.2
is-weakset@2.0.3:
dependencies:
@@ -7876,7 +7900,7 @@ snapshots:
devlop: 1.1.0
mdast-util-from-markdown: 2.0.2
mdast-util-to-markdown: 2.1.2
- parse-entities: 4.0.1
+ parse-entities: 4.0.2
stringify-entities: 4.0.4
unist-util-stringify-position: 4.0.0
vfile-message: 4.0.2
@@ -8327,10 +8351,9 @@ snapshots:
is-decimal: 1.0.4
is-hexadecimal: 1.0.4
- parse-entities@4.0.1:
+ parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
- character-entities: 2.0.2
character-entities-legacy: 3.0.0
character-reference-invalid: 2.0.1
decode-named-character-reference: 1.0.2
@@ -8425,9 +8448,9 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
- rdndmb-html5-to-touch@8.1.0(dnd-core@16.0.1):
+ rdndmb-html5-to-touch@8.1.1(dnd-core@16.0.1):
dependencies:
- dnd-multi-backend: 8.1.0(dnd-core@16.0.1)
+ dnd-multi-backend: 8.1.1(dnd-core@16.0.1)
react-dnd-html5-backend: 16.0.1
react-dnd-touch-backend: 16.0.1
transitivePeerDependencies:
@@ -8459,16 +8482,16 @@ snapshots:
dependencies:
dnd-core: 16.0.1
- react-dnd-multi-backend@8.1.0(dnd-core@16.0.1)(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ react-dnd-multi-backend@8.1.1(dnd-core@16.0.1)(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
dnd-core: 16.0.1
- dnd-multi-backend: 8.1.0(dnd-core@16.0.1)
+ dnd-multi-backend: 8.1.1(dnd-core@16.0.1)
react: 18.3.1
react-dnd: 16.0.1(@types/react@18.3.16)(react@18.3.1)
- react-dnd-preview: 8.1.0(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)
+ react-dnd-preview: 8.1.1(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)
react-dom: 18.3.1(react@18.3.1)
- react-dnd-preview@8.1.0(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react@18.3.1):
+ react-dnd-preview@8.1.1(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
react-dnd: 16.0.1(@types/react@18.3.16)(react@18.3.1)
@@ -8516,25 +8539,25 @@ snapshots:
react-force-graph-2d@1.26.1(react@18.3.1):
dependencies:
- force-graph: 1.47.0
+ force-graph: 1.47.1
prop-types: 15.8.1
react: 18.3.1
- react-kapsule: 2.5.2(react@18.3.1)
+ react-kapsule: 2.5.6(react@18.3.1)
react-force-graph-3d@1.25.1(react@18.3.1):
dependencies:
- 3d-force-graph: 1.74.2
+ 3d-force-graph: 1.74.3
prop-types: 15.8.1
react: 18.3.1
- react-kapsule: 2.5.2(react@18.3.1)
+ react-kapsule: 2.5.6(react@18.3.1)
- react-hook-form@7.54.0(react@18.3.1):
+ react-hook-form@7.54.1(react@18.3.1):
dependencies:
react: 18.3.1
react-is@16.13.1: {}
- react-kapsule@2.5.2(react@18.3.1):
+ react-kapsule@2.5.6(react@18.3.1):
dependencies:
jerrypick: 1.1.1
react: 18.3.1
@@ -8562,11 +8585,11 @@ snapshots:
immutability-helper: 3.1.1
lodash: 4.17.21
prop-types: 15.8.1
- rdndmb-html5-to-touch: 8.1.0(dnd-core@16.0.1)
+ rdndmb-html5-to-touch: 8.1.1(dnd-core@16.0.1)
react: 18.3.1
react-dnd: 16.0.1(@types/react@18.3.16)(react@18.3.1)
react-dnd-html5-backend: 16.0.1
- react-dnd-multi-backend: 8.1.0(dnd-core@16.0.1)(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-dnd-multi-backend: 8.1.1(dnd-core@16.0.1)(react-dnd@16.0.1(@types/react@18.3.16)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-dnd-touch-backend: 16.0.1
uuid: 9.0.1
transitivePeerDependencies:
@@ -8708,7 +8731,7 @@ snapshots:
es-errors: 1.3.0
get-intrinsic: 1.2.6
gopd: 1.2.0
- which-builtin-type: 1.2.0
+ which-builtin-type: 1.2.1
regenerate-unicode-properties@10.2.0:
dependencies:
@@ -9029,7 +9052,7 @@ snapshots:
get-intrinsic: 1.2.6
gopd: 1.2.0
has-symbols: 1.1.0
- internal-slot: 1.0.7
+ internal-slot: 1.1.0
regexp.prototype.flags: 1.5.3
set-function-name: 2.0.2
side-channel: 1.1.0
@@ -9112,7 +9135,7 @@ snapshots:
textarea-caret@3.0.2: {}
- three-forcegraph@1.42.5(three@0.170.0):
+ three-forcegraph@1.42.8(three@0.170.0):
dependencies:
accessor-fn: 1.5.1
d3-array: 3.2.4
@@ -9126,7 +9149,7 @@ snapshots:
three: 0.170.0
tinycolor2: 1.6.0
- three-render-objects@1.32.0(three@0.170.0):
+ three-render-objects@1.32.1(three@0.170.0):
dependencies:
'@tweenjs/tween.js': 25.0.0
accessor-fn: 1.5.1
@@ -9134,7 +9157,7 @@ snapshots:
polished: 4.3.1
three: 0.170.0
- three-spritetext@1.9.2(three@0.170.0):
+ three-spritetext@1.9.3(three@0.170.0):
dependencies:
three: 0.170.0
@@ -9298,9 +9321,9 @@ snapshots:
upath@1.2.0: {}
- update-browserslist-db@1.1.1(browserslist@4.24.2):
+ update-browserslist-db@1.1.1(browserslist@4.24.3):
dependencies:
- browserslist: 4.24.2
+ browserslist: 4.24.3
escalade: 3.2.0
picocolors: 1.1.1
@@ -9389,22 +9412,22 @@ snapshots:
which-boxed-primitive@1.1.0:
dependencies:
is-bigint: 1.1.0
- is-boolean-object: 1.2.0
+ is-boolean-object: 1.2.1
is-number-object: 1.1.0
is-string: 1.1.0
- is-symbol: 1.1.0
+ is-symbol: 1.1.1
- which-builtin-type@1.2.0:
+ which-builtin-type@1.2.1:
dependencies:
- call-bind: 1.0.8
+ call-bound: 1.0.2
function.prototype.name: 1.1.6
has-tostringtag: 1.0.2
is-async-function: 2.0.0
- is-date-object: 1.0.5
+ is-date-object: 1.1.0
is-finalizationregistry: 1.1.0
is-generator-function: 1.0.10
is-regex: 1.2.1
- is-weakref: 1.0.2
+ is-weakref: 1.1.0
isarray: 2.0.5
which-boxed-primitive: 1.1.0
which-collection: 1.0.2
diff --git a/src/components/cashu/inline-cashu-card.tsx b/src/components/cashu/inline-cashu-card.tsx
index bf4fff132..5d3d338fe 100644
--- a/src/components/cashu/inline-cashu-card.tsx
+++ b/src/components/cashu/inline-cashu-card.tsx
@@ -3,7 +3,6 @@ import { Box, Button, ButtonGroup, Card, CardProps, Heading, IconButton, Link, S
import { Token, getEncodedToken, CheckStateEnum } from "@cashu/cashu-ts";
import { CopyIconButton } from "../copy-icon-button";
-import useUserProfile from "../../hooks/use-user-profile";
import useCurrentAccount from "../../hooks/use-current-account";
import { ECashIcon, WalletIcon } from "../icons";
import CurrencyDollar from "../icons/currency-dollar";
@@ -14,28 +13,11 @@ import CurrencyPound from "../icons/currency-pound";
import CurrencyBitcoin from "../icons/currency-bitcoin";
import { getMintWallet } from "../../services/cashu-mints";
-function RedeemButton({ token }: { token: string }) {
- const account = useCurrentAccount()!;
- const metadata = useUserProfile(account.pubkey);
-
- const lnurl = metadata?.lud16 ?? "";
- const url = `https://redeem.cashu.me?token=${encodeURIComponent(token)}&lightning=${encodeURIComponent(
- lnurl,
- )}&autopay=yes`;
- return (
-
- );
-}
-
export default function InlineCachuCard({
token,
encoded,
...props
}: Omit & { token: Token; encoded?: string }) {
- const account = useCurrentAccount();
-
encoded = encoded || getEncodedToken(token);
const { value: spendable, loading } = useAsync(async () => {
if (!token) return;
@@ -84,7 +66,7 @@ export default function InlineCachuCard({
}
return (
-
+
@@ -96,7 +78,6 @@ export default function InlineCachuCard({
aria-label="Open Wallet"
href={`cashu://` + encoded}
/>
- {account && }
{denomination} {spendable === false ? " (Spent)" : loading ? : undefined}
@@ -105,7 +86,6 @@ export default function InlineCachuCard({
{token.unit && Unit: {token.unit}}
{token.memo && {token.memo}}
- {loading && }
);
}
diff --git a/src/components/sensitive-content-warning.tsx b/src/components/content-warning.tsx
similarity index 92%
rename from src/components/sensitive-content-warning.tsx
rename to src/components/content-warning.tsx
index a66a56f43..ff923c4c1 100644
--- a/src/components/sensitive-content-warning.tsx
+++ b/src/components/content-warning.tsx
@@ -3,7 +3,7 @@ import { Alert, AlertDescription, AlertIcon, AlertProps, AlertTitle, Button, Spa
import { useExpand } from "../providers/local/expanded";
import { useBreakpointValue } from "../providers/global/breakpoint-provider";
-export default function SensitiveContentWarning({ description }: { description?: string } & AlertProps) {
+export default function ContentWarning({ description }: { description?: string } & AlertProps) {
const expand = useExpand();
const smallScreen = useBreakpointValue({ base: true, md: false });
diff --git a/src/components/event-zap-modal/index.tsx b/src/components/event-zap-modal/index.tsx
index d29f9ad22..b70b203e8 100644
--- a/src/components/event-zap-modal/index.tsx
+++ b/src/components/event-zap-modal/index.tsx
@@ -12,9 +12,9 @@ import dayjs from "dayjs";
import { kinds } from "nostr-tools";
import { getValue } from "applesauce-core/observable";
import { getInboxes, getInvoice, getOutboxes, safeRelayUrls } from "applesauce-core/helpers";
+import { getZapSplits } from "applesauce-core/helpers/zap";
import { DraftNostrEvent, NostrEvent, isDTag } from "../../types/nostr-event";
-import { getZapSplits } from "../../helpers/nostr/zaps";
import { unique } from "../../helpers/array";
import relayScoreboardService from "../../services/relay-scoreboard";
import { getEventCoordinate, isReplaceable } from "../../helpers/nostr/event";
@@ -122,7 +122,7 @@ async function getPayRequestsForEvent(
fallbackPubkey?: string,
additionalRelays?: Iterable,
) {
- const splits = getZapSplits(event, fallbackPubkey);
+ const splits = getZapSplits(event) ?? (fallbackPubkey ? [{ pubkey: fallbackPubkey, percent: 1, weight: 1 }] : []);
const draftZapRequests: PayRequest[] = [];
for (const { pubkey, percent } of splits) {
diff --git a/src/components/event-zap-modal/input-step.tsx b/src/components/event-zap-modal/input-step.tsx
index 580614eaa..db6ed1ed7 100644
--- a/src/components/event-zap-modal/input-step.tsx
+++ b/src/components/event-zap-modal/input-step.tsx
@@ -1,11 +1,11 @@
import { Box, Button, Flex, Input, Text } from "@chakra-ui/react";
+import { getZapSplits } from "applesauce-core/helpers";
import { useForm } from "react-hook-form";
import { NostrEvent } from "../../types/nostr-event";
import { humanReadableSats } from "../../helpers/lightning";
import { LightningIcon } from "../icons";
import useUserLNURLMetadata from "../../hooks/use-user-lnurl-metadata";
-import { getZapSplits } from "../../helpers/nostr/zaps";
import { EmbedEvent, EmbedProps } from "../embed-event";
import useAppSettings from "../../hooks/use-app-settings";
import CustomZapAmountOptions from "./zap-options";
@@ -71,7 +71,7 @@ export default function InputStep({
},
});
- const splits = event ? getZapSplits(event, pubkey) : [];
+ const splits = event ? (getZapSplits(event) ?? []) : [];
const { metadata: lnurlMetadata } = useUserLNURLMetadata(pubkey);
const canZap = lnurlMetadata?.allowsNostr && lnurlMetadata?.nostrPubkey;
diff --git a/src/components/note/timeline-note/note-content-with-warning.tsx b/src/components/note/timeline-note/note-content-with-warning.tsx
index bcaedf4ea..eea83b7c8 100644
--- a/src/components/note/timeline-note/note-content-with-warning.tsx
+++ b/src/components/note/timeline-note/note-content-with-warning.tsx
@@ -1,19 +1,20 @@
import { NostrEvent } from "nostr-tools";
+import { getContentWarning } from "applesauce-core/helpers";
import { TextNoteContents } from "./text-note-contents";
import { useExpand } from "../../../providers/local/expanded";
-import SensitiveContentWarning from "../../sensitive-content-warning";
+import ContentWarning from "../../content-warning";
import useAppSettings from "../../../hooks/use-app-settings";
export default function NoteContentWithWarning({ event }: { event: NostrEvent }) {
const expand = useExpand();
const settings = useAppSettings();
- const contentWarningTag = event.tags.find((t) => t[0] === "content-warning");
- const showContentWarning = settings.showContentWarning && contentWarningTag && !expand?.expanded;
+ const warning = getContentWarning(event);
+ const showContentWarning = settings.showContentWarning && !!warning && !expand?.expanded;
return showContentWarning ? (
-
+
) : (
);
diff --git a/src/components/post-modal/index.tsx b/src/components/post-modal/index.tsx
index 13b4448bc..da72ee9d3 100644
--- a/src/components/post-modal/index.tsx
+++ b/src/components/post-modal/index.tsx
@@ -12,8 +12,6 @@ import {
Input,
Switch,
ModalProps,
- VisuallyHiddenInput,
- IconButton,
FormLabel,
FormControl,
FormHelperText,
@@ -28,30 +26,20 @@ import {
ButtonGroup,
Text,
} from "@chakra-ui/react";
-import dayjs from "dayjs";
import { useForm } from "react-hook-form";
-import { kinds, UnsignedEvent } from "nostr-tools";
-import { useThrottle } from "react-use";
+import { EventTemplate, UnsignedEvent } from "nostr-tools";
+import { useAsync, useThrottle } from "react-use";
import { useEventFactory, useObservable } from "applesauce-react/hooks";
+import { Emoji, ZapSplit } from "applesauce-core/helpers";
-import { ChevronDownIcon, ChevronUpIcon, UploadImageIcon } from "../icons";
+import { ChevronDownIcon, ChevronUpIcon } from "../icons";
import PublishAction from "../../classes/nostr-publish-action";
import { PublishDetails } from "../../views/task-manager/publish-log/publish-details";
import { TrustProvider } from "../../providers/local/trust-provider";
-import {
- correctContentMentions,
- createEmojiTags,
- ensureNotifyPubkeys,
- finalizeNote,
- getPubkeysMentionedInContent,
- setZapSplit,
-} from "../../helpers/nostr/post";
-import { UserAvatarStack } from "../compact-user-stack";
import MagicTextArea, { RefType } from "../magic-textarea";
import { useContextEmojis } from "../../providers/global/emoji-provider";
import CommunitySelect from "./community-select";
-import ZapSplitCreator, { fillRemainingPercent } from "./zap-split-creator";
-import { EventSplit } from "../../helpers/nostr/zaps";
+import ZapSplitCreator from "./zap-split-creator";
import useCurrentAccount from "../../hooks/use-current-account";
import useCacheForm from "../../hooks/use-cache-form";
import useTextAreaUploadFile, { useTextAreaInsertTextWithForm } from "../../hooks/use-textarea-upload-file";
@@ -64,7 +52,6 @@ import localSettings from "../../services/local-settings";
import useLocalStorageDisclosure from "../../hooks/use-localstorage-disclosure";
import InsertGifButton from "../gif/insert-gif-button";
import InsertImageButton from "./insert-image-button";
-import { unixNow } from "applesauce-core/helpers";
type FormValues = {
subject: string;
@@ -72,7 +59,7 @@ type FormValues = {
nsfw: boolean;
nsfwReason: string;
community: string;
- split: EventSplit;
+ split: Omit[];
difficulty: number;
};
@@ -111,7 +98,7 @@ export default function PostModal({
nsfw: false,
nsfwReason: "",
community: initCommunity,
- split: [] as EventSplit,
+ split: [] as Omit[],
difficulty: noteDifficulty || 0,
},
mode: "all",
@@ -128,47 +115,34 @@ export default function PostModal({
// cache form to localStorage
useCacheForm(cacheFormKey, getValues, reset, formState);
- const updateDraft = useCallback(
- async (values = getValues()) => {
- const { content, nsfw, nsfwReason, community, split, subject } = values;
+ const getDraft = async (values = getValues()) => {
+ // build draft using factory
+ let draft = await factory.note(values.content, {
+ emojis: emojis.filter((e) => !!e.url) as Emoji[],
+ contentWarning: values.nsfw ? values.nsfwReason || values.nsfw : false,
+ splits: values.split,
+ });
- let draft = finalizeNote({
- kind: kinds.ShortTextNote,
- content,
- tags: [],
- created_at: unixNow(),
- });
+ // TODO: remove when NIP-72 communities are removed
+ if (values.community) draft.tags.push(["a", values.community]);
+ if (values.subject) draft.tags.push(["subject", values.subject]);
- if (nsfw) draft.tags.push(nsfwReason ? ["content-warning", nsfwReason] : ["content-warning"]);
- if (community) draft.tags.push(["a", community]);
- if (subject) draft.tags.push(["subject", subject]);
+ const unsigned = await finalizeDraft(draft);
- const contentMentions = getPubkeysMentionedInContent(draft.content);
- draft = createEmojiTags(draft, emojis);
- draft = ensureNotifyPubkeys(draft, contentMentions);
- if (split.length > 0) {
- draft = setZapSplit(draft, fillRemainingPercent(split, account.pubkey));
- }
-
- const unsigned = await finalizeDraft(draft);
- setDraft(unsigned);
- return unsigned;
- },
- [getValues, emojis, finalizeDraft, setDraft, factory],
- );
+ setDraft(unsigned);
+ return unsigned;
+ };
// throttle update the draft every 500ms
- const throttleValues = useThrottle(JSON.stringify(getValues()), 500);
- useEffect(() => {
- updateDraft(getValues());
- }, [throttleValues]);
+ const throttleValues = useThrottle(getValues(), 500);
+ const { value: preview } = useAsync(() => getDraft(), [throttleValues]);
const textAreaRef = useRef(null);
const insertText = useTextAreaInsertTextWithForm(textAreaRef, getValues, setValue);
const { onPaste } = useTextAreaUploadFile(insertText);
const publishPost = async (unsigned?: UnsignedEvent) => {
- unsigned = unsigned || draft || (await updateDraft());
+ unsigned = unsigned || draft || (await getDraft());
const pub = await publish("Post", unsigned);
if (pub) setPublishAction(pub);
@@ -177,13 +151,12 @@ export default function PostModal({
if (values.difficulty > 0) {
setMiningTarget(values.difficulty);
} else {
- const unsigned = await updateDraft(values);
+ const unsigned = await getDraft(values);
publishPost(unsigned);
}
});
const canSubmit = getValues().content.length > 0;
- const mentions = getPubkeysMentionedInContent(correctContentMentions(getValues().content));
const renderBody = () => {
if (publishAction) {
@@ -229,13 +202,13 @@ export default function PostModal({
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") submit();
}}
/>
- {draft && draft.content.length > 0 && (
+ {preview && preview.content.length > 0 && (
Preview:
-
+
@@ -253,7 +226,6 @@ export default function PostModal({
More Options
- {mentions.length > 0 && }
@@ -305,8 +277,8 @@ export default function PostModal({
setValue("split", s, { shouldDirty: true })}
+ splits={getValues().split}
+ onChange={(splits) => setValue("split", splits, { shouldDirty: true })}
authorPubkey={account?.pubkey}
/>
diff --git a/src/components/post-modal/zap-split-creator.tsx b/src/components/post-modal/zap-split-creator.tsx
index 1a2d5b843..1e030c80b 100644
--- a/src/components/post-modal/zap-split-creator.tsx
+++ b/src/components/post-modal/zap-split-creator.tsx
@@ -7,27 +7,18 @@ import {
NumberInput,
NumberInputField,
NumberInputStepper,
- Text,
useToast,
} from "@chakra-ui/react";
import { CloseIcon } from "@chakra-ui/icons";
import { useForm } from "react-hook-form";
-import { EventSplit } from "../../helpers/nostr/zaps";
import { AddIcon } from "../icons";
import { normalizeToHexPubkey } from "../../helpers/nip19";
import UserAvatar from "../user/user-avatar";
import UserLink from "../user/user-link";
import UserAutocomplete from "../user-autocomplete";
-function getRemainingPercent(split: EventSplit) {
- return Math.round((1 - split.reduce((v, p) => v + p.percent, 0)) * 100) / 100;
-}
-export function fillRemainingPercent(split: EventSplit, pubkey: string) {
- const remainingPercent = getRemainingPercent(split);
- if (remainingPercent === 0) return split;
- return split.concat({ pubkey, percent: remainingPercent });
-}
+type Split = { pubkey: string; weight: number };
function validateNpub(input: string) {
const pubkey = normalizeToHexPubkey(input);
@@ -36,29 +27,20 @@ function validateNpub(input: string) {
}
}
-function AddUserForm({
- onSubmit,
- remainingPercent,
-}: {
- onSubmit: (values: { pubkey: string; percent: number }) => void;
- remainingPercent: number;
-}) {
+function AddUserForm({ onSubmit }: { onSubmit: (values: Split) => void }) {
const toast = useToast();
- const { register, handleSubmit, getValues, setValue, reset, watch } = useForm({
+ const { register, handleSubmit, reset } = useForm({
defaultValues: {
pubkey: "",
- percent: Math.min(remainingPercent, 50),
},
mode: "all",
});
- watch("percent");
const submit = handleSubmit((values) => {
try {
const pubkey = normalizeToHexPubkey(values.pubkey);
if (!pubkey) throw new Error("Invalid npub");
- const percent = values.percent / 100;
- onSubmit({ pubkey, percent });
+ onSubmit({ pubkey, weight: 1 });
reset();
} catch (e) {
if (e instanceof Error) toast({ description: e.message, status: "error" });
@@ -68,88 +50,81 @@ function AddUserForm({
return (
- setValue("percent", n, { shouldDirty: true })}
- >
-
-
-
-
-
-
- } aria-label="Add" type="submit" />
+ } aria-label="Add" type="submit" />
);
}
function UserCard({
pubkey,
- percent,
- showRemove = true,
+ weight,
onRemove,
+ onChange,
}: {
pubkey: string;
- percent: number;
- showRemove?: boolean;
+ weight: number;
onRemove?: () => void;
+ onChange?: (split: Split) => void;
}) {
return (
-
- {Math.round(percent * 10000) / 100}%
-
- {showRemove && (
- }
- aria-label="Remove from split"
- title="Remove"
- onClick={onRemove}
- />
- )}
+
+ onChange?.({ pubkey, weight: Number.isFinite(n) ? n : 1 })}
+ ml="auto"
+ >
+
+
+
+
+
+
+ }
+ aria-label="Remove from split"
+ title="Remove"
+ onClick={onRemove}
+ />
);
}
export default function ZapSplitCreator({
- split,
+ splits,
onChange,
- authorPubkey,
}: {
- split: EventSplit;
- onChange: (split: EventSplit) => void;
+ splits: Split[];
+ onChange: (split: Split[]) => void;
authorPubkey?: string;
}) {
- const remainingPercent = getRemainingPercent(split);
-
- const addUser = ({ pubkey, percent }: { pubkey: string; percent: number }) => {
- if (percent > remainingPercent) throw new Error("Not enough percent left");
- if (split.some((s) => s.pubkey === pubkey)) throw new Error("User already in split");
- onChange(split.concat({ pubkey, percent }));
+ const addUser = ({ pubkey, weight }: Split) => {
+ if (splits.some((s) => s.pubkey === pubkey)) throw new Error("User already in split");
+ onChange(splits.concat({ pubkey, weight }));
};
const removeUser = (pubkey: string) => {
- onChange(split.filter((p) => p.pubkey !== pubkey));
+ onChange(splits.filter((p) => p.pubkey !== pubkey));
+ };
+ const changeUser = (split: Split) => {
+ onChange(splits.map((s) => (s.pubkey === split.pubkey ? split : s)));
};
-
- const displaySplit = authorPubkey ? fillRemainingPercent(split, authorPubkey) : split;
return (
Zap Splits
- {remainingPercent > 0 && }
- {displaySplit.map(({ pubkey, percent }) => (
+
+ {splits.map(({ pubkey, weight }) => (
removeUser(pubkey)}
+ onChange={changeUser}
/>
))}
diff --git a/src/helpers/nostr/post.ts b/src/helpers/nostr/post.ts
index 9fd17f3c8..c98707629 100644
--- a/src/helpers/nostr/post.ts
+++ b/src/helpers/nostr/post.ts
@@ -1,13 +1,9 @@
-import { EventTemplate, kinds, nip18, nip19 } from "nostr-tools";
-import { EventPointer } from "nostr-tools/nip19";
-import { getInboxes, isPTag } from "applesauce-core/helpers";
+import { EventTemplate, nip19 } from "nostr-tools";
import { NostrEvent, Tag } from "../../types/nostr-event";
-import { getMatchEmoji, getMatchHashtag, getMatchNostrLink } from "../regexp";
+import { getMatchNostrLink } from "../regexp";
import { getThreadReferences } from "./event";
import { safeDecode } from "../nip19";
-import { Emoji } from "../../providers/global/emoji-provider";
-import { EventSplit } from "./zaps";
import { unique } from "../array";
import { getEventPointerRelayHint } from "../../services/relay-hints";
@@ -44,23 +40,6 @@ function AddEtag(tags: Tag[], eventId: string, relayHint?: string, type?: string
return [...tags, tag];
}
-/** @deprecated use event factory instead */
-function AddQuotePointerTag(tags: Tag[], pointer: EventPointer) {
- const hint = pointer.relays?.[0] || getEventPointerRelayHint(pointer.id) || "";
-
- const tag: string[] = ["q", pointer.id, hint];
- if (pointer.author) tag.push(pointer.author);
-
- if (tags.some((t) => t[0] === tag[0] && t[1] === tag[1] && t[3] === tag[3])) {
- // replace the tag
- return tags.map((t) => {
- if (t[0] === tag[0] && t[1] === tag[1]) return tag;
- return t;
- });
- }
- return [...tags, tag];
-}
-
/** adds the "root" and "reply" E tags */
export function addReplyTags(draft: EventTemplate, replyTo: NostrEvent) {
const updated: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
@@ -88,10 +67,6 @@ export function ensureNotifyPubkeys(draft: EventTemplate, pubkeys: string[]) {
return updated;
}
-export function correctContentMentions(content: string) {
- return content.replaceAll(/(?<=^|\s)(?:@)?(npub1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58})/gi, "nostr:$1");
-}
-
export function getPubkeysMentionedInContent(content: string, direct = false) {
const matched = content.matchAll(getMatchNostrLink());
@@ -120,11 +95,6 @@ export function getPubkeysMentionedInContent(content: string, direct = false) {
return unique(pubkeys);
}
-export function ensureNotifyContentMentions(draft: EventTemplate) {
- const mentions = getPubkeysMentionedInContent(draft.content);
- return mentions.length > 0 ? ensureNotifyPubkeys(draft, mentions) : draft;
-}
-
export function getAllEventsMentionedInContent(content: string) {
const matched = content.matchAll(getMatchNostrLink());
@@ -146,63 +116,3 @@ export function getAllEventsMentionedInContent(content: string) {
return events;
}
-export function ensureTagContentMentions(draft: EventTemplate) {
- const mentions = getAllEventsMentionedInContent(draft.content);
- const updated: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
-
- for (const pointer of mentions) {
- updated.tags = AddEtag(updated.tags, pointer.id, pointer.relays?.[0] ?? "", "mention", false);
- updated.tags = AddQuotePointerTag(updated.tags, pointer);
- }
-
- return updated;
-}
-
-/** @deprecated use includeContentHashtags from applesauce-factory instead */
-export function createHashtagTags(draft: EventTemplate) {
- const updatedDraft: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
-
- // create tags for all occurrences of #hashtag
- const matches = updatedDraft.content.matchAll(getMatchHashtag());
- for (const [_, space, hashtag] of matches) {
- const lower = hashtag.toLocaleLowerCase();
- if (!updatedDraft.tags.find((t) => t[0] === "t" && t[1] === lower)) {
- updatedDraft.tags.push(["t", lower]);
- }
- }
-
- return updatedDraft;
-}
-
-export function createEmojiTags(draft: EventTemplate, emojis: Emoji[]) {
- const updatedDraft: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
-
- // create tags for all occurrences of #hashtag
- const matches = updatedDraft.content.matchAll(getMatchEmoji());
- for (const [_, name] of matches) {
- const emoji = emojis.find((e) => e.name === name);
- if (emoji?.url) {
- updatedDraft.tags = addTag(updatedDraft.tags, ["emoji", emoji.name, emoji.url]);
- }
- }
-
- return updatedDraft;
-}
-
-export function setZapSplit(draft: EventTemplate, split: EventSplit) {
- const updatedDraft: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
-
- // TODO: get best input relay for user
- const zapTags = split.map((p) => ["zap", p.pubkey, "", String(p.percent * 100)]);
- updatedDraft.tags.push(...zapTags);
-
- return updatedDraft;
-}
-
-/** @deprecated use event factory instead */
-export function finalizeNote(draft: EventTemplate) {
- let updated: EventTemplate = { ...draft, tags: Array.from(draft.tags) };
- updated.content = correctContentMentions(updated.content);
- updated = ensureTagContentMentions(updated);
- return updated;
-}
diff --git a/src/helpers/nostr/stream.ts b/src/helpers/nostr/stream.ts
index d0a8c7e49..2ca0d0570 100644
--- a/src/helpers/nostr/stream.ts
+++ b/src/helpers/nostr/stream.ts
@@ -1,9 +1,6 @@
-import { kinds } from "nostr-tools";
-import { getEventPointerFromETag, getTagValue, safeRelayUrl, unixNow } from "applesauce-core/helpers";
+import { getEventPointerFromETag, getTagValue, safeRelayUrl } from "applesauce-core/helpers";
-import { DraftNostrEvent, NostrEvent, isPTag } from "../../types/nostr-event";
-import { ensureNotifyContentMentions } from "./post";
-import { getEventCoordinate } from "./event";
+import { NostrEvent, isPTag } from "../../types/nostr-event";
export type StreamStatus = "live" | "ended" | "planned";
@@ -80,16 +77,3 @@ export function getStreamParticipants(stream: NostrEvent) {
export function getStreamHashtags(stream: NostrEvent) {
return stream.tags.filter((t) => t[0] === "t").map((t) => t[1]);
}
-
-export function buildChatMessage(stream: NostrEvent, content: string) {
- let draft: DraftNostrEvent = {
- tags: [["a", getEventCoordinate(stream), "", "root"]],
- content,
- created_at: unixNow(),
- kind: kinds.LiveChatMessage,
- };
-
- draft = ensureNotifyContentMentions(draft);
-
- return draft;
-}
diff --git a/src/helpers/nostr/zaps.ts b/src/helpers/nostr/zaps.ts
index 7c28b2d62..7f39d6b8a 100644
--- a/src/helpers/nostr/zaps.ts
+++ b/src/helpers/nostr/zaps.ts
@@ -41,17 +41,3 @@ export function isProfileZap(event: NostrEvent) {
export function totalZaps(zaps: NostrEvent[]) {
return zaps.map(getZapPayment).reduce((t, p) => t + (p?.amount ?? 0), 0);
}
-
-export type EventSplit = { pubkey: string; percent: number; relay?: string }[];
-export function getZapSplits(event: NostrEvent, fallbackPubkey?: string): EventSplit {
- const tags = event.tags.filter((t) => t[0] === "zap" && t[1] && t[3]) as [string, string, string, string][];
-
- if (tags.length > 0) {
- const targets = tags
- .map((t) => ({ pubkey: t[1], relay: t[2], percent: parseFloat(t[3]) }))
- .filter((p) => Number.isFinite(p.percent));
-
- const total = targets.reduce((v, p) => v + p.percent, 0);
- return targets.map((p) => ({ ...p, percent: p.percent / total }));
- } else return [{ pubkey: fallbackPubkey || event.pubkey, relay: "", percent: 1 }];
-}
diff --git a/src/providers/global/event-factory-provider.tsx b/src/providers/global/event-factory-provider.tsx
index 73cab02cb..53b6cff23 100644
--- a/src/providers/global/event-factory-provider.tsx
+++ b/src/providers/global/event-factory-provider.tsx
@@ -1,8 +1,8 @@
+import { PropsWithChildren } from "react";
import { useObservable } from "applesauce-react/hooks";
import { FactoryProvider } from "applesauce-react/providers";
import eventFactoryService from "../../services/event-factory";
-import { PropsWithChildren } from "react";
export default function EventFactoryProvider({ children }: PropsWithChildren) {
const factory = useObservable(eventFactoryService.subject);
diff --git a/src/providers/global/index.tsx b/src/providers/global/index.tsx
index 5b97e982a..ad993750c 100644
--- a/src/providers/global/index.tsx
+++ b/src/providers/global/index.tsx
@@ -34,19 +34,19 @@ export const GlobalProviders = ({ children }: { children: React.ReactNode }) =>
-
-
-
-
-
-
+
+
+
+
+
+
{children}
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/providers/global/publish-provider.tsx b/src/providers/global/publish-provider.tsx
index 5cae63df9..6e321aebb 100644
--- a/src/providers/global/publish-provider.tsx
+++ b/src/providers/global/publish-provider.tsx
@@ -69,25 +69,7 @@ export default function PublishProvider({ children }: PropsWithChildren) {
const outBoxes = useUserOutbox(account?.pubkey);
const finalizeDraft = useCallback(
- async (event: EventTemplate | NostrEvent) => {
- let draft = cloneEvent(event.kind, event);
-
- // add client tag
- if (
- localSettings.addClientTag.value &&
- !NEVER_ATTACH_CLIENT_TAG.includes(draft.kind) &&
- !draft.tags.some((t) => t[0] === "client")
- ) {
- // TODO: this should be removed when all events are created using the event factory
- draft = await includeClientTag(
- NIP_89_CLIENT_APP.name,
- NIP_89_CLIENT_APP.address ? { ...NIP_89_CLIENT_APP.address, kind: kinds.Handlerinformation } : undefined,
- )(draft, {});
- }
-
- // request signature
- return await signerFinalize(draft);
- },
+ (event: EventTemplate | NostrEvent) => signerFinalize(event),
[signerFinalize],
);
diff --git a/src/services/event-factory.ts b/src/services/event-factory.ts
index acceaa5e7..7519dd164 100644
--- a/src/services/event-factory.ts
+++ b/src/services/event-factory.ts
@@ -1,9 +1,12 @@
import { BehaviorSubject, Observable } from "rxjs";
import { EventFactory } from "applesauce-factory";
+import { combineLatest } from "rxjs";
+
import { Account } from "../classes/accounts/account";
import { getEventRelayHint, getPubkeyRelayHint } from "./relay-hints";
import { NIP_89_CLIENT_APP } from "../const";
import accountService from "./account";
+import localSettings from "./local-settings";
class EventFactoryService {
subject = new BehaviorSubject(null);
@@ -12,22 +15,20 @@ class EventFactoryService {
return this.subject.value;
}
- constructor(account: Observable) {
- account.subscribe((current) => {
- if (!current) this.subject.next(null);
- else
- this.subject.next(
- new EventFactory({
- signer: current.signer,
- getRelayHint: getEventRelayHint,
- getPubkeyRelayHint: getPubkeyRelayHint,
- client: NIP_89_CLIENT_APP,
- }),
- );
+ constructor(account: Observable, includeClient: Observable) {
+ combineLatest([account, includeClient]).subscribe(([current, client]) => {
+ this.subject.next(
+ new EventFactory({
+ signer: current ? current.signer : undefined,
+ getRelayHint: getEventRelayHint,
+ getPubkeyRelayHint: getPubkeyRelayHint,
+ client: client ? NIP_89_CLIENT_APP : undefined,
+ }),
+ );
});
}
}
-const eventFactoryService = new EventFactoryService(accountService.current);
+const eventFactoryService = new EventFactoryService(accountService.current, localSettings.addClientTag);
export default eventFactoryService;
diff --git a/src/views/streams/stream/stream-chat/stream-chat-form.tsx b/src/views/streams/stream/stream-chat/stream-chat-form.tsx
index 698625165..5c5d87a52 100644
--- a/src/views/streams/stream/stream-chat/stream-chat-form.tsx
+++ b/src/views/streams/stream/stream-chat/stream-chat-form.tsx
@@ -2,10 +2,12 @@ import { useMemo, useRef } from "react";
import { Box, Button, Flex, useToast } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
import { NostrEvent } from "nostr-tools";
+import { useEventFactory } from "applesauce-react/hooks";
+import { LiveChatMessageBlueprint } from "applesauce-factory/blueprints";
+import { Emoji } from "applesauce-core/helpers";
-import { buildChatMessage, getStreamHost } from "../../../../helpers/nostr/stream";
+import { getStreamHost } from "../../../../helpers/nostr/stream";
import { unique } from "../../../../helpers/array";
-import { createEmojiTags, ensureNotifyContentMentions } from "../../../../helpers/nostr/post";
import { useContextEmojis } from "../../../../providers/global/emoji-provider";
import { MagicInput, RefType } from "../../../../components/magic-textarea";
import StreamZapButton from "../../components/stream-zap-button";
@@ -19,22 +21,27 @@ import InsertGifButton from "../../../../components/gif/insert-gif-button";
export default function ChatMessageForm({ stream, hideZapButton }: { stream: NostrEvent; hideZapButton?: boolean }) {
const toast = useToast();
const publish = usePublishEvent();
+ const factory = useEventFactory();
const emojis = useContextEmojis();
const streamRelays = useReadRelays(useAdditionalRelayContext());
const host = getStreamHost(stream);
const hostReadRelays = useUserInbox(host);
- const relays = useMemo(() => unique([...streamRelays, ...(hostReadRelays ?? [])]), [hostReadRelays, streamRelays]);
+ const writeRelays = useMemo(
+ () => unique([...streamRelays, ...(hostReadRelays ?? [])]),
+ [hostReadRelays, streamRelays],
+ );
const { setValue, handleSubmit, formState, reset, getValues, watch } = useForm({
defaultValues: { content: "" },
});
const sendMessage = handleSubmit(async (values) => {
try {
- let draft = buildChatMessage(stream, values.content);
- draft = ensureNotifyContentMentions(draft);
- draft = createEmojiTags(draft, emojis);
- const pub = await publish("Send Chat", draft, relays);
+ const draft = await factory.create(LiveChatMessageBlueprint, stream, values.content, {
+ emojis: emojis.filter((e) => !!e.url) as Emoji[],
+ });
+
+ const pub = await publish("Send Chat", draft, writeRelays);
if (pub) reset();
} catch (error) {
if (error instanceof Error) toast({ description: error.message, status: "error" });
diff --git a/src/views/thread/components/reply-form.tsx b/src/views/thread/components/reply-form.tsx
index 3262d0d70..dbf526ad4 100644
--- a/src/views/thread/components/reply-form.tsx
+++ b/src/views/thread/components/reply-form.tsx
@@ -1,26 +1,16 @@
import { useMemo, useRef } from "react";
import { Box, Button, ButtonGroup, Flex } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
-import { useThrottle } from "react-use";
+import { useAsync, useThrottle } from "react-use";
import { kinds } from "nostr-tools";
import { ThreadItem } from "applesauce-core/queries";
-import dayjs from "dayjs";
+import { useEventFactory } from "applesauce-react/hooks";
+import { Emoji } from "applesauce-core/helpers";
import { NostrEvent } from "../../../types/nostr-event";
-import { UserAvatarStack } from "../../../components/compact-user-stack";
-import { getThreadMembers } from "../../../helpers/thread";
-import {
- addReplyTags,
- createEmojiTags,
- ensureNotifyPubkeys,
- finalizeNote,
- getPubkeysMentionedInContent,
-} from "../../../helpers/nostr/post";
-import useCurrentAccount from "../../../hooks/use-current-account";
import MagicTextArea, { RefType } from "../../../components/magic-textarea";
import { useContextEmojis } from "../../../providers/global/emoji-provider";
import { TrustProvider } from "../../../providers/local/trust-provider";
-import { unique } from "../../../helpers/array";
import { usePublishEvent } from "../../../providers/global/publish-provider";
import { TextNoteContents } from "../../../components/note/timeline-note/text-note-contents";
import useCacheForm from "../../../hooks/use-cache-form";
@@ -37,10 +27,10 @@ export type ReplyFormProps = {
export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kinds.ShortTextNote }: ReplyFormProps) {
const publish = usePublishEvent();
- const account = useCurrentAccount();
+ const factory = useEventFactory();
const emojis = useContextEmojis();
+ const customEmojis = useMemo(() => emojis.filter((e) => !!e.url) as Emoji[], [emojis]);
- const threadMembers = useMemo(() => getThreadMembers(item, account?.pubkey), [item, account?.pubkey]);
const { setValue, getValues, watch, handleSubmit, formState, reset } = useForm({
defaultValues: {
content: "",
@@ -50,32 +40,31 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin
const clearCache = useCacheForm<{ content: string }>(`reply-${item.event.id}`, getValues, reset, formState);
- const contentMentions = getPubkeysMentionedInContent(getValues().content);
- const notifyPubkeys = unique([...threadMembers, ...contentMentions]);
-
watch("content");
const textAreaRef = useRef(null);
const insertText = useTextAreaInsertTextWithForm(textAreaRef, getValues, setValue);
const { onPaste } = useTextAreaUploadFile(insertText);
- const draft = useMemo(() => {
- let updated = finalizeNote({ kind: replyKind, content: getValues().content, created_at: dayjs().unix(), tags: [] });
- updated = createEmojiTags(updated, emojis);
- updated = addReplyTags(updated, item.event);
- updated = ensureNotifyPubkeys(updated, notifyPubkeys);
- return updated;
- }, [getValues().content, emojis]);
-
const submit = handleSubmit(async (values) => {
- const pub = await publish("Reply", { ...draft, created_at: dayjs().unix() });
+ const draft = await factory.noteReply(item.event, values.content, {
+ emojis: customEmojis,
+ });
+
+ const pub = await publish("Reply", draft);
if (pub && onSubmitted) onSubmitted(pub.event);
clearCache();
});
const formRef = useRef(null);
- const previewDraft = useThrottle(draft, 500);
+
+ // throttle preview
+ const throttleValues = useThrottle(getValues(), 500);
+ const { value: preview } = useAsync(
+ () => factory.noteReply(item.event, throttleValues.content, { emojis: customEmojis }),
+ [throttleValues, customEmojis],
+ );
return (
@@ -96,7 +85,6 @@ export default function ReplyForm({ item, onCancel, onSubmitted, replyKind = kin
-
{onCancel && }
- {previewDraft.content.length > 0 && (
+ {preview && preview.content.length > 0 && (
-
+
)}