21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022-2023 Mutiny Wallet Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
11
package.json
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "mws",
|
||||
"version": "0.1.1",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "solid-start dev",
|
||||
"build": "solid-start build",
|
||||
@@ -9,9 +10,9 @@
|
||||
},
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.16.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
||||
"@typescript-eslint/parser": "^5.59.2",
|
||||
"@types/node": "^18.16.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
||||
"@typescript-eslint/parser": "^5.59.5",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"esbuild": "^0.14.54",
|
||||
"eslint": "^8.40.0",
|
||||
@@ -32,7 +33,7 @@
|
||||
"@kobalte/core": "^0.8.2",
|
||||
"@kobalte/tailwindcss": "^0.5.0",
|
||||
"@modular-forms/solid": "^0.13.2",
|
||||
"@mutinywallet/mutiny-wasm": "^0.2.8",
|
||||
"@mutinywallet/mutiny-wasm": "^0.3.0",
|
||||
"@mutinywallet/waila-wasm": "^0.1.5",
|
||||
"@solid-primitives/upload": "^0.0.111",
|
||||
"@solidjs/meta": "^0.28.4",
|
||||
|
||||
148
pnpm-lock.yaml
generated
@@ -11,8 +11,8 @@ dependencies:
|
||||
specifier: ^0.13.2
|
||||
version: 0.13.2(solid-js@1.7.5)
|
||||
'@mutinywallet/mutiny-wasm':
|
||||
specifier: ^0.2.8
|
||||
version: 0.2.8
|
||||
specifier: ^0.3.0
|
||||
version: 0.3.0
|
||||
'@mutinywallet/waila-wasm':
|
||||
specifier: ^0.1.5
|
||||
version: 0.1.5
|
||||
@@ -52,14 +52,14 @@ dependencies:
|
||||
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^18.16.5
|
||||
version: 18.16.5
|
||||
specifier: ^18.16.6
|
||||
version: 18.16.6
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^5.59.2
|
||||
version: 5.59.2(@typescript-eslint/parser@5.59.2)(eslint@8.40.0)(typescript@4.9.5)
|
||||
specifier: ^5.59.5
|
||||
version: 5.59.5(@typescript-eslint/parser@5.59.5)(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^5.59.2
|
||||
version: 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
specifier: ^5.59.5
|
||||
version: 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
autoprefixer:
|
||||
specifier: ^10.4.14
|
||||
version: 10.4.14(postcss@8.4.23)
|
||||
@@ -74,7 +74,7 @@ devDependencies:
|
||||
version: 2.7.1(eslint-plugin-import@2.27.5)(eslint@8.40.0)
|
||||
eslint-plugin-import:
|
||||
specifier: 2.27.5
|
||||
version: 2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
version: 2.27.5(@typescript-eslint/parser@5.59.5)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
eslint-plugin-prettier:
|
||||
specifier: 4.2.1
|
||||
version: 4.2.1(eslint@8.40.0)(prettier@2.8.8)
|
||||
@@ -95,7 +95,7 @@ devDependencies:
|
||||
version: 4.9.5
|
||||
vite:
|
||||
specifier: ^4.3.5
|
||||
version: 4.3.5(@types/node@18.16.5)
|
||||
version: 4.3.5(@types/node@18.16.6)
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.14.7
|
||||
version: 0.14.7(vite@4.3.5)(workbox-build@6.5.4)(workbox-window@6.5.4)
|
||||
@@ -1590,8 +1590,8 @@ packages:
|
||||
solid-js: 1.7.5
|
||||
dev: false
|
||||
|
||||
/@mutinywallet/mutiny-wasm@0.2.8:
|
||||
resolution: {integrity: sha512-SaLdJTsK4XTW0xmD3Du8AnHw/hvbomxCbyANyA2IbV4aybtPPgRDcGwRsyCegPioYQHP0skqzwsi1E6k44GIBw==}
|
||||
/@mutinywallet/mutiny-wasm@0.3.0:
|
||||
resolution: {integrity: sha512-K+u2u/XMX1269U8af3T/ZvS+SzzrQcVYrdMi420dWCa14gke0vPWbGp+01zN7SCqBL4jp929emHTUZ4YBEpkzQ==}
|
||||
dev: false
|
||||
|
||||
/@mutinywallet/waila-wasm@0.1.5:
|
||||
@@ -1955,8 +1955,8 @@ packages:
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
dev: true
|
||||
|
||||
/@types/node@18.16.5:
|
||||
resolution: {integrity: sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==}
|
||||
/@types/node@18.16.6:
|
||||
resolution: {integrity: sha512-N7KINmeB8IN3vRR8dhgHEp+YpWvGFcpDoh5XZ8jB5a00AdFKCKEyyGTOPTddUf4JqU1ZKTVxkOxakDvchNVI2Q==}
|
||||
|
||||
/@types/offscreencanvas@2019.7.0:
|
||||
resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==}
|
||||
@@ -1965,22 +1965,22 @@ packages:
|
||||
/@types/resolve@1.17.1:
|
||||
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
||||
dependencies:
|
||||
'@types/node': 18.16.5
|
||||
'@types/node': 18.16.6
|
||||
dev: true
|
||||
|
||||
/@types/resolve@1.20.2:
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
/@types/semver@7.3.13:
|
||||
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
|
||||
/@types/semver@7.5.0:
|
||||
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
|
||||
dev: true
|
||||
|
||||
/@types/trusted-types@2.0.3:
|
||||
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.59.2(@typescript-eslint/parser@5.59.2)(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==}
|
||||
/@typescript-eslint/eslint-plugin@5.59.5(@typescript-eslint/parser@5.59.5)(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^5.0.0
|
||||
@@ -1991,10 +1991,10 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.5.1
|
||||
'@typescript-eslint/parser': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/scope-manager': 5.59.2
|
||||
'@typescript-eslint/type-utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/scope-manager': 5.59.5
|
||||
'@typescript-eslint/type-utils': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
debug: 4.3.4
|
||||
eslint: 8.40.0
|
||||
grapheme-splitter: 1.0.4
|
||||
@@ -2007,8 +2007,8 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.59.2(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==}
|
||||
/@typescript-eslint/parser@5.59.5(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
@@ -2017,9 +2017,9 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 5.59.2
|
||||
'@typescript-eslint/types': 5.59.2
|
||||
'@typescript-eslint/typescript-estree': 5.59.2(typescript@4.9.5)
|
||||
'@typescript-eslint/scope-manager': 5.59.5
|
||||
'@typescript-eslint/types': 5.59.5
|
||||
'@typescript-eslint/typescript-estree': 5.59.5(typescript@4.9.5)
|
||||
debug: 4.3.4
|
||||
eslint: 8.40.0
|
||||
typescript: 4.9.5
|
||||
@@ -2027,16 +2027,16 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/scope-manager@5.59.2:
|
||||
resolution: {integrity: sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==}
|
||||
/@typescript-eslint/scope-manager@5.59.5:
|
||||
resolution: {integrity: sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 5.59.2
|
||||
'@typescript-eslint/visitor-keys': 5.59.2
|
||||
'@typescript-eslint/types': 5.59.5
|
||||
'@typescript-eslint/visitor-keys': 5.59.5
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.59.2(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==}
|
||||
/@typescript-eslint/type-utils@5.59.5(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
@@ -2045,8 +2045,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 5.59.2(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/typescript-estree': 5.59.5(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
debug: 4.3.4
|
||||
eslint: 8.40.0
|
||||
tsutils: 3.21.0(typescript@4.9.5)
|
||||
@@ -2055,13 +2055,13 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/types@5.59.2:
|
||||
resolution: {integrity: sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==}
|
||||
/@typescript-eslint/types@5.59.5:
|
||||
resolution: {integrity: sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/typescript-estree@5.59.2(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==}
|
||||
/@typescript-eslint/typescript-estree@5.59.5(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
@@ -2069,8 +2069,8 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 5.59.2
|
||||
'@typescript-eslint/visitor-keys': 5.59.2
|
||||
'@typescript-eslint/types': 5.59.5
|
||||
'@typescript-eslint/visitor-keys': 5.59.5
|
||||
debug: 4.3.4
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
@@ -2081,18 +2081,18 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.59.2(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==}
|
||||
/@typescript-eslint/utils@5.59.5(eslint@8.40.0)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.40.0)
|
||||
'@types/json-schema': 7.0.11
|
||||
'@types/semver': 7.3.13
|
||||
'@typescript-eslint/scope-manager': 5.59.2
|
||||
'@typescript-eslint/types': 5.59.2
|
||||
'@typescript-eslint/typescript-estree': 5.59.2(typescript@4.9.5)
|
||||
'@types/semver': 7.5.0
|
||||
'@typescript-eslint/scope-manager': 5.59.5
|
||||
'@typescript-eslint/types': 5.59.5
|
||||
'@typescript-eslint/typescript-estree': 5.59.5(typescript@4.9.5)
|
||||
eslint: 8.40.0
|
||||
eslint-scope: 5.1.1
|
||||
semver: 7.5.0
|
||||
@@ -2101,11 +2101,11 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/visitor-keys@5.59.2:
|
||||
resolution: {integrity: sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==}
|
||||
/@typescript-eslint/visitor-keys@5.59.5:
|
||||
resolution: {integrity: sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 5.59.2
|
||||
'@typescript-eslint/types': 5.59.5
|
||||
eslint-visitor-keys: 3.4.1
|
||||
dev: true
|
||||
|
||||
@@ -2343,7 +2343,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001486
|
||||
electron-to-chromium: 1.4.385
|
||||
electron-to-chromium: 1.4.387
|
||||
node-releases: 2.0.10
|
||||
update-browserslist-db: 1.0.11(browserslist@4.21.5)
|
||||
|
||||
@@ -2626,8 +2626,8 @@ packages:
|
||||
jake: 10.8.5
|
||||
dev: true
|
||||
|
||||
/electron-to-chromium@1.4.385:
|
||||
resolution: {integrity: sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==}
|
||||
/electron-to-chromium@1.4.387:
|
||||
resolution: {integrity: sha512-tutLf+alr1/0YqJwKPdstVvDLmxmLb5xNyDLNS0RZmenHcEYk9qKfpKDCVZEKJ00JVbnayJm1MZAbYhYDFpcOw==}
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
@@ -2990,7 +2990,7 @@ packages:
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
eslint: 8.40.0
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.5)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
glob: 7.2.3
|
||||
is-glob: 4.0.3
|
||||
resolve: 1.22.2
|
||||
@@ -2999,7 +2999,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0):
|
||||
/eslint-module-utils@2.8.0(@typescript-eslint/parser@5.59.5)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0):
|
||||
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@@ -3020,7 +3020,7 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
debug: 3.2.7
|
||||
eslint: 8.40.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
@@ -3029,7 +3029,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0):
|
||||
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.5)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0):
|
||||
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
@@ -3039,7 +3039,7 @@ packages:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/parser': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
array-includes: 3.1.6
|
||||
array.prototype.flat: 1.3.1
|
||||
array.prototype.flatmap: 1.3.1
|
||||
@@ -3047,7 +3047,7 @@ packages:
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.40.0
|
||||
eslint-import-resolver-node: 0.3.7
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.59.5)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
|
||||
has: 1.0.3
|
||||
is-core-module: 2.12.0
|
||||
is-glob: 4.0.3
|
||||
@@ -3084,7 +3084,7 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
|
||||
'@typescript-eslint/utils': 5.59.5(eslint@8.40.0)(typescript@4.9.5)
|
||||
eslint: 8.40.0
|
||||
is-html: 2.0.0
|
||||
jsx-ast-utils: 3.3.3
|
||||
@@ -3767,7 +3767,7 @@ packages:
|
||||
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
dependencies:
|
||||
'@types/node': 18.16.5
|
||||
'@types/node': 18.16.6
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 7.2.0
|
||||
dev: true
|
||||
@@ -4577,7 +4577,7 @@ packages:
|
||||
solid-start: 0.2.26(@solidjs/meta@0.28.4)(@solidjs/router@0.8.2)(solid-js@1.7.5)(solid-start-node@0.2.26)(vite@4.3.5)
|
||||
terser: 5.17.2
|
||||
undici: 5.22.0
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -4647,8 +4647,8 @@ packages:
|
||||
solid-start-node: 0.2.26(solid-start@0.2.26)(undici@5.22.0)(vite@4.3.5)
|
||||
terser: 5.17.2
|
||||
undici: 5.22.0
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite-plugin-inspect: 0.7.25(rollup@3.21.5)(vite@4.3.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
vite-plugin-inspect: 0.7.26(rollup@3.21.5)(vite@4.3.5)
|
||||
vite-plugin-solid: 2.7.0(solid-js@1.7.5)(vite@4.3.5)
|
||||
wait-on: 6.0.1(debug@4.3.4)
|
||||
transitivePeerDependencies:
|
||||
@@ -5044,8 +5044,8 @@ packages:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
/vite-plugin-inspect@0.7.25(rollup@3.21.5)(vite@4.3.5):
|
||||
resolution: {integrity: sha512-11j3hG3stRfFkoI+adIDX+KvZueWNgd9lFGdh7lgm0IjGqpP6luCQAMSSnHHV7AZXaTE06X+bUG3M68diz8ZyA==}
|
||||
/vite-plugin-inspect@0.7.26(rollup@3.21.5)(vite@4.3.5):
|
||||
resolution: {integrity: sha512-gRjBay+OxLr/Dr+HXlfJVXZH0cqhE5hkkBvo2du2cA1LGUBnV8Aym89AdPrURkSpTk3Rvw9dNWM2VLIuw6RKJg==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
vite: ^3.1.0 || ^4.0.0
|
||||
@@ -5056,7 +5056,7 @@ packages:
|
||||
fs-extra: 11.1.1
|
||||
picocolors: 1.0.0
|
||||
sirv: 2.0.3
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
@@ -5073,7 +5073,7 @@ packages:
|
||||
fast-glob: 3.2.12
|
||||
pretty-bytes: 6.1.0
|
||||
rollup: 3.21.5
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
workbox-build: 6.5.4
|
||||
workbox-window: 6.5.4
|
||||
transitivePeerDependencies:
|
||||
@@ -5093,7 +5093,7 @@ packages:
|
||||
merge-anything: 5.1.6
|
||||
solid-js: 1.7.5
|
||||
solid-refresh: 0.5.2(solid-js@1.7.5)
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
vitefu: 0.2.4(vite@4.3.5)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -5103,10 +5103,10 @@ packages:
|
||||
peerDependencies:
|
||||
vite: ^2 || ^3 || ^4
|
||||
dependencies:
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
dev: true
|
||||
|
||||
/vite@4.3.5(@types/node@18.16.5):
|
||||
/vite@4.3.5(@types/node@18.16.6):
|
||||
resolution: {integrity: sha512-0gEnL9wiRFxgz40o/i/eTBwm+NEbpUeTWhzKrZDSdKm6nplj+z4lKz8ANDgildxHm47Vg8EUia0aicKbawUVVA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
@@ -5131,7 +5131,7 @@ packages:
|
||||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/node': 18.16.5
|
||||
'@types/node': 18.16.6
|
||||
esbuild: 0.17.18
|
||||
postcss: 8.4.23
|
||||
rollup: 3.21.5
|
||||
@@ -5146,7 +5146,7 @@ packages:
|
||||
vite:
|
||||
optional: true
|
||||
dependencies:
|
||||
vite: 4.3.5(@types/node@18.16.5)
|
||||
vite: 4.3.5(@types/node@18.16.6)
|
||||
|
||||
/wait-on@6.0.1(debug@4.3.4):
|
||||
resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==}
|
||||
|
||||
|
Before Width: | Height: | Size: 526 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 160 KiB |
18
src/assets/icons/coin.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#a)">
|
||||
<mask id="b" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M.667 8A7.333 7.333 0 0 1 8 .667c.368 0 .667.298.667.666v13.334a.667.667 0 0 1-.667.666A7.333 7.333 0 0 1 .667 8Zm6.666-5.963a6 6 0 0 0 0 11.926V2.037Z" fill="#fff"/>
|
||||
<path d="M8 1.333a6.667 6.667 0 1 1 0 13.334V1.333Z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.333 1.333c0-.368.299-.666.667-.666a7.333 7.333 0 1 1 0 14.666.667.667 0 0 1-.667-.666V1.333Zm1.334.704v11.926a6 6 0 0 0 0-11.926Z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.333 4c0-.368.299-.667.667-.667h5a.667.667 0 0 1 0 1.334H3A.667.667 0 0 1 2.333 4ZM1 6.667C1 6.299 1.298 6 1.667 6H8a.667.667 0 0 1 0 1.333H1.667A.667.667 0 0 1 1 6.667Zm0 2.666c0-.368.298-.666.667-.666H8A.667.667 0 1 1 8 10H1.667A.667.667 0 0 1 1 9.333ZM2.333 12c0-.368.299-.667.667-.667h5a.667.667 0 0 1 0 1.334H3A.667.667 0 0 1 2.333 12Z" fill="#fff"/>
|
||||
</mask>
|
||||
<g mask="url(#b)">
|
||||
<path d="M0 0h16v16H0V0Z" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M0 0h16v16H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
16
src/assets/icons/rs.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg width="64" height="57" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="b" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="30" y="10" width="34" height="38">
|
||||
<path fill="url(#a)" d="M30 10h34v38H30z"/>
|
||||
</mask>
|
||||
<g mask="url(#b)">
|
||||
<path d="M49.294 46.586c8.25 0 13.219-4.008 13.219-10.313v-.023c0-5.273-3.07-8.133-10.102-9.586l-3.656-.75c-4.078-.844-5.93-2.25-5.93-4.64v-.024c0-2.695 2.461-4.547 6.422-4.57 3.797 0 6.399 1.758 6.797 4.71l.047.282h5.79l-.024-.399c-.352-5.789-5.18-9.68-12.563-9.68-7.289 0-12.515 4.032-12.539 9.985v.024c0 5.039 3.281 8.132 9.938 9.515l3.632.75c4.36.914 6.118 2.274 6.118 4.805v.023c0 2.907-2.672 4.805-6.938 4.805-4.242 0-7.219-1.805-7.664-4.71l-.047-.282h-5.789l.024.351c.398 6.07 5.507 9.727 13.265 9.727Z" fill="#F61D5B" fill-opacity=".5"/>
|
||||
</g>
|
||||
<path d="M2.977 46h6.046V33.344h6.54L22.218 46h6.89l-7.382-13.57c3.937-1.43 6.375-5.11 6.375-9.657v-.046c0-6.54-4.407-10.547-11.625-10.547h-13.5V46Zm6.046-17.438V17.078h6.704c3.796 0 6.187 2.156 6.187 5.695v.047c0 3.633-2.25 5.742-6.07 5.742h-6.82Z" fill="#F61D5B"/>
|
||||
<path d="M44.86 46.586c8.25 0 13.218-4.008 13.218-10.313v-.023c0-5.273-3.07-8.133-10.101-9.586l-3.657-.75c-4.078-.844-5.93-2.25-5.93-4.64v-.024c0-2.695 2.462-4.547 6.422-4.57 3.797 0 6.399 1.758 6.797 4.71l.047.282h5.79l-.024-.399c-.352-5.789-5.18-9.68-12.563-9.68-7.289 0-12.515 4.032-12.539 9.985v.024c0 5.039 3.282 8.132 9.938 9.515l3.633.75c4.359.914 6.117 2.274 6.117 4.805v.023c0 2.907-2.672 4.805-6.938 4.805-4.242 0-7.218-1.805-7.664-4.71l-.047-.282H31.57l.024.351c.398 6.07 5.508 9.727 13.265 9.727Z" fill="#F61D5B" fill-opacity=".75"/>
|
||||
<defs>
|
||||
<linearGradient id="a" x1="64" y1="29.292" x2="30" y2="29.292" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#black" stop-opacity=".5"/>
|
||||
<stop offset="1" stop-color="#black"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 269 KiB |
BIN
src/assets/wave.gif
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
@@ -1,17 +1,21 @@
|
||||
import send from '~/assets/icons/send.svg';
|
||||
import receive from '~/assets/icons/receive.svg';
|
||||
import { Card, LoadingSpinner, NiceP, SmallAmount, SmallHeader, VStack } from './layout';
|
||||
import { For, Match, ParentComponent, Suspense, Switch, createMemo, createResource, createSignal } from 'solid-js';
|
||||
import { ButtonLink, Card, LoadingSpinner, NiceP, SmallAmount, SmallHeader, VStack } from './layout';
|
||||
import { For, Match, ParentComponent, Show, Suspense, Switch, createMemo, createResource, createSignal } from 'solid-js';
|
||||
import { useMegaStore } from '~/state/megaStore';
|
||||
import { MutinyInvoice } from '@mutinywallet/mutiny-wasm';
|
||||
import { prettyPrintTime } from '~/utils/prettyPrintTime';
|
||||
import { JsonModal } from '~/components/JsonModal';
|
||||
import mempoolTxUrl from '~/utils/mempoolTxUrl';
|
||||
import wave from "~/assets/wave.gif"
|
||||
import utxoIcon from '~/assets/icons/coin.svg';
|
||||
import { getRedshifted } from '~/utils/fakeLabels';
|
||||
|
||||
export const THREE_COLUMNS = 'grid grid-cols-[auto,1fr,auto] gap-4 py-2 px-2 border-b border-neutral-800 last:border-b-0'
|
||||
export const CENTER_COLUMN = 'min-w-0 overflow-hidden max-w-full'
|
||||
export const MISSING_LABEL = 'py-1 px-2 bg-white/10 rounded inline-block text-sm'
|
||||
export const RIGHT_COLUMN = 'flex flex-col items-right text-right max-w-[9rem]'
|
||||
export const REDSHIFT_LABEL = 'py-1 px-2 bg-white text-m-red rounded inline-block text-sm'
|
||||
export const RIGHT_COLUMN = 'flex flex-col items-right text-right max-w-[8rem]'
|
||||
|
||||
export type OnChainTx = {
|
||||
txid: string
|
||||
@@ -26,14 +30,15 @@ export type OnChainTx = {
|
||||
}
|
||||
}
|
||||
|
||||
type Utxo = {
|
||||
export type UtxoItem = {
|
||||
outpoint: string
|
||||
txout: {
|
||||
value: number
|
||||
script_pubkey: string
|
||||
}
|
||||
keychain: string
|
||||
is_spent: boolean
|
||||
is_spent: boolean,
|
||||
redshifted?: boolean
|
||||
}
|
||||
|
||||
const SubtleText: ParentComponent = (props) => {
|
||||
@@ -58,8 +63,7 @@ function OnChainItem(props: { item: OnChainTx }) {
|
||||
</div>
|
||||
<div class={CENTER_COLUMN}>
|
||||
<h2 class={MISSING_LABEL}>Unknown</h2>
|
||||
{isReceive() ? <SmallAmount amount={props.item.received} sign="+" /> : <SmallAmount amount={props.item.sent} />}
|
||||
{/* <h2 class="truncate">Txid: {props.item.txid}</h2> */}
|
||||
{isReceive() ? <SmallAmount amount={props.item.received} /> : <SmallAmount amount={props.item.sent} />}
|
||||
</div>
|
||||
<div class={RIGHT_COLUMN}>
|
||||
<SmallHeader>
|
||||
@@ -99,23 +103,31 @@ function InvoiceItem(props: { item: MutinyInvoice }) {
|
||||
)
|
||||
}
|
||||
|
||||
function Utxo(props: { item: Utxo }) {
|
||||
function Utxo(props: { item: UtxoItem }) {
|
||||
const spent = createMemo(() => props.item.is_spent);
|
||||
|
||||
const [open, setOpen] = createSignal(false)
|
||||
|
||||
const redshifted = createMemo(() => getRedshifted(props.item.outpoint));
|
||||
|
||||
return (
|
||||
<>
|
||||
<JsonModal open={open()} data={props.item} title="Unspent Transaction Output" setOpen={setOpen} />
|
||||
<div class={THREE_COLUMNS} onClick={() => setOpen(!open())}>
|
||||
<img src={receive} alt="receive arrow" />
|
||||
<div class="flex items-center">
|
||||
<img src={utxoIcon} alt="coin" />
|
||||
</div>
|
||||
<div class={CENTER_COLUMN}>
|
||||
<h2 class={MISSING_LABEL}>Unknown</h2>
|
||||
<div class="flex gap-2">
|
||||
<Show when={redshifted()} fallback={<h2 class={MISSING_LABEL}>Unknown</h2>}>
|
||||
<h2 class={REDSHIFT_LABEL}>Redshift</h2>
|
||||
</Show>
|
||||
</div>
|
||||
<SmallAmount amount={props.item.txout.value} />
|
||||
</div>
|
||||
<div class={RIGHT_COLUMN}>
|
||||
<SmallHeader class={spent() ? "text-m-red" : "text-m-green"}>
|
||||
{spent() ? "SPENT" : "UNSPENT"}
|
||||
{/* {spent() ? "SPENT" : "UNSPENT"} */}
|
||||
</SmallHeader>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,19 +140,19 @@ export function Activity() {
|
||||
|
||||
const getTransactions = async () => {
|
||||
console.log("Getting onchain txs");
|
||||
const txs = await state.node_manager?.list_onchain() as OnChainTx[];
|
||||
const txs = await state.mutiny_wallet?.list_onchain() as OnChainTx[];
|
||||
return txs.reverse();
|
||||
}
|
||||
|
||||
const getInvoices = async () => {
|
||||
console.log("Getting invoices");
|
||||
const invoices = await state.node_manager?.list_invoices() as MutinyInvoice[];
|
||||
const invoices = await state.mutiny_wallet?.list_invoices() as MutinyInvoice[];
|
||||
return invoices.filter((inv) => inv.paid).reverse();
|
||||
}
|
||||
|
||||
const getUtXos = async () => {
|
||||
console.log("Getting utxos");
|
||||
const utxos = await state.node_manager?.list_utxos() as Utxo[];
|
||||
const utxos = await state.mutiny_wallet?.list_utxos() as UtxoItem[];
|
||||
return utxos;
|
||||
}
|
||||
|
||||
@@ -201,6 +213,7 @@ export function Activity() {
|
||||
</For>
|
||||
</Match>
|
||||
</Switch>
|
||||
<ButtonLink href="/redshift" layout="small" class="flex items-center gap-2 self-center hover:text-m-red">Redshift <img src={wave} class="h-4" alt="redshift"></img></ButtonLink>
|
||||
</Card>
|
||||
</Suspense>
|
||||
</VStack>
|
||||
@@ -220,8 +233,8 @@ export function CombinedActivity(props: { limit?: number }) {
|
||||
|
||||
const getAllActivity = async () => {
|
||||
console.log("Getting all activity");
|
||||
const txs = await state.node_manager?.list_onchain() as OnChainTx[];
|
||||
const invoices = await state.node_manager?.list_invoices() as MutinyInvoice[];
|
||||
const txs = await state.mutiny_wallet?.list_onchain() as OnChainTx[];
|
||||
const invoices = await state.mutiny_wallet?.list_invoices() as MutinyInvoice[];
|
||||
|
||||
const activity: ActivityItem[] = [];
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import logo from '~/assets/icons/mutiny-logo.svg';
|
||||
import { Card, DefaultMain, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { DefaultMain, MutinyWalletGuard, SafeArea, VStack, Card } from "~/components/layout";
|
||||
import BalanceBox from "~/components/BalanceBox";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import ReloadPrompt from "~/components/Reload";
|
||||
@@ -10,7 +10,7 @@ import userClock from '~/assets/icons/user-clock.svg';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<header class="w-full flex justify-between items-center mt-4 mb-2">
|
||||
@@ -30,6 +30,6 @@ export default function App() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="home" />
|
||||
</SafeArea>
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import { createSignal } from "solid-js";
|
||||
import { ConfirmDialog } from "~/components/Dialog";
|
||||
import { Button } from "~/components/layout";
|
||||
import { showToast } from "~/components/Toaster";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
import eify from "~/utils/eify";
|
||||
|
||||
export function deleteDb(name: string) {
|
||||
const req = indexedDB.deleteDatabase(name);
|
||||
@@ -20,18 +22,7 @@ export function deleteDb(name: string) {
|
||||
}
|
||||
|
||||
export function DeleteEverything() {
|
||||
async function resetNode() {
|
||||
setConfirmLoading(true);
|
||||
deleteDb("gossip")
|
||||
deleteDb("wallet")
|
||||
localStorage.clear();
|
||||
showToast({ title: "Deleted", description: `Deleted all data` })
|
||||
setConfirmOpen(false);
|
||||
setConfirmLoading(false);
|
||||
setTimeout(() => {
|
||||
window.location.href = "/";
|
||||
}, 3000);
|
||||
}
|
||||
const [_state, actions] = useMegaStore();
|
||||
|
||||
async function confirmReset() {
|
||||
setConfirmOpen(true);
|
||||
@@ -40,6 +31,25 @@ export function DeleteEverything() {
|
||||
const [confirmOpen, setConfirmOpen] = createSignal(false);
|
||||
const [confirmLoading, setConfirmLoading] = createSignal(false);
|
||||
|
||||
|
||||
async function resetNode() {
|
||||
try {
|
||||
setConfirmLoading(true);
|
||||
await actions.deleteMutinyWallet();
|
||||
showToast({ title: "Deleted", description: `Deleted all data` })
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = "/";
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showToast(eify(e))
|
||||
} finally {
|
||||
setConfirmOpen(false);
|
||||
setConfirmLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={confirmReset}>Delete Everything</Button>
|
||||
@@ -48,4 +58,4 @@ export function DeleteEverything() {
|
||||
</ConfirmDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Title } from "solid-start";
|
||||
import { ButtonLink, DefaultMain, LargeHeader, SafeArea, SmallHeader } from "~/components/layout";
|
||||
import { Button, ButtonLink, DefaultMain, LargeHeader, SafeArea, SmallHeader } from "~/components/layout";
|
||||
|
||||
export default function ErrorDisplay(props: { error: Error }) {
|
||||
return (
|
||||
@@ -13,7 +13,7 @@ export default function ErrorDisplay(props: { error: Error }) {
|
||||
{props.error.name}</span>: {props.error.message}
|
||||
</p>
|
||||
<div class="h-full" />
|
||||
<ButtonLink href="/" intent="red">Dangit</ButtonLink>
|
||||
<Button onClick={() => window.location.href = "/"} intent="red">Dangit</Button>
|
||||
</DefaultMain>
|
||||
</SafeArea>
|
||||
);
|
||||
|
||||
@@ -6,13 +6,13 @@ import { showToast } from "./Toaster";
|
||||
import { downloadTextFile } from "~/utils/download";
|
||||
import { createFileUploader } from "@solid-primitives/upload"
|
||||
import { ConfirmDialog } from "./Dialog";
|
||||
import { NodeManager } from "@mutinywallet/mutiny-wasm";
|
||||
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
|
||||
|
||||
export function ImportExport() {
|
||||
const [state, _] = useMegaStore()
|
||||
|
||||
async function handleSave() {
|
||||
const json = await state.node_manager?.export_json()
|
||||
const json = await state.mutiny_wallet?.export_json()
|
||||
downloadTextFile(json || "", "mutiny-state.json")
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function ImportExport() {
|
||||
// This should throw if there's a parse error, so we won't end up clearing
|
||||
JSON.parse(text);
|
||||
|
||||
NodeManager.import_json(text);
|
||||
MutinyWallet.import_json(text);
|
||||
|
||||
window.location.href = "/"
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ function PeerItem(props: { peer: MutinyPeer }) {
|
||||
const [state, _] = useMegaStore()
|
||||
|
||||
const handleDisconnectPeer = async () => {
|
||||
const nodes = await state.node_manager?.list_nodes();
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
|
||||
if (props.peer.is_connected) {
|
||||
await state.node_manager?.disconnect_peer(firstNode, props.peer.pubkey);
|
||||
await state.mutiny_wallet?.disconnect_peer(firstNode, props.peer.pubkey);
|
||||
} else {
|
||||
await state.node_manager?.delete_peer(firstNode, props.peer.pubkey);
|
||||
await state.mutiny_wallet?.delete_peer(firstNode, props.peer.pubkey);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ function PeersList() {
|
||||
const [state, _] = useMegaStore()
|
||||
|
||||
const getPeers = async () => {
|
||||
return await state.node_manager?.list_peers() as Promise<MutinyPeer[]>
|
||||
return await state.mutiny_wallet?.list_peers() as Promise<MutinyPeer[]>
|
||||
};
|
||||
|
||||
const [peers, { refetch }] = createResource(getPeers);
|
||||
@@ -95,10 +95,10 @@ function ConnectPeer(props: { refetchPeers: RefetchPeersType }) {
|
||||
e.preventDefault();
|
||||
|
||||
const peerConnectString = value().trim();
|
||||
const nodes = await state.node_manager?.list_nodes();
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
|
||||
await state.node_manager?.connect_to_peer(firstNode, peerConnectString)
|
||||
await state.mutiny_wallet?.connect_to_peer(firstNode, peerConnectString)
|
||||
|
||||
await props.refetchPeers()
|
||||
|
||||
@@ -140,7 +140,7 @@ function ChannelItem(props: { channel: MutinyChannel, network?: string }) {
|
||||
async function confirmCloseChannel() {
|
||||
setConfirmLoading(true);
|
||||
try {
|
||||
await state.node_manager?.close_channel(props.channel.outpoint as string)
|
||||
await state.mutiny_wallet?.close_channel(props.channel.outpoint as string)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast(eify(e));
|
||||
@@ -179,7 +179,7 @@ function ChannelsList() {
|
||||
const [state, _] = useMegaStore()
|
||||
|
||||
const getChannels = async () => {
|
||||
return await state.node_manager?.list_channels() as Promise<MutinyChannel[]>
|
||||
return await state.mutiny_wallet?.list_channels() as Promise<MutinyChannel[]>
|
||||
};
|
||||
|
||||
const [channels, { refetch }] = createResource(getChannels);
|
||||
@@ -194,7 +194,7 @@ function ChannelsList() {
|
||||
});
|
||||
})
|
||||
|
||||
const network = state.node_manager?.get_network();
|
||||
const network = state.mutiny_wallet?.get_network();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -236,10 +236,10 @@ function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) {
|
||||
const pubkey = peerPubkey().trim();
|
||||
const bigAmount = BigInt(amount());
|
||||
|
||||
const nodes = await state.node_manager?.list_nodes();
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
|
||||
const new_channel = await state.node_manager?.open_channel(firstNode, pubkey, bigAmount)
|
||||
const new_channel = await state.mutiny_wallet?.open_channel(firstNode, pubkey, bigAmount)
|
||||
|
||||
setNewChannel(new_channel)
|
||||
|
||||
@@ -303,7 +303,7 @@ function LnUrlAuth() {
|
||||
e.preventDefault();
|
||||
|
||||
const lnurl = value().trim();
|
||||
await state.node_manager?.lnurl_auth(0, lnurl)
|
||||
await state.mutiny_wallet?.lnurl_auth(0, lnurl)
|
||||
|
||||
setValue("");
|
||||
};
|
||||
|
||||
@@ -2,11 +2,12 @@ import mutiny_m from '~/assets/icons/m.svg';
|
||||
import airplane from '~/assets/icons/airplane.svg';
|
||||
import settings from '~/assets/icons/settings.svg';
|
||||
import receive from '~/assets/icons/big-receive.svg';
|
||||
import redshift from '~/assets/icons/rs.svg';
|
||||
import userClock from '~/assets/icons/user-clock.svg';
|
||||
|
||||
import { A } from "solid-start";
|
||||
|
||||
type ActiveTab = 'home' | 'scan' | 'send' | 'receive' | 'settings' | 'activity' | 'none';
|
||||
type ActiveTab = 'home' | 'scan' | 'send' | 'receive' | 'settings' | 'redshift' | 'activity' | 'none';
|
||||
|
||||
export default function NavBar(props: { activeTab: ActiveTab }) {
|
||||
const activeStyle = 'border-t-0 border-b-0 p-2 bg-black rounded-lg'
|
||||
@@ -34,6 +35,11 @@ export default function NavBar(props: { activeTab: ActiveTab }) {
|
||||
<img src={userClock} alt="activity" />
|
||||
</A>
|
||||
</li>
|
||||
<li class={props.activeTab === "redshift" ? activeStyle : inactiveStyle}>
|
||||
<A href="/redshift">
|
||||
<img src={redshift} alt="redshift" width={36} />
|
||||
</A>
|
||||
</li>
|
||||
<li class={props.activeTab === "settings" ? activeStyle : inactiveStyle}>
|
||||
<A href="/settings">
|
||||
<img src={settings} alt="settings" />
|
||||
|
||||
@@ -3,7 +3,7 @@ import { As, Dialog } from "@kobalte/core";
|
||||
import { Button, Card } from "~/components/layout";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
import { Show, createResource } from "solid-js";
|
||||
import { getExistingSettings } from "~/logic/nodeManagerSetup";
|
||||
import { getExistingSettings } from "~/logic/mutinyWalletSetup";
|
||||
import getHostname from "~/utils/getHostname";
|
||||
|
||||
const OVERLAY = "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm"
|
||||
@@ -15,9 +15,9 @@ export default function PeerConnectModal() {
|
||||
const [state, _] = useMegaStore()
|
||||
|
||||
const getPeerConnectString = async () => {
|
||||
if (state.node_manager) {
|
||||
if (state.mutiny_wallet) {
|
||||
const { proxy } = getExistingSettings();
|
||||
const nodes = await state.node_manager.list_nodes();
|
||||
const nodes = await state.mutiny_wallet.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
const hostName = getHostname(proxy || "")
|
||||
const connectString = `mutiny:${firstNode}@${hostName}`
|
||||
|
||||
@@ -1,36 +1,22 @@
|
||||
import { createForm, url } from '@modular-forms/solid';
|
||||
import { TextField } from '~/components/layout/TextField';
|
||||
import { NodeManagerSettingStrings, getExistingSettings } from '~/logic/nodeManagerSetup';
|
||||
import { Button } from '~/components/layout';
|
||||
import { createSignal } from 'solid-js';
|
||||
import { deleteDb } from '~/components/DeleteEverything';
|
||||
import { MutinyWalletSettingStrings, getExistingSettings } from '~/logic/mutinyWalletSetup';
|
||||
import { Button, SmallHeader } from '~/components/layout';
|
||||
import { showToast } from './Toaster';
|
||||
import eify from '~/utils/eify';
|
||||
import { ConfirmDialog } from "~/components/Dialog";
|
||||
import { useMegaStore } from '~/state/megaStore';
|
||||
|
||||
export function SettingsStringsEditor() {
|
||||
const existingSettings = getExistingSettings();
|
||||
const [_settingsForm, { Form, Field }] = createForm<NodeManagerSettingStrings>({ initialValues: existingSettings });
|
||||
const [confirmOpen, setConfirmOpen] = createSignal(false);
|
||||
|
||||
const [settingsTemp, setSettingsTemp] = createSignal<NodeManagerSettingStrings>();
|
||||
|
||||
const [_settingsForm, { Form, Field }] = createForm<MutinyWalletSettingStrings>({ initialValues: existingSettings });
|
||||
const [_store, actions] = useMegaStore();
|
||||
|
||||
async function handleSubmit(values: NodeManagerSettingStrings) {
|
||||
async function handleSubmit(values: MutinyWalletSettingStrings) {
|
||||
try {
|
||||
const existing = getExistingSettings();
|
||||
const newSettings = { ...existing, ...values }
|
||||
if (existing.network !== values.network) {
|
||||
// If the network changes we need to confirm the wipe
|
||||
// Save the settings so we can get them later
|
||||
setSettingsTemp(newSettings);
|
||||
setConfirmOpen(true);
|
||||
} else {
|
||||
await actions.setupNodeManager(newSettings);
|
||||
window.location.reload();
|
||||
}
|
||||
await actions.setupMutinyWallet(newSettings);
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showToast(eify(e))
|
||||
@@ -38,42 +24,15 @@ export function SettingsStringsEditor() {
|
||||
console.log(values)
|
||||
}
|
||||
|
||||
async function confirmStateReset() {
|
||||
try {
|
||||
deleteDb("gossip")
|
||||
localStorage.clear();
|
||||
showToast({ title: "Deleted", description: `Deleted all data` })
|
||||
const loadedValues = settingsTemp();
|
||||
|
||||
await actions.setupNodeManager(loadedValues);
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
showToast(eify(e))
|
||||
}
|
||||
|
||||
setConfirmOpen(false);
|
||||
}
|
||||
|
||||
return <Form onSubmit={handleSubmit} class="flex flex-col gap-4">
|
||||
<ConfirmDialog loading={false} isOpen={confirmOpen()} onConfirm={confirmStateReset} onCancel={() => setConfirmOpen(false)}>
|
||||
Are you sure? Changing networks will delete your node's state. This can't be undone!
|
||||
</ConfirmDialog>
|
||||
<h2 class="text-2xl font-light">Don't trust us! Use your own servers to back Mutiny.</h2>
|
||||
<Field name="network">
|
||||
{(field, props) => (
|
||||
// TODO: make a cool select component
|
||||
<div class="flex flex-col gap-2">
|
||||
<label class="text-sm font-semibold uppercase">Network</label>
|
||||
<select {...field} {...props} class="bg-black rounded-xl border border-white px-4 py-2">
|
||||
<option value="bitcoin">Mainnet</option>
|
||||
<option value="testnet">Testnet</option>
|
||||
<option value="regtest">Regtest</option>
|
||||
<option value="signet">Signet</option>
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
</Field>
|
||||
<div class="flex flex-col gap-2">
|
||||
<SmallHeader>Network</SmallHeader>
|
||||
<pre>
|
||||
{existingSettings.network}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<Field name="proxy" validate={[url("Should be a url starting with wss://")]}>
|
||||
{(field, props) => (
|
||||
<TextField {...props} value={field.value} error={field.error} label="Websockets Proxy" />
|
||||
|
||||
@@ -71,11 +71,11 @@ export const FullscreenLoader = () => {
|
||||
);
|
||||
}
|
||||
|
||||
export const NodeManagerGuard: ParentComponent = (props) => {
|
||||
export const MutinyWalletGuard: ParentComponent = (props) => {
|
||||
const [state, _] = useMegaStore();
|
||||
return (
|
||||
<Suspense fallback={<FullscreenLoader />}>
|
||||
<Show when={state.node_manager}>
|
||||
<Show when={state.mutiny_wallet}>
|
||||
{props.children}
|
||||
</Show>
|
||||
</Suspense>
|
||||
@@ -133,4 +133,4 @@ export const Indicator: ParentComponent = (props) => {
|
||||
return (
|
||||
<div class="box-border animate-pulse px-2 py-1 -my-1 bg-white/70 rounded text-xs uppercase text-black">{props.children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
import initNodeManager, { NodeManager } from '@mutinywallet/mutiny-wasm';
|
||||
import initMutinyWallet, { MutinyWallet } from '@mutinywallet/mutiny-wasm';
|
||||
import initWaila from '@mutinywallet/waila-wasm'
|
||||
|
||||
// export type NodeManagerSettingStrings = {
|
||||
// export type MutinyWalletSettingStrings = {
|
||||
// network?: string, proxy?: string, esplora?: string, rgs?: string, lsp?: string,
|
||||
// }
|
||||
|
||||
type Network = "bitcoin" | "testnet" | "regtest" | "signet";
|
||||
export type NodeManagerSettingStrings = {
|
||||
export type MutinyWalletSettingStrings = {
|
||||
network?: Network, proxy?: string, esplora?: string, rgs?: string, lsp?: string,
|
||||
}
|
||||
|
||||
export function getExistingSettings(): NodeManagerSettingStrings {
|
||||
export function getExistingSettings(): MutinyWalletSettingStrings {
|
||||
const network = localStorage.getItem('MUTINY_SETTINGS_network') || import.meta.env.VITE_NETWORK;
|
||||
const proxy = localStorage.getItem('MUTINY_SETTINGS_proxy') || import.meta.env.VITE_PROXY;
|
||||
const esplora = localStorage.getItem('MUTINY_SETTINGS_esplora') || import.meta.env.VITE_ESPLORA;
|
||||
@@ -21,7 +21,7 @@ export function getExistingSettings(): NodeManagerSettingStrings {
|
||||
return { network, proxy, esplora, rgs, lsp }
|
||||
}
|
||||
|
||||
export async function setAndGetMutinySettings(settings?: NodeManagerSettingStrings): Promise<NodeManagerSettingStrings> {
|
||||
export async function setAndGetMutinySettings(settings?: MutinyWalletSettingStrings): Promise<MutinyWalletSettingStrings> {
|
||||
let { network, proxy, esplora, rgs, lsp } = settings || {};
|
||||
|
||||
const existingSettings = getExistingSettings();
|
||||
@@ -70,29 +70,29 @@ export async function checkForWasm() {
|
||||
}
|
||||
}
|
||||
|
||||
export async function setupNodeManager(settings?: NodeManagerSettingStrings): Promise<NodeManager> {
|
||||
await initNodeManager();
|
||||
export async function setupMutinyWallet(settings?: MutinyWalletSettingStrings): Promise<MutinyWallet> {
|
||||
await initMutinyWallet();
|
||||
// Might as well init waila while we're at it
|
||||
await initWaila();
|
||||
|
||||
console.time("Setup");
|
||||
console.log("Starting setup...")
|
||||
const { network, proxy, esplora, rgs, lsp } = await setAndGetMutinySettings(settings)
|
||||
console.log("Initializing Node Manager")
|
||||
console.log("Initializing Mutiny Manager")
|
||||
console.log("Using network", network);
|
||||
console.log("Using proxy", proxy);
|
||||
console.log("Using esplora address", esplora);
|
||||
console.log("Using rgs address", rgs);
|
||||
console.log("Using lsp address", lsp);
|
||||
|
||||
const nodeManager = await new NodeManager("", undefined, proxy, network, esplora, rgs, lsp)
|
||||
const mutinyWallet = await new MutinyWallet("", undefined, proxy, network, esplora, rgs, lsp)
|
||||
|
||||
const nodes = await nodeManager.list_nodes();
|
||||
const nodes = await mutinyWallet.list_nodes();
|
||||
|
||||
// If we don't have any nodes yet, create one
|
||||
if (!nodes.length) {
|
||||
await nodeManager?.new_node()
|
||||
await mutinyWallet?.new_node()
|
||||
}
|
||||
|
||||
return nodeManager
|
||||
return mutinyWallet
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { For, Show, createResource } from "solid-js";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { Button, Card, DefaultMain, LargeHeader, NiceP, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { Button, Card, DefaultMain, LargeHeader, NiceP, MutinyWalletGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { BackLink } from "~/components/layout/BackLink";
|
||||
import { CombinedActivity } from "~/components/Activity";
|
||||
import { A } from "solid-start";
|
||||
@@ -43,7 +43,7 @@ const TAB = "flex-1 inline-block px-8 py-4 text-lg font-semibold rounded-lg ui-s
|
||||
|
||||
export default function Activity() {
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink />
|
||||
@@ -73,6 +73,6 @@ export default function Activity() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="activity" />
|
||||
</SafeArea>
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { DeleteEverything } from "~/components/DeleteEverything";
|
||||
import KitchenSink from "~/components/KitchenSink";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { Card, DefaultMain, LargeHeader, NodeManagerGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
|
||||
import { Card, DefaultMain, LargeHeader, MutinyWalletGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
|
||||
import { BackLink } from "~/components/layout/BackLink";
|
||||
|
||||
export default function Admin() {
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink href="/settings" title="Settings" />
|
||||
@@ -22,6 +22,6 @@ export default function Admin() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="none" />
|
||||
</SafeArea>
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, DefaultMain, LargeHeader, NiceP, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { Button, DefaultMain, LargeHeader, NiceP, MutinyWalletGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { useNavigate } from 'solid-start';
|
||||
import { SeedWords } from '~/components/SeedWords';
|
||||
@@ -18,7 +18,7 @@ export default function App() {
|
||||
}
|
||||
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink />
|
||||
@@ -30,7 +30,7 @@ export default function App() {
|
||||
If you clear your browser history, or lose your device, these 12 words are the only way you can restore your wallet.
|
||||
</NiceP>
|
||||
<NiceP>Mutiny is self-custodial. It's all up to you...</NiceP>
|
||||
<SeedWords words={store.node_manager?.show_seed() || ""} setHasSeen={setHasSeenBackup} />
|
||||
<SeedWords words={store.mutiny_wallet?.show_seed() || ""} setHasSeen={setHasSeenBackup} />
|
||||
<Show when={hasSeenBackup()}>
|
||||
<NiceP>You are responsible for your funds!</NiceP>
|
||||
</Show>
|
||||
@@ -39,6 +39,6 @@ export default function App() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="none" />
|
||||
</SafeArea>
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MutinyBip21RawMaterials, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
|
||||
import { createEffect, createMemo, createResource, createSignal, Match, onCleanup, onMount, Show, Switch } from "solid-js";
|
||||
import { QRCodeSVG } from "solid-qr-code";
|
||||
import { Button, Card, Indicator, LargeHeader, NodeManagerGuard, SafeArea } from "~/components/layout";
|
||||
import { Button, Card, Indicator, LargeHeader, MutinyWalletGuard, SafeArea } from "~/components/layout";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
import { objectToSearchParams } from "~/utils/objectToSearchParams";
|
||||
@@ -104,13 +104,13 @@ export default function Receive() {
|
||||
async function getUnifiedQr(amount: string) {
|
||||
const bigAmount = BigInt(amount);
|
||||
try {
|
||||
const raw = await state.node_manager?.create_bip21(bigAmount);
|
||||
// FIXME: actual labels
|
||||
const raw = await state.mutiny_wallet?.create_bip21(bigAmount, []);
|
||||
// Save the raw info so we can watch the address and invoice
|
||||
setBip21Raw(raw);
|
||||
|
||||
const params = objectToSearchParams({
|
||||
amount: raw?.btc_amount,
|
||||
label: raw?.description,
|
||||
lightning: raw?.invoice
|
||||
})
|
||||
|
||||
@@ -138,7 +138,7 @@ export default function Receive() {
|
||||
const lightning = bip21.invoice
|
||||
const address = bip21.address
|
||||
|
||||
const invoice = await state.node_manager?.get_invoice(lightning)
|
||||
const invoice = await state.mutiny_wallet?.get_invoice(lightning)
|
||||
|
||||
if (invoice && invoice.paid) {
|
||||
setReceiveState("paid")
|
||||
@@ -146,7 +146,7 @@ export default function Receive() {
|
||||
return "lightning_paid"
|
||||
}
|
||||
|
||||
const tx = await state.node_manager?.check_address(address) as OnChainTx | undefined;
|
||||
const tx = await state.mutiny_wallet?.check_address(address) as OnChainTx | undefined;
|
||||
|
||||
if (tx) {
|
||||
setReceiveState("paid")
|
||||
@@ -168,7 +168,7 @@ export default function Receive() {
|
||||
});
|
||||
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<main class="max-w-[600px] flex flex-col flex-1 gap-4 mx-auto p-4 overflow-y-auto">
|
||||
<Show when={receiveState() === "show"} fallback={<BackLink />}>
|
||||
@@ -229,6 +229,6 @@ export default function Receive() {
|
||||
</main>
|
||||
<NavBar activeTab="receive" />
|
||||
</SafeArea >
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
)
|
||||
}
|
||||
409
src/routes/Redshift.tsx
Normal file
@@ -0,0 +1,409 @@
|
||||
import { Component, createEffect, createMemo, createResource, createSignal, For, Match, onCleanup, onMount, ParentComponent, Show, Suspense, Switch } from "solid-js";
|
||||
import { CENTER_COLUMN, MISSING_LABEL, REDSHIFT_LABEL, RIGHT_COLUMN, THREE_COLUMNS, UtxoItem } from "~/components/Activity";
|
||||
import { Card, DefaultMain, LargeHeader, LoadingSpinner, NiceP, MutinyWalletGuard, SafeArea, SmallAmount, SmallHeader, VStack } from "~/components/layout";
|
||||
import { BackLink } from "~/components/layout/BackLink";
|
||||
import { StyledRadioGroup } from "~/components/layout/Radio";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
import wave from "~/assets/wave.gif"
|
||||
import utxoIcon from '~/assets/icons/coin.svg';
|
||||
import { Button } from "~/components/layout/Button";
|
||||
import { ProgressBar } from "~/components/layout/ProgressBar";
|
||||
import { MutinyChannel } from "@mutinywallet/mutiny-wasm";
|
||||
import mempoolTxUrl from "~/utils/mempoolTxUrl";
|
||||
import { Amount } from "~/components/Amount";
|
||||
import { getRedshifted, setRedshifted } from "~/utils/fakeLabels";
|
||||
|
||||
type ShiftOption = "utxo" | "lightning"
|
||||
|
||||
type ShiftStage = "choose" | "observe" | "success" | "failure"
|
||||
|
||||
type OutPoint = string; // Replace with the actual TypeScript type for OutPoint
|
||||
type RedshiftStatus = string; // Replace with the actual TypeScript type for RedshiftStatus
|
||||
type RedshiftRecipient = any; // Replace with the actual TypeScript type for RedshiftRecipient
|
||||
type PublicKey = any; // Replace with the actual TypeScript type for PublicKey
|
||||
|
||||
interface RedshiftResult {
|
||||
id: string;
|
||||
input_utxo: OutPoint;
|
||||
status: RedshiftStatus;
|
||||
recipient: RedshiftRecipient;
|
||||
output_utxo?: OutPoint;
|
||||
introduction_channel?: OutPoint;
|
||||
output_channel?: OutPoint;
|
||||
introduction_node: PublicKey;
|
||||
amount_sats: bigint;
|
||||
change_amt?: bigint;
|
||||
fees_paid: bigint;
|
||||
}
|
||||
|
||||
const dummyRedshift: RedshiftResult = {
|
||||
id: "44036599c37d590899e8d5d920860286",
|
||||
input_utxo: "44036599c37d590899e8d5d92086028695d2c2966fdc354ce1da9a9eac610a53:1",
|
||||
status: "Completed", // Replace with a dummy value for RedshiftStatus
|
||||
recipient: {}, // Replace with a dummy value for RedshiftRecipient
|
||||
output_utxo: "44036599c37d590899e8d5d92086028695d2c2966fdc354ce1da9a9eac610a53:1",
|
||||
introduction_channel: "a7773e57f8595848a635e9af105927cac9ecaf292d71a76456ae0455bd3c9c64:0",
|
||||
output_channel: "a7773e57f8595848a635e9af105927cac9ecaf292d71a76456ae0455bd3c9c64:0",
|
||||
introduction_node: {}, // Replace with a dummy value for PublicKey
|
||||
amount_sats: BigInt(1000000),
|
||||
change_amt: BigInt(12345),
|
||||
fees_paid: BigInt(2500),
|
||||
};
|
||||
|
||||
function RedshiftReport(props: { redshift: RedshiftResult, utxo: UtxoItem }) {
|
||||
const [state, _actions] = useMegaStore();
|
||||
|
||||
const getUtXos = async () => {
|
||||
console.log("Getting utxos");
|
||||
return await state.mutiny_wallet?.list_utxos() as UtxoItem[];
|
||||
}
|
||||
|
||||
function findUtxoByOutpoint(outpoint?: string, utxos: UtxoItem[] = []): UtxoItem | undefined {
|
||||
if (!outpoint) return undefined;
|
||||
return utxos.find((utxo) => utxo.outpoint === outpoint);
|
||||
}
|
||||
|
||||
|
||||
const [utxos, { refetch: _refetchUtxos }] = createResource(getUtXos);
|
||||
|
||||
const inputUtxo = createMemo(() => {
|
||||
console.log(utxos())
|
||||
const foundUtxo = findUtxoByOutpoint(props.redshift.input_utxo, utxos())
|
||||
console.log("Found utxo:", foundUtxo)
|
||||
return foundUtxo
|
||||
})
|
||||
|
||||
|
||||
async function checkRedshift(id: string) {
|
||||
// const rs = redshiftItems[0] as RedshiftResult;
|
||||
console.log("Checking redshift", id)
|
||||
const redshift = await state.mutiny_wallet?.get_redshift(id);
|
||||
console.log(redshift)
|
||||
return redshift;
|
||||
}
|
||||
|
||||
const [redshiftResource, { refetch }] = createResource(props.redshift.id, checkRedshift);
|
||||
onMount(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (redshiftResource()) refetch();
|
||||
// if (sentAmount() === 200000) {
|
||||
// clearInterval(interval)
|
||||
// props.setShiftStage("success");
|
||||
// // setSentAmount((0))
|
||||
|
||||
// } else {
|
||||
// setSentAmount((sentAmount() + 50000))
|
||||
// }
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
const outputUtxo = createMemo(() => {
|
||||
return findUtxoByOutpoint(redshiftResource()?.output_utxo, utxos())
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
setRedshifted(true, redshiftResource()?.output_utxo)
|
||||
})
|
||||
|
||||
|
||||
return (
|
||||
<VStack biggap>
|
||||
|
||||
{/* <VStack>
|
||||
<NiceP>We did it. Here's your new UTXO:</NiceP>
|
||||
<Show when={utxos() && outputUtxo()}>
|
||||
<Card>
|
||||
<Utxo item={outputUtxo()!} />
|
||||
</Card>
|
||||
</Show>
|
||||
</VStack> */}
|
||||
<VStack>
|
||||
<NiceP>What happened?</NiceP>
|
||||
<Show when={redshiftResource()}>
|
||||
|
||||
<Card>
|
||||
<VStack biggap>
|
||||
{/* <KV key="Input utxo">
|
||||
<Show when={utxos() && inputUtxo()}>
|
||||
<Utxo item={inputUtxo()!} />
|
||||
</Show>
|
||||
</KV> */}
|
||||
<KV key="Starting amount">
|
||||
<Amount amountSats={redshiftResource().amount_sats} />
|
||||
</KV>
|
||||
<KV key="Fees paid">
|
||||
<Amount amountSats={redshiftResource().fees_paid} />
|
||||
</KV>
|
||||
<KV key="Change">
|
||||
<Amount amountSats={redshiftResource().change_amt} />
|
||||
</KV>
|
||||
<KV key="Outbound channel">
|
||||
<VStack>
|
||||
<pre class="whitespace-pre-wrap break-all">{redshiftResource().introduction_channel}</pre>
|
||||
<a class="" href={mempoolTxUrl(redshiftResource().introduction_channel?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
|
||||
View on mempool
|
||||
</a>
|
||||
</VStack>
|
||||
</KV>
|
||||
<Show when={redshiftResource().output_channel}>
|
||||
<KV key="Return channel">
|
||||
<VStack>
|
||||
<pre class="whitespace-pre-wrap break-all">{redshiftResource().output_channel}</pre>
|
||||
<a class="" href={mempoolTxUrl(redshiftResource().output_channel?.split(":")[0], "signet")} target="_blank" rel="noreferrer">
|
||||
View on mempool
|
||||
</a>
|
||||
|
||||
</VStack>
|
||||
</KV>
|
||||
</Show>
|
||||
</VStack>
|
||||
</Card>
|
||||
</Show>
|
||||
<SmallHeader></SmallHeader>
|
||||
</VStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
const SHIFT_OPTIONS = [{ value: "utxo", label: "UTXO", caption: "Trade your UTXO for a fresh UTXO" }, { value: "lightning", label: "Lightning", caption: "Convert your UTXO into Lightning" }]
|
||||
|
||||
export function Utxo(props: { item: UtxoItem, onClick?: () => void }) {
|
||||
const redshifted = createMemo(() => getRedshifted(props.item.outpoint));
|
||||
return (
|
||||
<>
|
||||
<div class={THREE_COLUMNS} onClick={props.onClick}>
|
||||
<div class="flex items-center">
|
||||
<img src={utxoIcon} alt="coin" />
|
||||
</div>
|
||||
<div class={CENTER_COLUMN}>
|
||||
<div class="flex gap-2">
|
||||
<Show when={redshifted()} fallback={<h2 class={MISSING_LABEL}>Unknown</h2>}>
|
||||
<h2 class={REDSHIFT_LABEL}>Redshift</h2>
|
||||
</Show>
|
||||
</div>
|
||||
<SmallAmount amount={props.item.txout.value} />
|
||||
</div>
|
||||
<div class={RIGHT_COLUMN}>
|
||||
<SmallHeader class={props.item?.is_spent ? "text-m-red" : "text-m-green"}>
|
||||
{/* {props.item?.is_spent ? "SPENT" : "UNSPENT"} */}
|
||||
</SmallHeader>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const FAKE_STATES = ["Creating a new node", "Opening a channel", "Sending funds through", "Closing the channel", "Redshift complete"]
|
||||
|
||||
function ShiftObserver(props: { setShiftStage: (stage: ShiftStage) => void, redshiftId: String }) {
|
||||
const [state, _actions] = useMegaStore();
|
||||
|
||||
const [fakeStage, setFakeStage] = createSignal(2);
|
||||
|
||||
const [sentAmount, setSentAmount] = createSignal(0);
|
||||
|
||||
onMount(() => {
|
||||
const interval = setInterval(() => {
|
||||
if (sentAmount() === 200000) {
|
||||
clearInterval(interval)
|
||||
props.setShiftStage("success");
|
||||
// setSentAmount((0))
|
||||
|
||||
} else {
|
||||
setSentAmount((sentAmount() + 50000))
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
async function checkRedshift(id: string) {
|
||||
console.log("Checking redshift", id)
|
||||
const redshift = await state.mutiny_wallet?.get_redshift(id);
|
||||
console.log(redshift)
|
||||
return redshift
|
||||
}
|
||||
|
||||
const [redshiftResource, { refetch }] = createResource(props.redshiftId, checkRedshift);
|
||||
|
||||
// onMount(() => {
|
||||
// const interval = setInterval(() => {
|
||||
// if (redshiftResource()) refetch();
|
||||
// // if (sentAmount() === 200000) {
|
||||
// // clearInterval(interval)
|
||||
// // props.setShiftStage("success");
|
||||
// // // setSentAmount((0))
|
||||
|
||||
// // } else {
|
||||
// // setSentAmount((sentAmount() + 50000))
|
||||
// // }
|
||||
// }, 1000)
|
||||
// })
|
||||
|
||||
// createEffect(() => {
|
||||
// const interval = setInterval(() => {
|
||||
// if (chosenUtxo()) refetch();
|
||||
// }, 1000); // Poll every second
|
||||
// onCleanup(() => {
|
||||
// clearInterval(interval);
|
||||
// });
|
||||
// });
|
||||
|
||||
return (
|
||||
<>
|
||||
<NiceP>Watch it go!</NiceP>
|
||||
<Card>
|
||||
<VStack>
|
||||
<pre class="self-center">{FAKE_STATES[fakeStage()]}</pre>
|
||||
<ProgressBar value={sentAmount()} max={200000} />
|
||||
<img src={wave} class="h-4 self-center" alt="sine wave" />
|
||||
</VStack>
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const KV: ParentComponent<{ key: string }> = (props) => {
|
||||
return (
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="text-sm font-semibold uppercase">{props.key}</p>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Redshift() {
|
||||
const [state, _actions] = useMegaStore();
|
||||
|
||||
const [shiftStage, setShiftStage] = createSignal<ShiftStage>("choose");
|
||||
const [shiftType, setShiftType] = createSignal<ShiftOption>("utxo");
|
||||
|
||||
const [chosenUtxo, setChosenUtxo] = createSignal<UtxoItem>();
|
||||
|
||||
const getUtXos = async () => {
|
||||
console.log("Getting utxos");
|
||||
return await state.mutiny_wallet?.list_utxos() as UtxoItem[];
|
||||
}
|
||||
|
||||
const getChannels = async () => {
|
||||
console.log("Getting channels");
|
||||
await state.mutiny_wallet?.sync()
|
||||
const channels = await state.mutiny_wallet?.list_channels() as Promise<MutinyChannel[]>;
|
||||
console.log(channels)
|
||||
return channels
|
||||
|
||||
}
|
||||
|
||||
const [utxos, { refetch: _refetchUtxos }] = createResource(getUtXos);
|
||||
const [channels, { refetch: _refetchChannels }] = createResource(getChannels);
|
||||
|
||||
|
||||
|
||||
const redshiftedUtxos = createMemo(() => {
|
||||
return utxos()?.filter((utxo) => getRedshifted(utxo.outpoint))
|
||||
})
|
||||
|
||||
const unredshiftedUtxos = createMemo(() => {
|
||||
return utxos()?.filter((utxo) => !getRedshifted(utxo.outpoint))
|
||||
})
|
||||
|
||||
function resetState() {
|
||||
setShiftStage("choose");
|
||||
setShiftType("utxo");
|
||||
setChosenUtxo(undefined);
|
||||
}
|
||||
|
||||
async function redshiftUtxo(utxo: UtxoItem) {
|
||||
console.log("Redshifting utxo", utxo.outpoint)
|
||||
const redshift = await state.mutiny_wallet?.init_redshift(utxo.outpoint);
|
||||
console.log("Redshift initialized:")
|
||||
console.log(redshift)
|
||||
return redshift
|
||||
}
|
||||
|
||||
const [initializedRedshift, { refetch: _refetchRedshift }] = createResource(chosenUtxo, redshiftUtxo);
|
||||
|
||||
createEffect(() => {
|
||||
if (chosenUtxo() && initializedRedshift()) {
|
||||
// window.location.href = "/"
|
||||
setShiftStage("observe");
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink />
|
||||
<LargeHeader>Redshift</LargeHeader>
|
||||
<VStack biggap>
|
||||
{/* <pre>{JSON.stringify(redshiftResource(), null, 2)}</pre> */}
|
||||
<Switch>
|
||||
<Match when={shiftStage() === "choose"}>
|
||||
<VStack>
|
||||
<NiceP>Where is this going?</NiceP>
|
||||
<StyledRadioGroup red value={shiftType()} onValueChange={(newValue) => setShiftType(newValue as ShiftOption)} choices={SHIFT_OPTIONS} />
|
||||
</VStack>
|
||||
<VStack>
|
||||
<NiceP>Choose your <span class="inline-block"><img class="h-4" src={wave} alt="sine wave" /></span> UTXO to begin</NiceP>
|
||||
<Suspense>
|
||||
<Card title="Unshifted UTXOs">
|
||||
<Switch>
|
||||
<Match when={utxos.loading}>
|
||||
<LoadingSpinner wide />
|
||||
</Match>
|
||||
<Match when={utxos.state === "ready" && unredshiftedUtxos()?.length === 0}>
|
||||
<code>No utxos (empty state)</code>
|
||||
</Match>
|
||||
<Match when={utxos.state === "ready" && unredshiftedUtxos() && unredshiftedUtxos()!.length >= 0}>
|
||||
<For each={unredshiftedUtxos()}>
|
||||
{(utxo) =>
|
||||
<Utxo item={utxo} onClick={() => setChosenUtxo(utxo)} />
|
||||
}
|
||||
</For>
|
||||
</Match>
|
||||
</Switch>
|
||||
</Card>
|
||||
</Suspense>
|
||||
<Suspense>
|
||||
<Card titleElement={<SmallHeader><span class="text-m-red">Redshifted </span>UTXOs</SmallHeader>}>
|
||||
<Switch>
|
||||
<Match when={utxos.loading}>
|
||||
<LoadingSpinner wide />
|
||||
</Match>
|
||||
<Match when={utxos.state === "ready" && redshiftedUtxos()?.length === 0}>
|
||||
<code>No utxos (empty state)</code>
|
||||
</Match>
|
||||
<Match when={utxos.state === "ready" && redshiftedUtxos() && redshiftedUtxos()!.length >= 0}>
|
||||
<For each={redshiftedUtxos()}>
|
||||
{(utxo) =>
|
||||
<Utxo item={utxo} />
|
||||
}
|
||||
</For>
|
||||
</Match>
|
||||
</Switch>
|
||||
</Card>
|
||||
</Suspense>
|
||||
</VStack>
|
||||
</Match>
|
||||
<Match when={shiftStage() === "observe" && chosenUtxo()}>
|
||||
<ShiftObserver setShiftStage={setShiftStage} utxo={chosenUtxo()!} />
|
||||
</Match>
|
||||
<Match when={shiftStage() === "success" && chosenUtxo()}>
|
||||
<VStack biggap>
|
||||
<RedshiftReport redshift={dummyRedshift} utxo={chosenUtxo()!} />
|
||||
<Button intent="red" onClick={resetState}>Nice</Button>
|
||||
</VStack>
|
||||
</Match>
|
||||
<Match when={shiftStage() === "failure"}>
|
||||
<NiceP>Oh dear</NiceP>
|
||||
<NiceP>Here's what happened:</NiceP>
|
||||
<Button intent="red" onClick={resetState}>Dangit</Button>
|
||||
</Match>
|
||||
</Switch>
|
||||
</VStack>
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="redshift" />
|
||||
</SafeArea>
|
||||
</MutinyWalletGuard>
|
||||
)
|
||||
}
|
||||
@@ -83,7 +83,7 @@ export default function Scanner() {
|
||||
// When we have a nice result we can head over to the send screen
|
||||
createEffect(() => {
|
||||
if (scanResult()) {
|
||||
const network = state.node_manager?.get_network() || "signet";
|
||||
const network = state.mutiny_wallet?.get_network() || "signet";
|
||||
const result = toParsedParams(scanResult() || "", network);
|
||||
if (!result.ok) {
|
||||
showToast(result.error);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Match, Show, Switch, createEffect, createMemo, createSignal, onMount } from "solid-js";
|
||||
import { Amount } from "~/components/Amount";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { Button, ButtonLink, Card, DefaultMain, HStack, LargeHeader, NodeManagerGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
|
||||
import { Button, ButtonLink, Card, DefaultMain, HStack, LargeHeader, MutinyWalletGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
|
||||
import { Paste } from "~/assets/svg/Paste";
|
||||
import { Scan } from "~/assets/svg/Scan";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
@@ -14,8 +14,8 @@ import { FullscreenModal } from "~/components/layout/FullscreenModal";
|
||||
import megacheck from "~/assets/icons/megacheck.png"
|
||||
import megaex from "~/assets/icons/megaex.png";
|
||||
import mempoolTxUrl from "~/utils/mempoolTxUrl";
|
||||
import { useNavigate } from "solid-start";
|
||||
import { BackLink } from "~/components/layout/BackLink";
|
||||
import { useNavigate } from "solid-start";
|
||||
import { TagEditor } from "~/components/TagEditor";
|
||||
import { TagItem, createUniqueId, listTags } from "~/state/contacts";
|
||||
import { StringShower } from "~/components/ShareCard";
|
||||
@@ -170,7 +170,7 @@ export default function Send() {
|
||||
if (source.memo) setDescription(source.memo);
|
||||
|
||||
if (source.invoice) {
|
||||
state.node_manager?.decode_invoice(source.invoice).then(invoice => {
|
||||
state.mutiny_wallet?.decode_invoice(source.invoice).then(invoice => {
|
||||
if (invoice?.amount_sats) setAmountSats(invoice.amount_sats);
|
||||
setInvoice(invoice)
|
||||
setSource("lightning")
|
||||
@@ -193,7 +193,7 @@ export default function Send() {
|
||||
|
||||
function parsePaste(text: string) {
|
||||
if (text) {
|
||||
const network = state.node_manager?.get_network() || "signet";
|
||||
const network = state.mutiny_wallet?.get_network() || "signet";
|
||||
const result = toParsedParams(text || "", network);
|
||||
if (!result.ok) {
|
||||
showToast(result.error);
|
||||
@@ -230,21 +230,21 @@ export default function Send() {
|
||||
const bolt11 = invoice()?.bolt11;
|
||||
const sentDetails: Partial<SentDetails> = {};
|
||||
if (source() === "lightning" && invoice() && bolt11) {
|
||||
const nodes = await state.node_manager?.list_nodes();
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
sentDetails.destination = bolt11;
|
||||
// If the invoice has sats use that, otherwise we pass the user-defined amount
|
||||
if (invoice()?.amount_sats) {
|
||||
await state.node_manager?.pay_invoice(firstNode, bolt11);
|
||||
await state.mutiny_wallet?.pay_invoice(firstNode, bolt11);
|
||||
sentDetails.amount = invoice()?.amount_sats;
|
||||
} else {
|
||||
await state.node_manager?.pay_invoice(firstNode, bolt11, amountSats());
|
||||
await state.mutiny_wallet?.pay_invoice(firstNode, bolt11, amountSats());
|
||||
sentDetails.amount = amountSats();
|
||||
}
|
||||
} else if (source() === "lightning" && nodePubkey()) {
|
||||
const nodes = await state.node_manager?.list_nodes();
|
||||
const nodes = await state.mutiny_wallet?.list_nodes();
|
||||
const firstNode = nodes[0] as string || ""
|
||||
const payment = await state.node_manager?.keysend(firstNode, nodePubkey()!, amountSats());
|
||||
const payment = await state.mutiny_wallet?.keysend(firstNode, nodePubkey()!, amountSats());
|
||||
console.log(payment?.value)
|
||||
|
||||
// TODO: handle timeouts
|
||||
@@ -254,8 +254,9 @@ export default function Send() {
|
||||
sentDetails.amount = amountSats();
|
||||
}
|
||||
} else if (source() === "onchain" && address()) {
|
||||
// FIXME: actual labels
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const txid = await state.node_manager?.send_to_address(address()!, amountSats());
|
||||
const txid = await state.mutiny_wallet?.send_to_address(address()!, amountSats(), []);
|
||||
sentDetails.amount = amountSats();
|
||||
sentDetails.destination = address();
|
||||
// TODO: figure out if this is necessary, it takes forever
|
||||
@@ -280,7 +281,7 @@ export default function Send() {
|
||||
})
|
||||
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink />
|
||||
@@ -302,7 +303,7 @@ export default function Send() {
|
||||
<img src={megacheck} alt="success" class="w-1/2 mx-auto max-w-[50vh]" />
|
||||
<Amount amountSats={sentDetails()?.amount} showFiat />
|
||||
<Show when={sentDetails()?.txid}>
|
||||
<a href={mempoolTxUrl(sentDetails()?.txid, state.node_manager?.get_network())} target="_blank" rel="noreferrer">
|
||||
<a href={mempoolTxUrl(sentDetails()?.txid, state.mutiny_wallet?.get_network())} target="_blank" rel="noreferrer">
|
||||
Mempool Link
|
||||
</a>
|
||||
</Show>
|
||||
@@ -335,6 +336,6 @@ export default function Send() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="send" />
|
||||
</SafeArea >
|
||||
</NodeManagerGuard >
|
||||
</MutinyWalletGuard >
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ButtonLink, DefaultMain, LargeHeader, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { ButtonLink, DefaultMain, LargeHeader, MutinyWalletGuard, SafeArea, VStack } from "~/components/layout";
|
||||
import { BackLink } from "~/components/layout/BackLink";
|
||||
import NavBar from "~/components/NavBar";
|
||||
import { SeedWords } from "~/components/SeedWords";
|
||||
@@ -9,7 +9,7 @@ export default function Settings() {
|
||||
const [store, _actions] = useMegaStore();
|
||||
|
||||
return (
|
||||
<NodeManagerGuard>
|
||||
<MutinyWalletGuard>
|
||||
<SafeArea>
|
||||
<DefaultMain>
|
||||
<BackLink />
|
||||
@@ -17,7 +17,7 @@ export default function Settings() {
|
||||
<VStack biggap>
|
||||
<VStack>
|
||||
<p class="text-2xl font-light">Write down these words or you'll die!</p>
|
||||
<SeedWords words={store.node_manager?.show_seed() || ""} />
|
||||
<SeedWords words={store.mutiny_wallet?.show_seed() || ""} />
|
||||
</VStack>
|
||||
<SettingsStringsEditor />
|
||||
<ButtonLink href="/admin">"I know what I'm doing"</ButtonLink>
|
||||
@@ -25,6 +25,6 @@ export default function Settings() {
|
||||
</DefaultMain>
|
||||
<NavBar activeTab="settings" />
|
||||
</SafeArea>
|
||||
</NodeManagerGuard>
|
||||
</MutinyWalletGuard>
|
||||
)
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
// Inspired by https://github.com/solidjs/solid-realworld/blob/main/src/store/index.js
|
||||
import { ParentComponent, createContext, createEffect, onCleanup, onMount, useContext } from "solid-js";
|
||||
import { createStore } from "solid-js/store";
|
||||
import { NodeManagerSettingStrings, setupNodeManager } from "~/logic/nodeManagerSetup";
|
||||
import { MutinyBalance, NodeManager } from "@mutinywallet/mutiny-wasm";
|
||||
import { MutinyWalletSettingStrings, setupMutinyWallet } from "~/logic/mutinyWalletSetup";
|
||||
import { MutinyBalance, MutinyWallet } from "@mutinywallet/mutiny-wasm";
|
||||
import { ParsedParams } from "~/routes/Scanner";
|
||||
|
||||
const MegaStoreContext = createContext<MegaStore>();
|
||||
@@ -13,7 +13,8 @@ type UserStatus = undefined | "new_here" | "waitlisted" | "approved" | "paid"
|
||||
|
||||
export type MegaStore = [{
|
||||
waitlist_id?: string;
|
||||
node_manager?: NodeManager;
|
||||
mutiny_wallet?: MutinyWallet;
|
||||
deleting: boolean;
|
||||
user_status: UserStatus;
|
||||
scan_result?: ParsedParams;
|
||||
balance?: MutinyBalance;
|
||||
@@ -24,7 +25,8 @@ export type MegaStore = [{
|
||||
dismissed_restore_prompt: boolean
|
||||
}, {
|
||||
fetchUserStatus(): Promise<UserStatus>;
|
||||
setupNodeManager(settings?: NodeManagerSettingStrings): Promise<void>;
|
||||
setupMutinyWallet(settings?: MutinyWalletSettingStrings): Promise<void>;
|
||||
deleteMutinyWallet(): Promise<void>;
|
||||
setWaitlistId(waitlist_id: string): void;
|
||||
setScanResult(scan_result: ParsedParams | undefined): void;
|
||||
sync(): Promise<void>;
|
||||
@@ -35,7 +37,8 @@ export type MegaStore = [{
|
||||
export const Provider: ParentComponent = (props) => {
|
||||
const [state, setState] = createStore({
|
||||
waitlist_id: localStorage.getItem("waitlist_id"),
|
||||
node_manager: undefined as NodeManager | undefined,
|
||||
mutiny_wallet: undefined as MutinyWallet | undefined,
|
||||
deleting: false,
|
||||
user_status: undefined as UserStatus,
|
||||
scan_result: undefined as ParsedParams | undefined,
|
||||
// TODO: wire this up to real price once we have caching
|
||||
@@ -66,24 +69,34 @@ export const Provider: ParentComponent = (props) => {
|
||||
return "new_here"
|
||||
}
|
||||
},
|
||||
async setupNodeManager(settings?: NodeManagerSettingStrings): Promise<void> {
|
||||
async setupMutinyWallet(settings?: MutinyWalletSettingStrings): Promise<void> {
|
||||
try {
|
||||
const nodeManager = await setupNodeManager(settings)
|
||||
setState({ node_manager: nodeManager })
|
||||
const mutinyWallet = await setupMutinyWallet(settings)
|
||||
setState({ mutiny_wallet: mutinyWallet })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
async deleteMutinyWallet(): Promise<void> {
|
||||
await state.mutiny_wallet?.stop();
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
mutiny_wallet: undefined,
|
||||
deleting: true,
|
||||
}));
|
||||
MutinyWallet.import_json("{}");
|
||||
localStorage.clear();
|
||||
},
|
||||
setWaitlistId(waitlist_id: string) {
|
||||
setState({ waitlist_id })
|
||||
},
|
||||
async sync(): Promise<void> {
|
||||
console.time("BDK Sync Time")
|
||||
try {
|
||||
if (state.node_manager && !state.is_syncing) {
|
||||
if (state.mutiny_wallet && !state.is_syncing) {
|
||||
setState({ is_syncing: true })
|
||||
await state.node_manager?.sync()
|
||||
const balance = await state.node_manager?.get_balance();
|
||||
await state.mutiny_wallet?.sync()
|
||||
const balance = await state.mutiny_wallet?.get_balance();
|
||||
setState({ balance, last_sync: Date.now() })
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -115,9 +128,9 @@ export const Provider: ParentComponent = (props) => {
|
||||
|
||||
// Only load node manager when status is approved
|
||||
createEffect(() => {
|
||||
if (state.user_status === "approved" && !state.node_manager) {
|
||||
if (state.user_status === "approved" && !state.mutiny_wallet && !state.deleting) {
|
||||
console.log("running setup node manager...")
|
||||
actions.setupNodeManager().then(() => console.log("node manager setup done"))
|
||||
actions.setupMutinyWallet().then(() => console.log("node manager setup done"))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -152,4 +165,4 @@ export function useMegaStore() {
|
||||
throw new Error("useMegaStore: cannot find a MegaStoreContext")
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { NodeManager } from "@mutinywallet/mutiny-wasm";
|
||||
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
|
||||
|
||||
export function satsToUsd(amount: number | undefined, price: number, formatted: boolean): string {
|
||||
if (typeof amount !== "number" || isNaN(amount)) {
|
||||
return ""
|
||||
}
|
||||
try {
|
||||
const btc = NodeManager.convert_sats_to_btc(BigInt(Math.floor(amount)));
|
||||
const btc = MutinyWallet.convert_sats_to_btc(BigInt(Math.floor(amount)));
|
||||
const usd = btc * price;
|
||||
|
||||
if (formatted) {
|
||||
@@ -26,7 +26,7 @@ export function usdToSats(amount: number | undefined, price: number, formatted:
|
||||
}
|
||||
try {
|
||||
const btc = price / amount;
|
||||
const sats = NodeManager.convert_btc_to_sats(btc);
|
||||
const sats = MutinyWallet.convert_btc_to_sats(btc);
|
||||
if (formatted) {
|
||||
return parseInt(sats.toString()).toLocaleString();
|
||||
} else {
|
||||
|
||||
19
src/utils/fakeLabels.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// Simple storage for fake labels
|
||||
// For each outpoint string, we can store a boolean whether it's redshifted or not
|
||||
|
||||
function setRedshifted(redshifted: boolean, outpoint?: string,) {
|
||||
if (outpoint === undefined) return;
|
||||
localStorage.setItem(outpoint, redshifted.toString())
|
||||
}
|
||||
|
||||
function getRedshifted(outpoint: string): boolean {
|
||||
const redshifted = localStorage.getItem(outpoint)
|
||||
if (redshifted === null) {
|
||||
return false
|
||||
}
|
||||
return redshifted === 'true'
|
||||
}
|
||||
|
||||
const TEST_UTXO = "47651763fbd74488a478aad80e4205c3e34bbadcfc42b5cd9557ef12a15ab00c:1"
|
||||
|
||||
export { setRedshifted, getRedshifted, TEST_UTXO }
|
||||
@@ -52,7 +52,7 @@ export default defineConfig({
|
||||
},
|
||||
optimizeDeps: {
|
||||
// Don't want vite to bundle these late during dev causing reload
|
||||
include: ["qr-scanner", "nostr-tools", "class-variance-authority"],
|
||||
include: ["qr-scanner", "nostr-tools", "class-variance-authority", "@kobalte/core", "@solid-primitives/upload"],
|
||||
// This is necessary because otherwise `vite dev` can't find the wasm
|
||||
exclude: ["@mutinywallet/mutiny-wasm", "@mutinywallet/waila-wasm"],
|
||||
},
|
||||
|
||||