Merge pull request #83 from MutinyWallet/send-receive-fixups

Send receive fixups
This commit is contained in:
Paul Miller
2023-05-09 08:51:21 -05:00
committed by GitHub
31 changed files with 615 additions and 460 deletions

View File

@@ -4,7 +4,6 @@ module.exports = {
"es2021": true
},
"extends": [
"prettier",
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:solid/typescript",

View File

@@ -9,12 +9,12 @@
},
"type": "module",
"devDependencies": {
"@types/node": "^18.16.4",
"@types/node": "^18.16.5",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"autoprefixer": "^10.4.14",
"esbuild": "^0.14.54",
"eslint": "^8.39.0",
"eslint": "^8.40.0",
"eslint-import-resolver-typescript": "2.7.1",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-prettier": "4.2.1",
@@ -31,7 +31,7 @@
"dependencies": {
"@kobalte/core": "^0.8.2",
"@kobalte/tailwindcss": "^0.5.0",
"@modular-forms/solid": "^0.13.1",
"@modular-forms/solid": "^0.13.2",
"@mutinywallet/mutiny-wasm": "^0.2.8",
"@mutinywallet/waila-wasm": "^0.1.5",
"@solid-primitives/upload": "^0.0.111",
@@ -41,12 +41,20 @@
"class-variance-authority": "^0.4.0",
"nostr-tools": "^1.10.1",
"qr-scanner": "^1.4.2",
"solid-js": "^1.7.4",
"solid-js": "^1.7.5",
"solid-qr-code": "^0.0.8",
"solid-start": "^0.2.26",
"undici": "^5.22.0"
},
"engines": {
"node": ">=16.8"
},
"prettier": {
"semi": false,
"singleQuote": false,
"trailingComma": "es5",
"printWidth": 80,
"tabWidth": 2,
"useTabs": false
}
}

364
pnpm-lock.yaml generated
View File

@@ -3,13 +3,13 @@ lockfileVersion: '6.0'
dependencies:
'@kobalte/core':
specifier: ^0.8.2
version: 0.8.2(solid-js@1.7.4)
version: 0.8.2(solid-js@1.7.5)
'@kobalte/tailwindcss':
specifier: ^0.5.0
version: 0.5.0(tailwindcss@3.3.2)
'@modular-forms/solid':
specifier: ^0.13.1
version: 0.13.1(solid-js@1.7.4)
specifier: ^0.13.2
version: 0.13.2(solid-js@1.7.5)
'@mutinywallet/mutiny-wasm':
specifier: ^0.2.8
version: 0.2.8
@@ -18,16 +18,16 @@ dependencies:
version: 0.1.5
'@solid-primitives/upload':
specifier: ^0.0.111
version: 0.0.111(solid-js@1.7.4)
version: 0.0.111(solid-js@1.7.5)
'@solidjs/meta':
specifier: ^0.28.4
version: 0.28.4(solid-js@1.7.4)
version: 0.28.4(solid-js@1.7.5)
'@solidjs/router':
specifier: ^0.8.2
version: 0.8.2(solid-js@1.7.4)
version: 0.8.2(solid-js@1.7.5)
'@thisbeyond/solid-select':
specifier: ^0.14.0
version: 0.14.0(solid-js@1.7.4)
version: 0.14.0(solid-js@1.7.5)
class-variance-authority:
specifier: ^0.4.0
version: 0.4.0(typescript@4.9.5)
@@ -38,28 +38,28 @@ dependencies:
specifier: ^1.4.2
version: 1.4.2
solid-js:
specifier: ^1.7.4
version: 1.7.4
specifier: ^1.7.5
version: 1.7.5
solid-qr-code:
specifier: ^0.0.8
version: 0.0.8(qr.js@0.0.0)(solid-js@1.7.4)
version: 0.0.8(qr.js@0.0.0)(solid-js@1.7.5)
solid-start:
specifier: ^0.2.26
version: 0.2.26(@solidjs/meta@0.28.4)(@solidjs/router@0.8.2)(solid-js@1.7.4)(solid-start-node@0.2.26)(vite@4.3.5)
version: 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)
undici:
specifier: ^5.22.0
version: 5.22.0
devDependencies:
'@types/node':
specifier: ^18.16.4
version: 18.16.4
specifier: ^18.16.5
version: 18.16.5
'@typescript-eslint/eslint-plugin':
specifier: ^5.59.2
version: 5.59.2(@typescript-eslint/parser@5.59.2)(eslint@8.39.0)(typescript@4.9.5)
version: 5.59.2(@typescript-eslint/parser@5.59.2)(eslint@8.40.0)(typescript@4.9.5)
'@typescript-eslint/parser':
specifier: ^5.59.2
version: 5.59.2(eslint@8.39.0)(typescript@4.9.5)
version: 5.59.2(eslint@8.40.0)(typescript@4.9.5)
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.23)
@@ -67,20 +67,20 @@ devDependencies:
specifier: ^0.14.54
version: 0.14.54
eslint:
specifier: ^8.39.0
version: 8.39.0
specifier: ^8.40.0
version: 8.40.0
eslint-import-resolver-typescript:
specifier: 2.7.1
version: 2.7.1(eslint-plugin-import@2.27.5)(eslint@8.39.0)
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.39.0)
version: 2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0)
eslint-plugin-prettier:
specifier: 4.2.1
version: 4.2.1(eslint@8.39.0)(prettier@2.8.8)
version: 4.2.1(eslint@8.40.0)(prettier@2.8.8)
eslint-plugin-solid:
specifier: 0.11.0
version: 0.11.0(eslint@8.39.0)(typescript@4.9.5)
version: 0.11.0(eslint@8.40.0)(typescript@4.9.5)
postcss:
specifier: ^8.4.23
version: 8.4.23
@@ -95,7 +95,7 @@ devDependencies:
version: 4.9.5
vite:
specifier: ^4.3.5
version: 4.3.5(@types/node@18.16.4)
version: 4.3.5(@types/node@18.16.5)
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)
@@ -1161,7 +1161,7 @@ packages:
babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.8)
babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.8)
babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.8)
core-js-compat: 3.30.1
core-js-compat: 3.30.2
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -1420,14 +1420,14 @@ packages:
requiresBuild: true
optional: true
/@eslint-community/eslint-utils@4.4.0(eslint@8.39.0):
/@eslint-community/eslint-utils@4.4.0(eslint@8.40.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
eslint: 8.39.0
eslint-visitor-keys: 3.4.0
eslint: 8.40.0
eslint-visitor-keys: 3.4.1
dev: true
/@eslint-community/regexpp@4.5.1:
@@ -1435,13 +1435,13 @@ packages:
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
dev: true
/@eslint/eslintrc@2.0.2:
resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==}
/@eslint/eslintrc@2.0.3:
resolution: {integrity: sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.4
espree: 9.5.1
espree: 9.5.2
globals: 13.20.0
ignore: 5.2.4
import-fresh: 3.3.0
@@ -1452,8 +1452,8 @@ packages:
- supports-color
dev: true
/@eslint/js@8.39.0:
resolution: {integrity: sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==}
/@eslint/js@8.40.0:
resolution: {integrity: sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
@@ -1547,7 +1547,7 @@ packages:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
/@kobalte/core@0.8.2(solid-js@1.7.4):
/@kobalte/core@0.8.2(solid-js@1.7.5):
resolution: {integrity: sha512-EoBYKpYa3+Csr5Zh7l3aY3yAg7fk1O3ZM9lGyD1mdQ1FutTuwTkyj8z1CvSSj1Klb+rBL+X1N662Occ8Bmsi2w==}
peerDependencies:
solid-js: ^1.6.15
@@ -1556,8 +1556,8 @@ packages:
'@internationalized/date': 3.2.0
'@internationalized/number': 3.2.0
'@internationalized/string': 3.1.0
'@kobalte/utils': 0.6.1(solid-js@1.7.4)
solid-js: 1.7.4
'@kobalte/utils': 0.6.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@kobalte/tailwindcss@0.5.0(tailwindcss@3.3.2):
@@ -1568,26 +1568,26 @@ packages:
tailwindcss: 3.3.2
dev: false
/@kobalte/utils@0.6.1(solid-js@1.7.4):
/@kobalte/utils@0.6.1(solid-js@1.7.5):
resolution: {integrity: sha512-YvBqe9t9j0iYFUHfKXSMLQKM3s5+nL72RvT9b75W+IOxUpSpN4rdaI8C2j97k3LsEt7qY4ktJdt8lPM1rr8JXw==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/event-listener': 2.2.10(solid-js@1.7.4)
'@solid-primitives/keyed': 1.2.0(solid-js@1.7.4)
'@solid-primitives/media': 2.1.6(solid-js@1.7.4)
'@solid-primitives/props': 3.1.4(solid-js@1.7.4)
'@solid-primitives/refs': 1.0.2(solid-js@1.7.4)
'@solid-primitives/utils': 5.5.2(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/event-listener': 2.2.11(solid-js@1.7.5)
'@solid-primitives/keyed': 1.2.0(solid-js@1.7.5)
'@solid-primitives/media': 2.2.1(solid-js@1.7.5)
'@solid-primitives/props': 3.1.5(solid-js@1.7.5)
'@solid-primitives/refs': 1.0.3(solid-js@1.7.5)
'@solid-primitives/utils': 5.5.2(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@modular-forms/solid@0.13.1(solid-js@1.7.4):
resolution: {integrity: sha512-4Rx7drZ3/bZK46lfGbIyExYfPcPnpEDXcA9xhrUaLoZNWuMvPLTt8ctN6SZaqM5xvkGuE5dElUltqORk9eHA9A==}
/@modular-forms/solid@0.13.2(solid-js@1.7.5):
resolution: {integrity: sha512-wiwJUxbwDp8F2FI0hTYoydNumVRZruIiyjV+w91++zA0QofASuMWe3fs4lETHpaiQK/jJsGXhys7BFqXUf9SDg==}
peerDependencies:
solid-js: ^1.3.1
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/@mutinywallet/mutiny-wasm@0.2.8:
@@ -1785,109 +1785,109 @@ packages:
/@sideway/pinpoint@2.0.0:
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
/@solid-primitives/event-listener@2.2.10(solid-js@1.7.4):
resolution: {integrity: sha512-rWBCeF1NRAmLJtVo2wpY9vF3IAQ8VAxGnFDOUqROSdYhUfiCeM7Hw3PKkGCELwNQzZK1W1z+MjzB7fctpjX4Sg==}
/@solid-primitives/event-listener@2.2.11(solid-js@1.7.5):
resolution: {integrity: sha512-pX/offimvt8qtXxwk3kUB6R7igVhnXmSHosQ0ITBOPQvcyhB9Lfrb80zSM8Z0MUf6ZKWyt5n8lco+yK5v2+bIg==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/keyed@1.2.0(solid-js@1.7.4):
/@solid-primitives/keyed@1.2.0(solid-js@1.7.5):
resolution: {integrity: sha512-0DuTeJdxWjCTu73XnDZs24JzfXckBnpvCfQ6Mf/kTPKkMZJh7tjkBnZEk48ckrE9xmwat9stIdfrBmZctsepIw==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/@solid-primitives/media@2.1.6(solid-js@1.7.4):
resolution: {integrity: sha512-7yixsXmhZfbsAxk/glmTFWcacXhudYsbc/9kbC7EbaE+Jnd6i0HZmmQEkV+s/rZ32e5sE9dAHvlhPtiLbQb7Jg==}
/@solid-primitives/media@2.2.1(solid-js@1.7.5):
resolution: {integrity: sha512-KhfGIGox8zJlKKMAzj/Up9wvsZ6qgiN1htBV/fe7FKvqr+jjhnPl+71DzmdmcrW1JY3cuE5bNWpSubc8TD7dJw==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/event-listener': 2.2.10(solid-js@1.7.4)
'@solid-primitives/rootless': 1.3.2(solid-js@1.7.4)
'@solid-primitives/static-store': 0.0.2(solid-js@1.7.4)
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/event-listener': 2.2.11(solid-js@1.7.5)
'@solid-primitives/rootless': 1.4.0(solid-js@1.7.5)
'@solid-primitives/static-store': 0.0.3(solid-js@1.7.5)
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/props@3.1.4(solid-js@1.7.4):
resolution: {integrity: sha512-RiwOZXbqb3RMmkznyfI63gwAB/iVHPk8AWN55oIEBRkjzgpuqRXIzdbsSQVy23jMbkRs91tRtzxQ/g6eoWLnuQ==}
/@solid-primitives/props@3.1.5(solid-js@1.7.5):
resolution: {integrity: sha512-rnFjo3PgH2I4wJEGaMY+iKETfPntq9GMLbdX6bhllMocwF/CHILii4Hfgg41nhcGjJysuCSlA4WTq33ZD/9CFw==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/refs@1.0.2(solid-js@1.7.4):
resolution: {integrity: sha512-qnqQRdYbsENlVx86QCfftRKGZ/9zUJMGK9U85xDRymocEyeUXxdxgq0FeyGhvgg4A25spJVwHmuZUGY0aMBBLA==}
/@solid-primitives/refs@1.0.3(solid-js@1.7.5):
resolution: {integrity: sha512-LjB/qUCyke5socrcUxPGBv2GlciOjpba7HC1EIz6gihSePdu+SF3w+p2WaV4pACJy8ELacJ2lNq4EbAK7sTkAg==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/rootless@1.3.2(solid-js@1.7.4):
resolution: {integrity: sha512-R1rncXOUcB/i3PyvKhSWcsocPRe1n3HsMIO717RpWFd2knUF8+b0cGgRDEoneGaV/a5kq4cqH3csa66klxuM3A==}
/@solid-primitives/rootless@1.4.0(solid-js@1.7.5):
resolution: {integrity: sha512-hShkSvajBQKWI0g1oNKfLb3W5owQIhW1wBaMBgq/sAdUhWevyM+ldYab2bry5vnh7DxemLSCrtvFJWNTHCuJgQ==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/static-store@0.0.2(solid-js@1.7.4):
resolution: {integrity: sha512-JR51MmoZbFWE7fmzm0NnfS4RuLHpzXpPqAb7RJu3fHDGHp+q7v4KylseULcailINzDIosHQXbpiDQlj2Lx9zbQ==}
/@solid-primitives/static-store@0.0.3(solid-js@1.7.5):
resolution: {integrity: sha512-OHwr9w8gb+IZGGEdmPL5Oet62p4c8Py3AaxxOopxv++SmGoed2niO8nORNbUk/riScvqzeDpOrAuQ//fYPm2tw==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/upload@0.0.111(solid-js@1.7.4):
/@solid-primitives/upload@0.0.111(solid-js@1.7.5):
resolution: {integrity: sha512-Bxe2W5oJu7kRurmxr+ftvOojKhy5JUM91md2nBcedwrq1EspqWggV2ZOHauGcn8hg86W8p9Y+N8dmv16QHNRxQ==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
'@solid-primitives/utils': 6.1.0(solid-js@1.7.4)
solid-js: 1.7.4
'@solid-primitives/utils': 6.1.1(solid-js@1.7.5)
solid-js: 1.7.5
dev: false
/@solid-primitives/utils@5.5.2(solid-js@1.7.4):
/@solid-primitives/utils@5.5.2(solid-js@1.7.5):
resolution: {integrity: sha512-L52ig3eHKU6CqbPCKJIb4lweBuINHBOERcE1duApyKozEN8+zCqEKwD1Qo9ljKeEzJTBGWClxNpwEiNTUWTGvg==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/@solid-primitives/utils@6.1.0(solid-js@1.7.4):
resolution: {integrity: sha512-uTikKFrq33UO+MnKt2WzZr9WYbQe5YX58ytGkL+29DL6o0pZs1wrICbd4ymzSm8azqzMcQqEQOL3HLWjuv9tLw==}
/@solid-primitives/utils@6.1.1(solid-js@1.7.5):
resolution: {integrity: sha512-wxxUdxja126jTROs9Ro8Z5ExbHs9rv2Tl744S3Qmzki/gTcTXW8D1TvTArQcjqkCvSw8OIQ2EO2NI8sR28Trxg==}
peerDependencies:
solid-js: ^1.6.12
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/@solidjs/meta@0.28.4(solid-js@1.7.4):
/@solidjs/meta@0.28.4(solid-js@1.7.5):
resolution: {integrity: sha512-1USElsQuGVcJnmZ6CxPfUVmKvCsVdBQoGrUyMxLtFw36Ytt90dPs/qLyXLvPR/ZPD16/qauWqg6APEkbrDOLcA==}
peerDependencies:
solid-js: '>=1.4.0'
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
/@solidjs/router@0.8.2(solid-js@1.7.4):
/@solidjs/router@0.8.2(solid-js@1.7.5):
resolution: {integrity: sha512-gUKW+LZqxtX6y/Aw6JKyy4gQ9E7dLqp513oB9pSYJR1HM5c56Pf7eijzyXX+b3WuXig18Cxqah4tMtF0YGu80w==}
peerDependencies:
solid-js: ^1.5.3
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
/@surma/rollup-plugin-off-main-thread@2.2.3:
resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
@@ -1904,12 +1904,12 @@ packages:
tslib: 2.5.0
dev: false
/@thisbeyond/solid-select@0.14.0(solid-js@1.7.4):
/@thisbeyond/solid-select@0.14.0(solid-js@1.7.5):
resolution: {integrity: sha512-ecq4U3Vnc/nJbU84ARuPg2scNuYt994ljF5AmBlzuZW87x43mWiGJ5hEWufIJJMpDT6CcnCIx/xbrdDkaDEHQw==}
peerDependencies:
solid-js: ^1.5
dependencies:
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/@types/babel__core@7.20.0:
@@ -1955,8 +1955,8 @@ packages:
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
dev: true
/@types/node@18.16.4:
resolution: {integrity: sha512-LUhvPmAKAbgm+p/K11IWszLZVoZDlMF4NRmqbhEzDz/CnCuehPkZXwZbBCKGJsgjnuVejotBwM7B3Scrq4EqDw==}
/@types/node@18.16.5:
resolution: {integrity: sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==}
/@types/offscreencanvas@2019.7.0:
resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==}
@@ -1965,7 +1965,7 @@ packages:
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
'@types/node': 18.16.4
'@types/node': 18.16.5
dev: true
/@types/resolve@1.20.2:
@@ -1979,7 +1979,7 @@ packages:
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
dev: true
/@typescript-eslint/eslint-plugin@5.59.2(@typescript-eslint/parser@5.59.2)(eslint@8.39.0)(typescript@4.9.5):
/@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==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -1991,12 +1991,12 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.5.1
'@typescript-eslint/parser': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
'@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.39.0)(typescript@4.9.5)
'@typescript-eslint/utils': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
'@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)
debug: 4.3.4
eslint: 8.39.0
eslint: 8.40.0
grapheme-splitter: 1.0.4
ignore: 5.2.4
natural-compare-lite: 1.4.0
@@ -2007,7 +2007,7 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser@5.59.2(eslint@8.39.0)(typescript@4.9.5):
/@typescript-eslint/parser@5.59.2(eslint@8.40.0)(typescript@4.9.5):
resolution: {integrity: sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -2021,7 +2021,7 @@ packages:
'@typescript-eslint/types': 5.59.2
'@typescript-eslint/typescript-estree': 5.59.2(typescript@4.9.5)
debug: 4.3.4
eslint: 8.39.0
eslint: 8.40.0
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
@@ -2035,7 +2035,7 @@ packages:
'@typescript-eslint/visitor-keys': 5.59.2
dev: true
/@typescript-eslint/type-utils@5.59.2(eslint@8.39.0)(typescript@4.9.5):
/@typescript-eslint/type-utils@5.59.2(eslint@8.40.0)(typescript@4.9.5):
resolution: {integrity: sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -2046,9 +2046,9 @@ packages:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.59.2(typescript@4.9.5)
'@typescript-eslint/utils': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
'@typescript-eslint/utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
debug: 4.3.4
eslint: 8.39.0
eslint: 8.40.0
tsutils: 3.21.0(typescript@4.9.5)
typescript: 4.9.5
transitivePeerDependencies:
@@ -2081,19 +2081,19 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils@5.59.2(eslint@8.39.0)(typescript@4.9.5):
/@typescript-eslint/utils@5.59.2(eslint@8.40.0)(typescript@4.9.5):
resolution: {integrity: sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==}
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.39.0)
'@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)
eslint: 8.39.0
eslint: 8.40.0
eslint-scope: 5.1.1
semver: 7.5.0
transitivePeerDependencies:
@@ -2106,7 +2106,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.2
eslint-visitor-keys: 3.4.0
eslint-visitor-keys: 3.4.1
dev: true
/accepts@1.3.8:
@@ -2240,7 +2240,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.21.5
caniuse-lite: 1.0.30001482
caniuse-lite: 1.0.30001486
fraction.js: 4.2.0
normalize-range: 0.1.2
picocolors: 1.0.0
@@ -2291,7 +2291,7 @@ packages:
dependencies:
'@babel/core': 7.21.8
'@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8)
core-js-compat: 3.30.1
core-js-compat: 3.30.2
transitivePeerDependencies:
- supports-color
@@ -2342,8 +2342,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001482
electron-to-chromium: 1.4.384
caniuse-lite: 1.0.30001486
electron-to-chromium: 1.4.385
node-releases: 2.0.10
update-browserslist-db: 1.0.11(browserslist@4.21.5)
@@ -2380,8 +2380,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
/caniuse-lite@1.0.30001482:
resolution: {integrity: sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ==}
/caniuse-lite@1.0.30001486:
resolution: {integrity: sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==}
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
@@ -2501,8 +2501,8 @@ packages:
/convert-source-map@1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
/core-js-compat@3.30.1:
resolution: {integrity: sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==}
/core-js-compat@3.30.2:
resolution: {integrity: sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==}
dependencies:
browserslist: 4.21.5
@@ -2626,8 +2626,8 @@ packages:
jake: 10.8.5
dev: true
/electron-to-chromium@1.4.384:
resolution: {integrity: sha512-I97q0MmRAAqj53+a8vZsDkEXBZki+ehYAOPzwtQzALip52aEp2+BJqHFtTlsfjoqVZYwPpHC8wM6MbsSZQ/Eqw==}
/electron-to-chromium@1.4.385:
resolution: {integrity: sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg==}
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -2847,7 +2847,7 @@ packages:
dev: true
optional: true
/esbuild-plugin-solid@0.5.0(esbuild@0.17.18)(solid-js@1.7.4):
/esbuild-plugin-solid@0.5.0(esbuild@0.17.18)(solid-js@1.7.5):
resolution: {integrity: sha512-ITK6n+0ayGFeDVUZWNMxX+vLsasEN1ILrg4pISsNOQ+mq4ljlJJiuXotInd+HE0MzwTcA9wExT1yzDE2hsqPsg==}
peerDependencies:
esbuild: '>=0.12'
@@ -2857,7 +2857,7 @@ packages:
'@babel/preset-typescript': 7.21.5(@babel/core@7.21.8)
babel-preset-solid: 1.7.4(@babel/core@7.21.8)
esbuild: 0.17.18
solid-js: 1.7.4
solid-js: 1.7.5
transitivePeerDependencies:
- supports-color
@@ -2981,7 +2981,7 @@ packages:
- supports-color
dev: true
/eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.27.5)(eslint@8.39.0):
/eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.27.5)(eslint@8.40.0):
resolution: {integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==}
engines: {node: '>=4'}
peerDependencies:
@@ -2989,8 +2989,8 @@ packages:
eslint-plugin-import: '*'
dependencies:
debug: 4.3.4
eslint: 8.39.0
eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.39.0)
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)
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.39.0):
/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):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
@@ -3020,16 +3020,16 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
debug: 3.2.7
eslint: 8.39.0
eslint: 8.40.0
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.27.5)(eslint@8.39.0)
eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.27.5)(eslint@8.40.0)
transitivePeerDependencies:
- 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.39.0):
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.2)(eslint-import-resolver-typescript@2.7.1)(eslint@8.40.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
@@ -3039,15 +3039,15 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
'@typescript-eslint/parser': 5.59.2(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
debug: 3.2.7
doctrine: 2.1.0
eslint: 8.39.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.39.0)
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)
has: 1.0.3
is-core-module: 2.12.0
is-glob: 4.0.3
@@ -3062,7 +3062,7 @@ packages:
- supports-color
dev: true
/eslint-plugin-prettier@4.2.1(eslint@8.39.0)(prettier@2.8.8):
/eslint-plugin-prettier@4.2.1(eslint@8.40.0)(prettier@2.8.8):
resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==}
engines: {node: '>=12.0.0'}
peerDependencies:
@@ -3073,19 +3073,19 @@ packages:
eslint-config-prettier:
optional: true
dependencies:
eslint: 8.39.0
eslint: 8.40.0
prettier: 2.8.8
prettier-linter-helpers: 1.0.0
dev: true
/eslint-plugin-solid@0.11.0(eslint@8.39.0)(typescript@4.9.5):
/eslint-plugin-solid@0.11.0(eslint@8.40.0)(typescript@4.9.5):
resolution: {integrity: sha512-3ve6IpEtl8nOvJnjaJACqlBmv449l6dMMhMczjQWvvLlRqkzLemgsJ9H+Isu8GLSBTNxDIm5oSKx/lO2j8vKbA==}
engines: {node: '>=12.0.0'}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@typescript-eslint/utils': 5.59.2(eslint@8.39.0)(typescript@4.9.5)
eslint: 8.39.0
'@typescript-eslint/utils': 5.59.2(eslint@8.40.0)(typescript@4.9.5)
eslint: 8.40.0
is-html: 2.0.0
jsx-ast-utils: 3.3.3
kebab-case: 1.0.2
@@ -3112,20 +3112,20 @@ packages:
estraverse: 5.3.0
dev: true
/eslint-visitor-keys@3.4.0:
resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==}
/eslint-visitor-keys@3.4.1:
resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/eslint@8.39.0:
resolution: {integrity: sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==}
/eslint@8.40.0:
resolution: {integrity: sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0)
'@eslint-community/eslint-utils': 4.4.0(eslint@8.40.0)
'@eslint-community/regexpp': 4.5.1
'@eslint/eslintrc': 2.0.2
'@eslint/js': 8.39.0
'@eslint/eslintrc': 2.0.3
'@eslint/js': 8.40.0
'@humanwhocodes/config-array': 0.11.8
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
@@ -3136,8 +3136,8 @@ packages:
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.0
eslint-visitor-keys: 3.4.0
espree: 9.5.1
eslint-visitor-keys: 3.4.1
espree: 9.5.2
esquery: 1.5.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
@@ -3166,13 +3166,13 @@ packages:
- supports-color
dev: true
/espree@9.5.1:
resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==}
/espree@9.5.2:
resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.8.2
acorn-jsx: 5.3.2(acorn@8.8.2)
eslint-visitor-keys: 3.4.0
eslint-visitor-keys: 3.4.1
dev: true
/esquery@1.5.0:
@@ -3738,8 +3738,8 @@ packages:
call-bind: 1.0.2
dev: true
/is-what@4.1.8:
resolution: {integrity: sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA==}
/is-what@4.1.9:
resolution: {integrity: sha512-I3FU0rkVvwhgLLEs6iITwZ/JaLXe7tQcHyzupXky8jigt1vu4KM0UOqDr963j36JRvJ835EATVIm6MnGz/i1/g==}
engines: {node: '>=12.13'}
/is-wsl@2.2.0:
@@ -3767,7 +3767,7 @@ packages:
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 18.16.4
'@types/node': 18.16.5
merge-stream: 2.0.0
supports-color: 7.2.0
dev: true
@@ -3929,11 +3929,11 @@ packages:
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
/merge-anything@5.1.5:
resolution: {integrity: sha512-9lquMsJxgaef2BXYUy8VnqHmuLYaEiGd7SULqOTuDFA9Lw6g6Hmdsblc6+yqshdJOQKkn9I106+3D5mnQMstvg==}
/merge-anything@5.1.6:
resolution: {integrity: sha512-0SIP3417t0sOL6/crPb6oC+ZNSMrjJeWkydlddgZVzsjQA86l8v3+f3WwvKanbsHxVF80QouJIdSh+Q249bu0g==}
engines: {node: '>=12.13'}
dependencies:
is-what: 4.1.8
is-what: 4.1.9
/merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -4397,7 +4397,7 @@ packages:
jest-worker: 26.6.2
rollup: 2.79.1
serialize-javascript: 4.0.0
terser: 5.17.1
terser: 5.17.2
dev: true
/rollup-plugin-visualizer@5.9.0(rollup@3.21.5):
@@ -4533,13 +4533,13 @@ packages:
engines: {node: '>=8'}
dev: true
/solid-js@1.7.4:
resolution: {integrity: sha512-hD/bzIpaa7DL/LGRRTLFvejQuxQaoXyH+DBgPputJW7zvFigCewQIoDvbwDR4VHTsa8VsMDPzV8BT0F9OqsS1Q==}
/solid-js@1.7.5:
resolution: {integrity: sha512-GfJ8na1e9FG1oAF5xC24BM+ATLym0sfH+ZblkbBFpueYdq3fWAoA5Ve+jGeIeLI7jmMGfa0rUaKruszNm2sH8w==}
dependencies:
csstype: 3.1.2
seroval: 0.5.1
/solid-qr-code@0.0.8(qr.js@0.0.0)(solid-js@1.7.4):
/solid-qr-code@0.0.8(qr.js@0.0.0)(solid-js@1.7.5):
resolution: {integrity: sha512-K7LC3IKvyRag6WW7/ijJl32pBmoC3EzZ7AuydyaAVKSmlwukJmqvrFkrxaA1bOWabYJhzP9qwLbjDVlCUP2BwQ==}
engines: {node: '>=10', yarn: '>=1.22.5'}
peerDependencies:
@@ -4547,10 +4547,10 @@ packages:
solid-js: ^1.4.8
dependencies:
qr.js: 0.0.0
solid-js: 1.7.4
solid-js: 1.7.5
dev: false
/solid-refresh@0.5.2(solid-js@1.7.4):
/solid-refresh@0.5.2(solid-js@1.7.5):
resolution: {integrity: sha512-I69HmFj0LsGRJ3n8CEMVjyQFgVtuM2bSjznu2hCnsY+i5oOxh8ioWj00nnHBv0UYD3WpE/Sq4Q3TNw2IKmKN7A==}
peerDependencies:
solid-js: ^1.3
@@ -4558,7 +4558,7 @@ packages:
'@babel/generator': 7.21.5
'@babel/helper-module-imports': 7.21.4
'@babel/types': 7.21.5
solid-js: 1.7.4
solid-js: 1.7.5
/solid-start-node@0.2.26(solid-start@0.2.26)(undici@5.22.0)(vite@4.3.5):
resolution: {integrity: sha512-8vciTGoQV+lIlCUSVHJPazlaoKDRfBowDkPeBr/EZdmtbcMOKoJYf/APPQWFspylF+nhzunMf0+zJP90VtMEYg==}
@@ -4574,14 +4574,14 @@ packages:
polka: 1.0.0-next.22
rollup: 3.21.5
sirv: 2.0.3
solid-start: 0.2.26(@solidjs/meta@0.28.4)(@solidjs/router@0.8.2)(solid-js@1.7.4)(solid-start-node@0.2.26)(vite@4.3.5)
terser: 5.17.1
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.4)
vite: 4.3.5(@types/node@18.16.5)
transitivePeerDependencies:
- supports-color
/solid-start@0.2.26(@solidjs/meta@0.28.4)(@solidjs/router@0.8.2)(solid-js@1.7.4)(solid-start-node@0.2.26)(vite@4.3.5):
/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):
resolution: {integrity: sha512-kne2HZlnSMzsirdnvNs1CsDqBl0L0uvKKt1t4de1CH7JIngyqoMcER97jTE0Ejr84KknANaKAdvJAzZcL7Ueng==}
hasBin: true
peerDependencies:
@@ -4621,8 +4621,8 @@ packages:
'@babel/preset-env': 7.21.5(@babel/core@7.21.8)
'@babel/preset-typescript': 7.21.5(@babel/core@7.21.8)
'@babel/template': 7.20.7
'@solidjs/meta': 0.28.4(solid-js@1.7.4)
'@solidjs/router': 0.8.2(solid-js@1.7.4)
'@solidjs/meta': 0.28.4(solid-js@1.7.5)
'@solidjs/router': 0.8.2(solid-js@1.7.5)
'@types/cookie': 0.5.1
chokidar: 3.5.3
compression: 1.7.4
@@ -4632,7 +4632,7 @@ packages:
dotenv: 16.0.3
es-module-lexer: 1.2.1
esbuild: 0.17.18
esbuild-plugin-solid: 0.5.0(esbuild@0.17.18)(solid-js@1.7.4)
esbuild-plugin-solid: 0.5.0(esbuild@0.17.18)(solid-js@1.7.5)
fast-glob: 3.2.12
get-port: 6.1.2
parse-multipart-data: 1.5.0
@@ -4643,13 +4643,13 @@ packages:
sade: 1.8.1
set-cookie-parser: 2.6.0
sirv: 2.0.3
solid-js: 1.7.4
solid-js: 1.7.5
solid-start-node: 0.2.26(solid-start@0.2.26)(undici@5.22.0)(vite@4.3.5)
terser: 5.17.1
terser: 5.17.2
undici: 5.22.0
vite: 4.3.5(@types/node@18.16.4)
vite: 4.3.5(@types/node@18.16.5)
vite-plugin-inspect: 0.7.25(rollup@3.21.5)(vite@4.3.5)
vite-plugin-solid: 2.7.0(solid-js@1.7.4)(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:
- supports-color
@@ -4850,8 +4850,8 @@ packages:
unique-string: 2.0.0
dev: true
/terser@5.17.1:
resolution: {integrity: sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==}
/terser@5.17.2:
resolution: {integrity: sha512-1D1aGbOF1Mnayq5PvfMc0amAR1y5Z1nrZaGCvI5xsdEfZEVte8okonk02OiaK5fw5hG1GWuuVsakOnpZW8y25A==}
engines: {node: '>=10'}
hasBin: true
dependencies:
@@ -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.4)
vite: 4.3.5(@types/node@18.16.5)
transitivePeerDependencies:
- rollup
- supports-color
@@ -5073,14 +5073,14 @@ packages:
fast-glob: 3.2.12
pretty-bytes: 6.1.0
rollup: 3.21.5
vite: 4.3.5(@types/node@18.16.4)
vite: 4.3.5(@types/node@18.16.5)
workbox-build: 6.5.4
workbox-window: 6.5.4
transitivePeerDependencies:
- supports-color
dev: true
/vite-plugin-solid@2.7.0(solid-js@1.7.4)(vite@4.3.5):
/vite-plugin-solid@2.7.0(solid-js@1.7.5)(vite@4.3.5):
resolution: {integrity: sha512-avp/Jl5zOp/Itfo67xtDB2O61U7idviaIp4mLsjhCa13PjKNasz+IID0jYTyqUp9SFx6/PmBr6v4KgDppqompg==}
peerDependencies:
solid-js: ^1.7.2
@@ -5090,10 +5090,10 @@ packages:
'@babel/preset-typescript': 7.21.5(@babel/core@7.21.8)
'@types/babel__core': 7.20.0
babel-preset-solid: 1.7.4(@babel/core@7.21.8)
merge-anything: 5.1.5
solid-js: 1.7.4
solid-refresh: 0.5.2(solid-js@1.7.4)
vite: 4.3.5(@types/node@18.16.4)
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)
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.4)
vite: 4.3.5(@types/node@18.16.5)
dev: true
/vite@4.3.5(@types/node@18.16.4):
/vite@4.3.5(@types/node@18.16.5):
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.4
'@types/node': 18.16.5
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.4)
vite: 4.3.5(@types/node@18.16.5)
/wait-on@6.0.1(debug@4.3.4):
resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==}

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 21H8V7h11m0-2H8c-.53043 0-1.03914.21071-1.41421.58579C6.21071 5.96086 6 6.46957 6 7v14c0 .5304.21071 1.0391.58579 1.4142C6.96086 22.7893 7.46957 23 8 23h11c.5304 0 1.0391-.2107 1.4142-.5858S21 21.5304 21 21V7c0-.53043-.2107-1.03914-.5858-1.41421C20.0391 5.21071 19.5304 5 19 5Zm-3-4H4c-.53043 0-1.03914.21071-1.41421.58579C2.21071 1.96086 2 2.46957 2 3v14h2V3h12V1Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 478 B

3
src/assets/icons/eye.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5ZM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5Zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 318 B

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.707 19.7069 18 10.4139l-4.414-4.41402-9.293 9.29302c-.12794.1281-.21882.2884-.263.464L3 20.9999l5.242-1.03c.176-.044.337-.135.465-.263ZM21 7.41388c.3749-.37506.5856-.88367.5856-1.414s-.2107-1.03895-.5856-1.414l-1.586-1.586c-.3751-.37494-.8837-.58557-1.414-.58557-.5303 0-1.0389.21063-1.414.58557L15 4.58588l4.414 4.414L21 7.41388Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 442 B

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 23c-.55 0-1.021-.196-1.413-.588C4.195 22.02 3.99934 21.5493 4 21V10c0-.55.196-1.021.588-1.413C4.98 8.195 5.45067 7.99933 6 8h3v2H6v11h12V10h-3V8h3c.55 0 1.021.196 1.413.588.392.392.5877.86267.587 1.412v11c0 .55-.196 1.021-.588 1.413-.392.392-.8627.5877-1.412.587H6Zm5-7V4.825l-1.6 1.6L8 5l4-4 4 4-1.4 1.425-1.6-1.6V16h-2Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 433 B

View File

@@ -223,7 +223,7 @@ export function CombinedActivity(props: { limit?: number }) {
const txs = await state.node_manager?.list_onchain() as OnChainTx[];
const invoices = await state.node_manager?.list_invoices() as MutinyInvoice[];
let activity: ActivityItem[] = [];
const activity: ActivityItem[] = [];
txs.forEach((tx) => {
activity.push({ type: "onchain", item: tx, time: tx.confirmation_time?.Confirmed?.time || Date.now() })

View File

@@ -0,0 +1,91 @@
import { Match, ParentComponent, Show, Switch, createMemo } from "solid-js";
import { Card, VStack } from "~/components/layout";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd } from "~/utils/conversions";
import { AmountEditable } from "./AmountEditable";
const noop = () => {
// do nothing
}
const KeyValue: ParentComponent<{ key: string, gray?: boolean }> = (props) => {
return (
<div class="flex justify-between items-center" classList={{ "text-neutral-400": props.gray }}>
<div class="font-semibold uppercase">{props.key}</div>
<div class="font-light">{props.children}</div>
</div>
)
}
export const InlineAmount: ParentComponent<{ amount: string, sign?: string, fiat?: boolean }> = (props) => {
const prettyPrint = createMemo(() => {
const parsed = Number(props.amount);
if (isNaN(parsed)) {
return props.amount;
} else {
return parsed.toLocaleString();
}
})
return (<div class="inline-block text-lg">{props.sign ? `${props.sign} ` : ""}{props.fiat ? "$" : ""}{prettyPrint()} <span class="text-sm">{props.fiat ? "USD" : "SATS"}</span></div>)
}
function USDShower(props: { amountSats: string, fee?: string }) {
const [state, _] = useMegaStore()
const amountInUsd = () => satsToUsd(state.price, add(props.amountSats, props.fee), true)
return (
<Show when={!(props.amountSats === "0")}>
<KeyValue gray key="">
<div class="self-end">&#8776; {amountInUsd()}&nbsp;<span class="text-sm">USD</span></div>
</KeyValue>
</Show>
)
}
function add(a: string, b?: string) {
return Number(a || 0) + Number(b || 0)
}
export function AmountCard(props: { amountSats: string, fee?: string, initialOpen?: boolean, isAmountEditable?: boolean, setAmountSats?: (amount: bigint) => void }) {
return (
<Card>
<VStack>
<Switch>
<Match when={props.fee}>
<div class="flex flex-col gap-1">
<KeyValue key="Amount">
<Show when={props.isAmountEditable} fallback={<InlineAmount amount={props.amountSats} />
}>
<AmountEditable initialOpen={props.initialOpen ?? false} initialAmountSats={props.amountSats.toString()} setAmountSats={props.setAmountSats ? props.setAmountSats : noop} />
</Show>
</KeyValue>
<KeyValue gray key="+ Fee">
<InlineAmount amount={props.fee || "0"} />
</KeyValue>
</div>
<hr class="border-white/20" />
<div class="flex flex-col gap-1">
<KeyValue key="Total">
<InlineAmount amount={add(props.amountSats, props.fee).toString()} />
</KeyValue>
<USDShower amountSats={props.amountSats} fee={props.fee} />
</div>
</Match>
<Match when={!props.fee}>
<div class="flex flex-col gap-1">
<KeyValue key="Amount">
<Show when={props.isAmountEditable} fallback={<InlineAmount amount={props.amountSats} />
}>
<AmountEditable initialOpen={props.initialOpen ?? false} initialAmountSats={props.amountSats.toString()} setAmountSats={props.setAmountSats ? props.setAmountSats : noop} />
</Show>
</KeyValue>
<USDShower amountSats={props.amountSats} />
</div>
</Match>
</Switch>
</VStack>
</Card>
)
}

View File

@@ -1,10 +1,11 @@
import { For, Show, createMemo, createSignal } from 'solid-js';
import { For, ParentComponent, Show, createMemo, createSignal } from 'solid-js';
import { Button } from '~/components/layout';
import { useMegaStore } from '~/state/megaStore';
import { satsToUsd } from '~/utils/conversions';
import { Amount } from './Amount';
import { Dialog } from '@kobalte/core';
import close from "~/assets/icons/close.svg";
import pencil from "~/assets/icons/pencil.svg";
import { InlineAmount } from './AmountCard';
const CHARACTERS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "DEL"];
@@ -25,8 +26,8 @@ function SingleDigitButton(props: { character: string, onClick: (c: string) => v
);
}
export function AmountEditable(props: { initialAmountSats: string, setAmountSats: (s: bigint) => void }) {
const [isOpen, setIsOpen] = createSignal(false);
export const AmountEditable: ParentComponent<{ initialAmountSats: string, initialOpen: boolean, setAmountSats: (s: bigint) => void }> = (props) => {
const [isOpen, setIsOpen] = createSignal(props.initialOpen);
const [displayAmount, setDisplayAmount] = createSignal(props.initialAmountSats || "0");
@@ -135,8 +136,13 @@ export function AmountEditable(props: { initialAmountSats: string, setAmountSats
return (
<Dialog.Root isOpen={isOpen()}>
<button onClick={() => setIsOpen(true)} class="p-4 rounded-xl border-2 border-m-blue">
<Amount amountSats={Number(displayAmount())} showFiat />
<button onClick={() => setIsOpen(true)} class="px-4 py-2 rounded-xl border-2 border-m-blue flex gap-2 items-center">
{/* <Amount amountSats={Number(displayAmount())} showFiat /><span>&#x270F;&#xFE0F;</span> */}
<Show when={displayAmount() !== "0"} fallback={<div class="inline-block font-semibold">Set amount</div>}>
<InlineAmount amount={displayAmount()} />
</Show>
<img src={pencil} alt="Edit" />
{/* {props.children} */}
</button>
<Dialog.Portal>
{/* <Dialog.Overlay class={OVERLAY} /> */}

View File

@@ -1,5 +1,5 @@
import { createResource, Show, Suspense } from "solid-js";
import { ButtonLink, FancyCard } from "~/components/layout";
import { Show, Suspense } from "solid-js";
import { ButtonLink, FancyCard, Indicator } from "~/components/layout";
import { useMegaStore } from "~/state/megaStore";
import { Amount } from "./Amount";
@@ -10,12 +10,6 @@ function prettyPrintAmount(n?: number | bigint): string {
return n.toLocaleString()
}
function SyncingIndicator() {
return (
<div class="box-border animate-pulse px-2 py-1 -my-1 bg-white/70 rounded text-xs uppercase text-black">Syncing</div>
)
}
export default function BalanceBox() {
const [state, actions] = useMegaStore();
@@ -25,7 +19,7 @@ export default function BalanceBox() {
<Amount amountSats={state.balance?.lightning || 0} showFiat />
</FancyCard>
<FancyCard title="On-Chain" tag={state.is_syncing && <SyncingIndicator />}>
<FancyCard title="On-Chain" tag={state.is_syncing && <Indicator>Syncing</Indicator>}>
<div onClick={actions.sync}>
<Amount amountSats={state.balance?.confirmed} showFiat />
</div>

View File

@@ -1,5 +1,5 @@
import { Match, Switch, createSignal, createUniqueId } from 'solid-js';
import { SmallHeader } from '~/components/layout';
import { SmallHeader, TinyButton } from '~/components/layout';
import { Dialog } from '@kobalte/core';
import close from "~/assets/icons/close.svg";
import { SubmitHandler } from '@modular-forms/solid';
@@ -39,7 +39,7 @@ export function ContactEditor(props: { createContact: (contact: ContactItem) =>
</button>
</Match>
<Match when={!props.list}>
<button onClick={() => setIsOpen(true)} class="border border-l-white/50 border-r-white/50 border-t-white/75 border-b-white/25 bg-black px-1 py-[0.5] rounded cursor-pointer hover:outline-white hover:outline-1">+ Add Contact</button>
<TinyButton onClick={() => setIsOpen(true)}>+ Add Contact</TinyButton>
</Match>
</Switch>
<Dialog.Portal>

View File

@@ -5,6 +5,7 @@ import close from "~/assets/icons/close.svg";
import { SubmitHandler } from '@modular-forms/solid';
import { ContactItem } from '~/state/contacts';
import { ContactForm } from './ContactForm';
import { showToast } from './Toaster';
export function ContactViewer(props: { contact: ContactItem, gradient: string, saveContact: (contact: ContactItem) => void }) {
const [isOpen, setIsOpen] = createSignal(false);
@@ -58,7 +59,7 @@ export function ContactViewer(props: { contact: ContactItem, gradient: string, s
<div class="flex w-full gap-2">
<Button layout="flex" intent="green" onClick={() => setIsEditing(true)}>Edit</Button>
<Button intent="blue" onClick={() => { }}>Pay</Button>
<Button intent="blue" onClick={() => { showToast({ title: "Unimplemented", description: "We don't do that yet" }) }}>Pay</Button>
</div>
</div>
</Match>

View File

@@ -12,7 +12,7 @@ export function ImportExport() {
const [state, _] = useMegaStore()
async function handleSave() {
let json = await state.node_manager?.export_json()
const json = await state.node_manager?.export_json()
downloadTextFile(json || "", "mutiny-state.json")
}

View File

@@ -5,7 +5,7 @@ import { useCopy } from "~/utils/useCopy";
const OVERLAY = "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm"
const DIALOG_POSITIONER = "fixed inset-0 z-50 flex items-center justify-center"
const DIALOG_CONTENT = "max-w-[600px] max-h-full p-4 bg-gray/50 backdrop-blur-md shadow-xl rounded-xl border border-white/10"
const DIALOG_CONTENT = "max-w-[600px] max-h-full mx-4 p-4 bg-neutral-900/50 backdrop-blur-md shadow-xl rounded-xl border border-white/10"
export function JsonModal(props: { title: string, open: boolean, data?: unknown, setOpen: (open: boolean) => void, children?: JSX.Element }) {
const json = createMemo(() => JSON.stringify(props.data, null, 2));

View File

@@ -1,6 +1,7 @@
import { Show, createSignal, onMount } from "solid-js";
import { Button, ButtonLink, SmallHeader, VStack } from "./layout";
import { useMegaStore } from "~/state/megaStore";
import { showToast } from "./Toaster";
export function OnboardWarning() {
const [state, actions] = useMegaStore();
@@ -25,7 +26,7 @@ export function OnboardWarning() {
Do you want to restore an existing Mutiny Wallet?
</p>
<div class="w-full flex gap-2">
<Button intent="green" onClick={() => { }}>Restore</Button>
<Button intent="green" onClick={() => { showToast({ title: "Unimplemented", description: "We don't do that yet" }) }}>Restore</Button>
<Button onClick={actions.dismissRestorePrompt}>Nope</Button>
</div>
</VStack>

View File

@@ -0,0 +1,71 @@
import { Card, VStack } from "~/components/layout";
import { useCopy } from "~/utils/useCopy";
import copyIcon from "~/assets/icons/copy.svg"
import shareIcon from "~/assets/icons/share.svg"
import eyeIcon from "~/assets/icons/eye.svg"
import { Show, createSignal } from "solid-js";
import { JsonModal } from "./JsonModal";
const STYLE = "px-4 py-2 rounded-xl border-2 border-white flex gap-2 items-center font-semibold"
function ShareButton(props: { receiveString: string }) {
async function share(receiveString: string) {
// If the browser doesn't support share we can just copy the address
if (!navigator.share) {
console.error("Share not supported")
}
const shareData: ShareData = {
title: "Mutiny Wallet",
text: receiveString,
}
try {
await navigator.share(shareData)
} catch (e) {
console.error(e)
}
}
return (
<button class={STYLE} onClick={(_) => share(props.receiveString)}><span>Share</span><img src={shareIcon} alt="share" /></button>
)
}
export function StringShower(props: { text: string }) {
const [open, setOpen] = createSignal(false);
return (
<>
<JsonModal open={open()} data={props.text} title="Details" setOpen={setOpen} />
<div class="flex gap-2">
<pre class="truncate text-neutral-400">{props.text}</pre>
<button class="w-[16rem]" onClick={() => setOpen(true)}>
<img src={eyeIcon} alt="eye" />
</button>
</div>
</>
)
}
export function ShareCard(props: { text?: string }) {
const [copy, copied] = useCopy({ copiedTimeout: 1000 });
function handleCopy() {
copy(props.text ?? "")
}
return (
<Card>
<StringShower text={props.text ?? ""} />
<VStack>
<div class="flex gap-4 justify-center">
<button class={STYLE} onClick={handleCopy}>{copied() ? "Copied" : "Copy"}<img src={copyIcon} alt="copy" /></button>
<Show when={navigator.share}>
<ShareButton receiveString={props.text ?? ""} />
</Show>
</div>
</VStack>
</Card >
)
}

View File

@@ -1,22 +1,21 @@
import { Select, createOptions } from "@thisbeyond/solid-select";
import "~/styles/solid-select.css"
import { SmallHeader } from "./layout";
import { For, createUniqueId } from "solid-js";
import { ContactEditor } from "./ContactEditor";
import { ContactItem, TagItem, TextItem, addContact } from "~/state/contacts";
import { TinyButton } from "./layout";
// take two arrays, subtract the second from the first, then return the first
function subtract<T>(a: T[], b: T[]) {
const set = new Set(b);
return a.filter(x => !set.has(x));
};
}
const createValue = (name: string): TextItem => {
return { id: createUniqueId(), name, kind: "text" };
};
export function TagEditor(props: { title: string, values: TagItem[], setValues: (values: TagItem[]) => void, selectedValues: TagItem[], setSelectedValues: (values: TagItem[]) => void }) {
console.log(props.values);
export function TagEditor(props: { values: TagItem[], setValues: (values: TagItem[]) => void, selectedValues: TagItem[], setSelectedValues: (values: TagItem[]) => void, placeholder: string }) {
const onChange = (selected: TagItem[]) => {
props.setSelectedValues(selected);
@@ -42,26 +41,23 @@ export function TagEditor(props: { title: string, values: TagItem[], setValues:
return (
<div class="flex flex-col gap-2 flex-grow flex-shrink flex-1" >
<SmallHeader>{props.title}</SmallHeader>
{/* FIXME this is causing overflow scroll for now good reason */}
<Select
multiple
initialValue={props.selectedValues}
onChange={onChange}
placeholder="Where's it coming from?"
placeholder={props.placeholder}
{...selectProps}
/>
<div class="flex gap-2 flex-wrap">
<For each={subtract(props.values, props.selectedValues).slice(0, 3)}>
{(tag) => (
<div onClick={() => onChange([...props.selectedValues, tag])}
class="border border-l-white/50 border-r-white/50 border-t-white/75 border-b-white/25 px-1 py-[0.5] rounded cursor-pointer hover:outline-white hover:outline-1"
classList={{ "bg-black": tag.kind === "text", "bg-m-blue": tag.kind === "contact" && tag.color === "blue", "bg-m-green": tag.kind === "contact" && tag.color === "green", "bg-m-red": tag.kind === "contact" && tag.color === "red", "bg-[#898989]": tag.kind === "contact" && tag.color === "gray" }}
<TinyButton onClick={() => onChange([...props.selectedValues, tag])}
>
{tag.name}
</div>
</TinyButton>
)}
</For>
{/* <button class="border border-l-white/50 border-r-white/50 border-t-white/75 border-b-white/25 bg-black px-1 py-[0.5] rounded cursor-pointer hover:outline-white hover:outline-1">+ Add Contact</button> */}
<ContactEditor createContact={newContact} />
</div>
</div >

View File

@@ -1,5 +1,5 @@
import { Back } from "~/assets/svg/Back";
export function BackButton(props: { onClick: () => void, title?: string }) {
return (<button onClick={props.onClick} class="text-m-red active:text-m-red/80 text-xl font-semibold no-underline md:hidden flex items-center"><Back />{props.title ? props.title : "Home"}</button>)
return (<button onClick={() => props.onClick()} class="text-m-red active:text-m-red/80 text-xl font-semibold no-underline md:hidden flex items-center"><Back />{props.title ? props.title : "Home"}</button>)
}

View File

@@ -1,11 +1,11 @@
import { Dialog } from "@kobalte/core";
import { JSX } from "solid-js";
import { Button, LargeHeader, SmallHeader } from "~/components/layout";
import { Button, LargeHeader } from "~/components/layout";
import close from "~/assets/icons/close.svg";
const DIALOG_POSITIONER = "fixed inset-0 safe-top safe-bottom z-50"
const DIALOG_CONTENT = "h-full flex flex-col justify-between p-4 bg-gray/50 backdrop-blur-md bg-black/80"
const DIALOG_CONTENT = "h-full flex flex-col justify-between p-4 backdrop-blur-md bg-neutral-900/50"
type FullscreenModalProps = {
title: string,

View File

@@ -4,13 +4,19 @@ import { For, Show } from "solid-js";
type Choices = { value: string, label: string, caption: string }[]
// TODO: how could would it be if we could just pass the estimated fees in here?
export function StyledRadioGroup(props: { value: string, choices: Choices, onValueChange: (value: string) => void, small?: boolean, red?: boolean }) {
export function StyledRadioGroup(props: { value: string, choices: Choices, onValueChange: (value: string) => void, small?: boolean, accent?: "red" | "white" }) {
return (
// TODO: rewrite this with CVA, props are bad for tailwind
<RadioGroup.Root value={props.value} onValueChange={(e) => props.onValueChange(e)} class={`grid w-full gap-${props.small ? "2" : "4"} grid-cols-${props.choices.length.toString()}`}>
<RadioGroup.Root value={props.value} onValueChange={(e) => props.onValueChange(e)}
class={"grid w-full gap-4"}
classList={{ "grid-cols-2": props.choices.length === 2, "grid-cols-3": props.choices.length === 3, "gap-2": props.small }}
>
<For each={props.choices}>
{choice =>
<RadioGroup.Item value={choice.value} class={`ui-checked:bg-neutral-950 bg-white/10 rounded outline outline-black/50 ${props.red ? "ui-checked:outline-m-red" : "ui-checked:outline-m-blue"} ui-checked:outline-2`}>
<RadioGroup.Item value={choice.value}
class={`ui-checked:bg-neutral-950 bg-white/10 rounded outline outline-black/50 ui-checked:outline-m-blue ui-checked:outline-2`}
classList={{ "ui-checked:outline-m-red": props.accent === "red", "ui-checked:outline-white": props.accent === "white" }}
>
<div class={props.small ? "py-2 px-2" : "py-3 px-4"}>
<RadioGroup.ItemInput />
<RadioGroup.ItemControl >

View File

@@ -16,7 +16,7 @@ export const SmallHeader: ParentComponent<{ class?: string }> = (props) => {
export const Card: ParentComponent<{ title?: string, titleElement?: JSX.Element }> = (props) => {
return (
<div class='rounded-xl p-4 flex flex-col gap-2 bg-neutral-950 overflow-x-hidden w-full'>
<div class='rounded-xl p-4 flex flex-col gap-2 bg-neutral-950/50 overflow-x-hidden w-full'>
{props.title && <SmallHeader>{props.title}</SmallHeader>}
{props.titleElement && props.titleElement}
{props.children}
@@ -97,7 +97,7 @@ export const Hr = () => <Separator.Root class="my-4 border-white/20" />
export const LargeHeader: ParentComponent<{ action?: JSX.Element }> = (props) => {
return (
<header class="w-full flex justify-between items-center mt-4 mb-2">
<h1 class="text-4xl font-semibold">{props.children}</h1>
<h1 class="text-3xl font-semibold">{props.children}</h1>
<Show when={props.action}>
{props.action}
</Show>
@@ -121,5 +121,16 @@ export const NiceP: ParentComponent = (props) => {
return (<p class="text-2xl font-light">{props.children}</p>)
}
export const TinyButton: ParentComponent<{ onClick: () => void }> = (props) => {
return (
<button class="py-1 px-2 rounded-lg bg-white/10" onClick={() => props.onClick()}>
{props.children}
</button>
)
}
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>
)
}

View File

@@ -28,7 +28,7 @@ export default function Root() {
content="width=device-width, initial-scale=1.0 height=device-height viewport-fit=cover user-scalable=no"
/>
<Link rel="manifest" href="/manifest.webmanifest" />
<Meta name="theme-color" content="#000000" />
<Meta name="theme-color" content="rgb(23,23,23)" />
<Meta name="description" content="Lightning wallet for the web" />
<Link rel="icon" href="/favicon.ico" />
<Link rel="apple-touch-icon" href="/images/icon.png" sizes="512x512" />

View File

@@ -1,8 +1,8 @@
import { For, Show, createResource } from "solid-js";
import NavBar from "~/components/NavBar";
import { Button, Card, DefaultMain, LargeHeader, NiceP, NodeManagerGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
import { Button, Card, DefaultMain, LargeHeader, NiceP, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
import { BackLink } from "~/components/layout/BackLink";
import { CombinedActivity, Activity as MutinyActivity } from "~/components/Activity";
import { CombinedActivity } from "~/components/Activity";
import { A } from "solid-start";
import settings from '~/assets/icons/settings.svg';
import { ContactItem, addContact, editContact, listContacts } from "~/state/contacts";

View File

@@ -1,10 +1,10 @@
import { Button, DefaultMain, LargeHeader, NiceP, NodeManagerGuard, SafeArea, VStack } from "~/components/layout";
import NavBar from "~/components/NavBar";
import { useNavigate } from 'solid-start';
import { BackButton } from '~/components/layout/BackButton';
import { SeedWords } from '~/components/SeedWords';
import { useMegaStore } from '~/state/megaStore';
import { Show, createSignal } from 'solid-js';
import { BackLink } from "~/components/layout/BackLink";
export default function App() {
const [store, actions] = useMegaStore();
@@ -21,7 +21,7 @@ export default function App() {
<NodeManagerGuard>
<SafeArea>
<DefaultMain>
<BackButton />
<BackLink />
<LargeHeader>Backup</LargeHeader>
<VStack>
<NiceP>Let's get these funds secured.</NiceP>

View File

@@ -1,12 +1,10 @@
import { MutinyBip21RawMaterials, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import { createEffect, createResource, createSignal, For, Match, onCleanup, onMount, Switch } from "solid-js";
import { createEffect, createMemo, createResource, createSignal, Match, onCleanup, onMount, Show, Switch } from "solid-js";
import { QRCodeSVG } from "solid-qr-code";
import { AmountEditable } from "~/components/AmountEditable";
import { Button, Card, LargeHeader, NodeManagerGuard, SafeArea, SmallHeader } from "~/components/layout";
import { Button, Card, Indicator, LargeHeader, NodeManagerGuard, SafeArea } from "~/components/layout";
import NavBar from "~/components/NavBar";
import { useMegaStore } from "~/state/megaStore";
import { objectToSearchParams } from "~/utils/objectToSearchParams";
import { useCopy } from "~/utils/useCopy";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { Amount } from "~/components/Amount";
import { FullscreenModal } from "~/components/layout/FullscreenModal";
@@ -17,6 +15,9 @@ import { showToast } from "~/components/Toaster";
import { useNavigate } from "solid-start";
import megacheck from "~/assets/icons/megacheck.png";
import { TagItem, listTags } from "~/state/contacts";
import { AmountCard } from "~/components/AmountCard";
import { ShareCard } from "~/components/ShareCard";
import { BackButton } from "~/components/layout/BackButton";
type OnChainTx = {
transaction: {
@@ -44,39 +45,9 @@ type OnChainTx = {
const createUniqueId = () => Math.random().toString(36).substr(2, 9);
const fakeContacts: TagItem[] = [
{ id: createUniqueId(), name: "Unknown", kind: "text" },
// { id: createUniqueId(), name: "Alice", kind: "contact" },
// { id: createUniqueId(), name: "Bob", kind: "contact" },
// { id: createUniqueId(), name: "Carol", kind: "contact" },
]
const RECEIVE_FLAVORS = [{ value: "unified", label: "Unified", caption: "Sender decides" }, { value: "lightning", label: "Lightning", caption: "Fast and cool" }, { value: "onchain", label: "On-chain", caption: "Just like Satoshi did it" }]
type ReceiveFlavor = "unified" | "lightning" | "onchain"
function ShareButton(props: { receiveString: string }) {
async function share(receiveString: string) {
// If the browser doesn't support share we can just copy the address
if (!navigator.share) {
console.error("Share not supported")
}
const shareData: ShareData = {
title: "Mutiny Wallet",
text: receiveString,
}
try {
await navigator.share(shareData)
} catch (e) {
console.error(e)
}
}
return (
<Button onClick={(_) => share(props.receiveString)}>Share</Button>
)
}
type ReceiveState = "edit" | "show" | "paid"
type PaidState = "lightning_paid" | "onchain_paid";
@@ -88,20 +59,12 @@ export default function Receive() {
const [receiveState, setReceiveState] = createSignal<ReceiveState>("edit")
const [bip21Raw, setBip21Raw] = createSignal<MutinyBip21RawMaterials>();
const [unified, setUnified] = createSignal("")
const [shouldShowAmountEditor, setShouldShowAmountEditor] = createSignal(true)
// Tagging stuff
const [selectedValues, setSelectedValues] = createSignal<TagItem[]>([]);
// const [tagItems] = createResource(listTags);
const [values, setValues] = createSignal<TagItem[]>([{ id: createUniqueId(), name: "Unknown", kind: "text" }]);
onMount(() => {
listTags().then((tags) => {
setValues(prev => [...prev, ...tags || []])
});
})
// The data we get after a payment
const [paymentTx, setPaymentTx] = createSignal<OnChainTx>();
const [paymentInvoice, setPaymentInvoice] = createSignal<MutinyInvoice>();
@@ -109,6 +72,25 @@ export default function Receive() {
// The flavor of the receive
const [flavor, setFlavor] = createSignal<ReceiveFlavor>("unified");
const receiveString = createMemo(() => {
if (unified() && receiveState() === "show") {
if (flavor() === "unified") {
return unified();
} else if (flavor() === "lightning") {
return bip21Raw()?.invoice ?? "";
} else if (flavor() === "onchain") {
return bip21Raw()?.address ?? "";
}
}
})
onMount(() => {
listTags().then((tags) => {
setValues(prev => [...prev, ...tags || []])
});
})
function clearAll() {
setAmount("")
setReceiveState("edit")
@@ -119,33 +101,6 @@ export default function Receive() {
setSelectedValues([])
}
let amountInput!: HTMLInputElement;
let labelInput!: HTMLInputElement;
function editAmount(e: Event) {
e.preventDefault();
setReceiveState("edit")
amountInput.focus();
}
function editLabel(e: Event) {
e.preventDefault();
setReceiveState("edit")
labelInput.focus();
}
const [copy, copied] = useCopy({ copiedTimeout: 1000 });
function handleCopy() {
if (flavor() === "unified") {
copy(unified() ?? "")
} else if (flavor() === "lightning") {
copy(bip21Raw()?.invoice ?? "")
} else if (flavor() === "onchain") {
copy(bip21Raw()?.address ?? "")
}
}
async function getUnifiedQr(amount: string) {
const bigAmount = BigInt(amount);
try {
@@ -174,6 +129,7 @@ export default function Receive() {
setUnified(unifiedQr || "")
setReceiveState("show")
setShouldShowAmountEditor(false)
}
async function checkIfPaid(bip21?: MutinyBip21RawMaterials): Promise<PaidState | undefined> {
@@ -214,63 +170,31 @@ export default function Receive() {
return (
<NodeManagerGuard>
<SafeArea>
<main class="max-w-[600px] flex flex-col gap-4 mx-auto p-4">
<BackLink />
<LargeHeader>Receive Bitcoin</LargeHeader>
<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 />}>
<BackButton onClick={() => setReceiveState("edit")} title="Edit" />
</Show>
<LargeHeader action={receiveState() === "show" && <Indicator>Checking</Indicator>}>Receive Bitcoin</LargeHeader>
<Switch>
<Match when={!unified() || receiveState() === "edit"}>
<dl>
<dd>
<AmountEditable initialAmountSats={amount() || "0"} setAmountSats={setAmount} />
</dd>
<dd>
<TagEditor title="Tag the origin" values={values()} setValues={setValues} selectedValues={selectedValues()} setSelectedValues={setSelectedValues} />
</dd>
</dl>
<Button class="w-full" disabled={!amount() || !selectedValues().length} intent="green" onClick={onSubmit}>Create Invoice</Button>
<div class="flex flex-col flex-1 gap-8">
<AmountCard initialOpen={shouldShowAmountEditor()} amountSats={amount() || "0"} setAmountSats={setAmount} isAmountEditable />
<Card title="Tag the origin">
<TagEditor values={values()} setValues={setValues} selectedValues={selectedValues()} setSelectedValues={setSelectedValues} placeholder="Where's it coming from?" />
</Card>
<div class="flex-1" />
<Button class="w-full flex-grow-0 mb-4" disabled={!amount() || !selectedValues().length} intent="green" onClick={onSubmit}>Create Invoice</Button>
</div>
</Match>
<Match when={unified() && receiveState() === "show"}>
<StyledRadioGroup small value={flavor()} onValueChange={setFlavor} choices={RECEIVE_FLAVORS} />
<StyledRadioGroup small value={flavor()} onValueChange={setFlavor} choices={RECEIVE_FLAVORS} accent="white" />
<div class="w-full bg-white rounded-xl">
<Switch>
<Match when={flavor() === "unified"}>
<QRCodeSVG value={unified() ?? ""} class="w-full h-full p-8 max-h-[400px]" />
</Match>
<Match when={flavor() === "lightning"}>
<QRCodeSVG value={bip21Raw()?.invoice ?? ""} class="w-full h-full p-8 max-h-[400px]" />
</Match>
<Match when={flavor() === "onchain"}>
<QRCodeSVG value={bip21Raw()?.address ?? ""} class="w-full h-full p-8 max-h-[400px]" />
</Match>
</Switch>
<QRCodeSVG value={receiveString() ?? ""} class="w-full h-full p-8 max-h-[400px]" />
</div>
<div class="flex gap-2 w-full">
<Button onClick={handleCopy}>{copied() ? "Copied" : "Copy"}</Button>
<ShareButton receiveString={unified() ?? ""} />
</div>
<Card>
<SmallHeader>Amount</SmallHeader>
<div class="flex justify-between">
<Amount amountSats={parseInt(amount()) || 0} showFiat={true} />
<button onClick={editAmount}>&#x270F;&#xFE0F;</button>
</div>
<SmallHeader>Tags</SmallHeader>
<div class="flex justify-between">
<div class="flex flex-wrap">
<For each={selectedValues()}>
{(tag) => (
<div class=" bg-white/20 rounded px-1">
{tag.name}
</div>)}
</For>
</div>
{/* <pre>{JSON.stringify(selectedValues(), null, 2)}</pre> */}
<button onClick={editLabel}>&#x270F;&#xFE0F;</button>
</div>
</Card>
<Card title="Bip21">
<code class="break-all">{unified()}</code>
</Card>
<p class="text-neutral-400 text-center">Show or share this code with the sender</p>
<ShareCard text={receiveString() ?? ""} />
</Match>
<Match when={receiveState() === "paid" && paidState() === "lightning_paid"}>
<FullscreenModal

View File

@@ -1,5 +1,5 @@
import Reader from "~/components/Reader";
import { createEffect, createSignal, onMount, Show } from "solid-js";
import { createEffect, createSignal, onMount } from "solid-js";
import { useNavigate } from "solid-start";
import { Button } from "~/components/layout";
import init, { PaymentParams } from "@mutinywallet/waila-wasm";
@@ -76,12 +76,8 @@ export default function Scanner() {
});
}
let waila;
onMount(() => {
init().then((w) => {
waila = w;
});
onMount(async () => {
await init()
})
// When we have a nice result we can head over to the send screen

View File

@@ -1,12 +1,11 @@
import { Match, Show, Switch, createEffect, createMemo, createResource, createSignal, onCleanup, onMount } from "solid-js";
import { Match, Show, Switch, createEffect, createMemo, createSignal, onMount } from "solid-js";
import { Amount } from "~/components/Amount";
import NavBar from "~/components/NavBar";
import { Button, ButtonLink, DefaultMain, HStack, LargeHeader, NodeManagerGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
import { Button, ButtonLink, Card, DefaultMain, HStack, LargeHeader, NodeManagerGuard, SafeArea, SmallHeader, VStack } from "~/components/layout";
import { Paste } from "~/assets/svg/Paste";
import { Scan } from "~/assets/svg/Scan";
import { useMegaStore } from "~/state/megaStore";
import { MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import { AmountEditable } from "~/components/AmountEditable";
import { StyledRadioGroup } from "~/components/layout/Radio";
import { ParsedParams, toParsedParams } from "./Scanner";
import { showToast } from "~/components/Toaster";
@@ -17,17 +16,104 @@ import megaex from "~/assets/icons/megaex.png";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { useNavigate } from "solid-start";
import { BackLink } from "~/components/layout/BackLink";
import { TagEditor } from "~/components/TagEditor";
import { TagItem, createUniqueId, listTags } from "~/state/contacts";
import { StringShower } from "~/components/ShareCard";
import { AmountCard } from "~/components/AmountCard";
type SendSource = "lightning" | "onchain";
const PAYMENT_METHODS = [{ value: "lightning", label: "Lightning", caption: "Fast and cool" }, { value: "onchain", label: "On-chain", caption: "Just like Satoshi did it" }]
// const TEST_DEST = "bitcoin:tb1pdh43en28jmhnsrhxkusja46aufdlae5qnfrhucw5jvefw9flce3sdxfcwe?amount=0.00001&label=heyo&lightning=lntbs10u1pjrwrdedq8dpjhjmcnp4qd60w268ve0jencwzhz048ruprkxefhj0va2uspgj4q42azdg89uupp5gngy2pqte5q5uvnwcxwl2t8fsdlla5s6xl8aar4xcsvxeus2w2pqsp5n5jp3pz3vpu92p3uswttxmw79a5lc566herwh3f2amwz2sp6f9tq9qyysgqcqpcxqrpwugv5m534ww5ukcf6sdw2m75f2ntjfh3gzeqay649256yvtecgnhjyugf74zakaf56sdh66ec9fqep2kvu6xv09gcwkv36rrkm38ylqsgpw3yfjl"
// const TEST_DEST_ADDRESS = "tb1pdh43en28jmhnsrhxkusja46aufdlae5qnfrhucw5jvefw9flce3sdxfcwe"
// TODO: better success / fail type
type SentDetails = { amount?: bigint, destination?: string, txid?: string, failure_reason?: string }
function MethodChooser(props: { source: SendSource, setSource: (source: string) => void }) {
const [store, _actions] = useMegaStore();
const methods = createMemo(() => {
return [
{ value: "lightning", label: "Lightning", caption: store.balance?.lightning ? `${store.balance?.lightning.toLocaleString()} SATS` : "No balance" },
{ value: "onchain", label: "On-chain", caption: store.balance?.confirmed ? `${store.balance?.confirmed.toLocaleString()} SATS` : "No balance" }
]
})
return (
<StyledRadioGroup accent="white" value={props.source} onValueChange={props.setSource} choices={methods()} />
)
}
function DestinationInput(props: {
fieldDestination: string,
setFieldDestination: (destination: string) => void,
handleDecode: () => void,
handlePaste: () => void,
}) {
return (
<VStack>
<SmallHeader>Destination</SmallHeader>
<textarea value={props.fieldDestination} onInput={(e) => props.setFieldDestination(e.currentTarget.value)} placeholder="bitcoin:..." class="p-2 rounded-lg bg-white/10 placeholder-neutral-400" />
<Button disabled={!props.fieldDestination} intent="blue" onClick={props.handleDecode}>Decode</Button>
<HStack>
<Button onClick={props.handlePaste}>
<div class="flex flex-col gap-2 items-center">
<Paste />
<span>Paste</span>
</div>
</Button>
<ButtonLink href="/scanner">
<div class="flex flex-col gap-2 items-center">
<Scan />
<span>Scan QR</span>
</div>
</ButtonLink>
</HStack>
</VStack>
)
}
function DestinationShower(props: {
source: SendSource,
description?: string,
address?: string,
invoice?: MutinyInvoice,
nodePubkey?: string,
clearAll: () => void,
}) {
return (
<Switch>
<Match when={props.address && props.source === "onchain"}>
<StringShower text={props.address || ""} />
</Match>
<Match when={props.invoice && props.source === "lightning"}>
<StringShower text={props.invoice?.bolt11 || ""} />
</Match>
<Match when={props.nodePubkey && props.source === "lightning"}>
<StringShower text={props.nodePubkey || ""} />
</Match>
</Switch>
)
}
function SendTags() {
// Tagging stuff
const [selectedValues, setSelectedValues] = createSignal<TagItem[]>([]);
const [values, setValues] = createSignal<TagItem[]>([{ id: createUniqueId(), name: "Unknown", kind: "text" }]);
onMount(() => {
listTags().then((tags) => {
setValues(prev => [...prev, ...tags || []])
});
})
return (
<TagEditor values={values()} setValues={setValues} selectedValues={selectedValues()} setSelectedValues={setSelectedValues} placeholder="Where's it going to?" />
)
}
export default function Send() {
const [state, actions] = useMegaStore();
const navigate = useNavigate()
@@ -35,7 +121,6 @@ export default function Send() {
// These can only be set by the user
const [fieldDestination, setFieldDestination] = createSignal("");
const [destination, setDestination] = createSignal<ParsedParams>();
const [privateLabel, setPrivateLabel] = createSignal("");
// These can be derived from the "destination" signal or set by the user
const [amountSats, setAmountSats] = createSignal(0n);
@@ -53,7 +138,6 @@ export default function Send() {
function clearAll() {
setDestination(undefined);
setPrivateLabel("");
setAmountSats(0n);
setSource("lightning");
setInvoice(undefined);
@@ -144,7 +228,7 @@ export default function Send() {
try {
setSending(true);
const bolt11 = invoice()?.bolt11;
let sentDetails: Partial<SentDetails> = {};
const sentDetails: Partial<SentDetails> = {};
if (source() === "lightning" && invoice() && bolt11) {
const nodes = await state.node_manager?.list_nodes();
const firstNode = nodes[0] as string || ""
@@ -226,94 +310,28 @@ export default function Send() {
</Switch>
</div>
</FullscreenModal>
<dl>
<dt>
<SmallHeader>Destination</SmallHeader>
</dt>
<dd>
<Switch>
<Match when={address() || invoice() || nodePubkey()}>
<div class="flex gap-2 items-center">
<Show when={address() && source() === "onchain"}>
<code class="truncate text-sm break-all">{"Address: "} {address()}
<Show when={description()}>
<br />
{"Description:"} {description()}
</Show>
</code>
</Show>
<Show when={invoice() && source() === "lightning"}>
<code class="truncate text-sm break-all">{"Invoice: "} {invoice()?.bolt11}
<Show when={description()}>
<br />
{"Description:"} {description()}
</Show>
</code>
</Show>
<Show when={nodePubkey() && source() === "lightning"}>
<code class="truncate text-sm break-all">{"Node Pubkey: "} {nodePubkey()}
</code>
</Show>
<Button class="flex-0" intent="glowy" layout="xs" onClick={clearAll}>Clear</Button>
</div>
<div class="my-8 flex flex-col sm:flex-row sm:justify-center gap-4 w-full items-center justify-center">
{/* if the amount came with the invoice we can't allow setting it */}
<Show when={!(invoice()?.amount_sats)} fallback={<Amount amountSats={amountSats() || 0} showFiat />}>
<AmountEditable initialAmountSats={amountSats().toString() || "0"} setAmountSats={setAmountSats} />
</Show>
<div class="bg-white/10 px-4 py-2 rounded-xl">
<div class="flex gap-2 items-center">
<h2 class="text-neutral-400 font-semibold uppercase">+ Fee</h2>
<h3 class="text-xl font-light text-neutral-300">
{fakeFee().toLocaleString()}&nbsp;<span class='text-lg'>SATS</span>
</h3>
</div>
<div class="flex gap-2 items-center">
<h2 class="font-semibold uppercase text-white">Total</h2>
<h3 class="text-xl font-light text-white">
{(amountSats().valueOf() + fakeFee().valueOf()).toLocaleString()}&nbsp;<span class='text-lg'>SATS</span>
</h3>
</div>
</div>
</div>
</Match>
<Match when={true}>
<VStack biggap>
<Switch>
<Match when={address() || invoice() || nodePubkey()}>
<Show when={address() && invoice()}>
<MethodChooser source={source()} setSource={setSource} />
</Show>
<Card>
<VStack>
<textarea value={fieldDestination()} onInput={(e) => setFieldDestination(e.currentTarget.value)} placeholder="bitcoin:..." class="p-2 rounded-lg bg-white/10 placeholder-neutral-400" />
<Button disabled={!fieldDestination()} intent="blue" onClick={handleDecode}>Decode</Button>
<HStack>
<Button onClick={handlePaste}>
<div class="flex flex-col gap-2 items-center">
<Paste />
<span>Paste</span>
</div>
</Button>
<ButtonLink href="/scanner">
<div class="flex flex-col gap-2 items-center">
<Scan />
<span>Scan QR</span>
</div>
</ButtonLink>
</HStack>
<DestinationShower source={source()} description={description()} invoice={invoice()} address={address()} nodePubkey={nodePubkey()} clearAll={clearAll} />
<SendTags />
</VStack>
</Match>
</Switch>
</dd>
<Show when={address() && invoice()}>
<dt>
<SmallHeader>
Payment Method
</SmallHeader>
</dt>
<dd>
<StyledRadioGroup value={source()} onValueChange={setSource} choices={PAYMENT_METHODS} />
</dd>
</Card>
<AmountCard amountSats={amountSats().toString()} setAmountSats={setAmountSats} fee={fakeFee().toString()} isAmountEditable={!(invoice()?.amount_sats)} />
</Match>
<Match when={true}>
<DestinationInput fieldDestination={fieldDestination()} setFieldDestination={setFieldDestination} handleDecode={handleDecode} handlePaste={handlePaste} />
</Match>
</Switch>
<Show when={destination()}>
<Button disabled={sendButtonDisabled()} intent="blue" onClick={handleSend} loading={sending()}>{sending() ? "Sending..." : "Confirm Send"}</Button>
</Show>
</dl>
<Show when={destination()}>
<Button disabled={sendButtonDisabled()} intent="blue" onClick={handleSend} loading={sending()}>{sending() ? "Sending..." : "Confirm Send"}</Button>
</Show>
</VStack>
</DefaultMain>
<NavBar activeTab="send" />
</SafeArea >

23
src/routes/Storybook.tsx Normal file
View File

@@ -0,0 +1,23 @@
import { AmountCard } from "~/components/AmountCard";
import NavBar from "~/components/NavBar";
import { ShareCard } from "~/components/ShareCard";
import { DefaultMain, LargeHeader, SafeArea, VStack } from "~/components/layout";
const SAMPLE = "bitcoin:tb1prqm8xtlgme0vmw5s30lgf0a4f5g4mkgsqundwmpu6thrg8zr6uvq2qrhzq?amount=0.001&lightning=lntbs1m1pj9n9xjsp5xgdrmvprtm67p7nq4neparalexlhlmtxx87zx6xeqthsplu842zspp546d6zd2seyaxpapaxx62m88yz3xueqtjmn9v6wj8y56np8weqsxqdqqnp4qdn2hj8tfknpuvdg6tz9yrf3e27ltrx9y58c24jh89lnm43yjwfc5xqrpwjcqpj9qrsgq5sdgh0m3ur5mu5hrmmag4mx9yvy86f83pd0x9ww80kgck6tac3thuzkj0mrtltaxwnlfea95h2re7tj4qsnwzxlvrdmyq2h9mgapnycpppz6k6"
export default function Admin() {
return (
<SafeArea>
<DefaultMain>
<LargeHeader>Storybook</LargeHeader>
<VStack>
<AmountCard amountSats={"100000"} fee={"69"} />
<AmountCard amountSats={"100000"} />
<AmountCard amountSats={"100000"} isAmountEditable />
<AmountCard amountSats={"0"} isAmountEditable />
<ShareCard text={SAMPLE} />
</VStack>
</DefaultMain>
<NavBar activeTab="none" />
</SafeArea>
)
}

View File

@@ -2,8 +2,8 @@
export function downloadTextFile(content: string, fileName: string) {
const contentType = "application/json";
var a = document.createElement("a");
var file = new Blob([content], { type: contentType });
const a = document.createElement("a");
const file = new Blob([content], { type: contentType });
a.href = URL.createObjectURL(file);
a.download = fileName;
a.click();

View File

@@ -14,9 +14,7 @@ async function generateGradientFromHashedString(str: string) {
}
export async function gradientsPerContact(contacts: ContactItem[]) {
//
// let gradients: { [key: string]: string } = {};
let gradients = new Map();
const gradients = new Map();
for (const contact of contacts) {
const gradient = await generateGradientFromHashedString(contact.name);
gradients.set(contact.id, gradient);