From 9958758963e4dccb9e5fc0d5a9f55666c43e83f8 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Tue, 3 Oct 2023 17:57:30 +0800 Subject: [PATCH 01/28] chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --- .env.example | 4 + package-lock.json | 333 ++++----- package.json | 6 +- src/app/App.tsx | 15 + src/app/components/bottomModal/index.tsx | 12 +- .../confirmBtcTransactionComponent/index.tsx | 32 +- .../confirmStxTransactionComponent/index.tsx | 40 +- src/app/components/sendForm/index.tsx | 4 +- src/app/hooks/queries/useFeeMultipliers.ts | 6 +- src/app/hooks/useWalletReducer.ts | 13 +- src/app/routes/index.tsx | 5 + .../screens/authenticationRequest/index.tsx | 6 +- .../screens/confirmBrc20Transaction/index.tsx | 33 +- src/app/screens/createWalletSuccess/index.tsx | 5 +- src/app/screens/home/index.tsx | 99 ++- .../screens/ledger/addStxAddress/index.tsx | 228 ++++--- .../confirmLedgerTransaction/index.styled.ts | 105 +++ .../ledger/confirmLedgerTransaction/index.tsx | 245 +++---- .../importLedgerAccount/index.styled.ts | 294 -------- .../ledger/importLedgerAccount/index.tsx | 633 +++--------------- .../importLedgerAccount/stepControls.tsx | 166 +++++ .../importLedgerAccount/steps/index.styled.ts | 286 ++++++++ .../importLedgerAccount/steps/index.tsx | 444 ++++++++++++ .../ledger/importLedgerAccount/types.ts | 18 + .../index.styled.ts | 114 ++++ .../verifyLedgerAccountAddress/index.tsx | 474 ++++++------- src/app/screens/legalLinks/index.tsx | 98 ++- src/app/screens/onboarding/index.tsx | 12 +- src/app/screens/settings/index.tsx | 10 + .../settings/privacyPreferences/index.tsx | 99 +++ src/app/screens/signPsbtRequest/index.tsx | 110 +-- src/app/screens/signatureRequest/index.tsx | 14 +- .../stores/wallet/actions/actionCreators.ts | 9 + src/app/stores/wallet/actions/types.ts | 16 +- src/app/stores/wallet/reducer.ts | 7 + src/app/utils/constants.ts | 12 + src/app/utils/ledger.ts | 8 +- src/app/utils/mixpanel.ts | 53 ++ src/assets/img/dashboard-icon.svg | 58 ++ src/locales/en.json | 30 +- 40 files changed, 2491 insertions(+), 1665 deletions(-) create mode 100644 src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts create mode 100644 src/app/screens/ledger/importLedgerAccount/stepControls.tsx create mode 100644 src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts create mode 100644 src/app/screens/ledger/importLedgerAccount/steps/index.tsx create mode 100644 src/app/screens/ledger/importLedgerAccount/types.ts create mode 100644 src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts create mode 100644 src/app/screens/settings/privacyPreferences/index.tsx create mode 100644 src/app/utils/mixpanel.ts create mode 100644 src/assets/img/dashboard-icon.svg diff --git a/.env.example b/.env.example index 0bb2ec289..5d9d73148 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,6 @@ +# Providers TRANSAC_API_KEY= MOON_PAY_API_KEY= + +# Analytics +MIX_PANEL_TOKEN= diff --git a/package-lock.json b/package-lock.json index c21dfb377..d815080fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "xverse-web-extension", - "version": "0.18.2", + "version": "0.19.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xverse-web-extension", - "version": "0.18.2", + "version": "0.19.0", "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.7.3-4f2dd98", + "@secretkeylabs/xverse-core": "1.8.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -33,7 +33,9 @@ "crypto-browserify": "^3.12.0", "date-fns": "^2.29.3", "i18next": "^21.9.1", + "js-sha256": "^0.10.1", "jsontokens": "^4.0.1", + "mixpanel-browser": "^2.47.0", "moment": "^2.29.4", "nanoid": "^4.0.0", "p-queue": "^7.3.4", @@ -718,9 +720,9 @@ "dev": true }, "node_modules/@bitcoinerlab/descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.0.2.tgz", - "integrity": "sha512-q/0NuNlIof5Hb+ll/diU6Ib7GJ1MLwYUDTE6s/Ui4//r28LtxRPjI12/tYaMLWgTmpfuxcEnZI7+6aNFeS1EXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.1.1.tgz", + "integrity": "sha512-AMFkbBBg9T1iWtEmWB23oADk7zaOQix6wUPLXalhTyFDjhkFXDd6pCRfto/HAdaPg/ccM4GMTVgYLee9WdYFyQ==", "dependencies": { "@bitcoinerlab/miniscript": "^1.2.1", "@bitcoinerlab/secp256k1": "^1.0.5", @@ -738,9 +740,9 @@ } }, "node_modules/@bitcoinerlab/miniscript": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.2.1.tgz", - "integrity": "sha512-2Pkan4Vvq7afQNeveakFM/Np9D+DhlPtKITO/hTgKjPsPnLWqdOVyja1u/Qhr7Voi2bW9Tor6hLOYTw84QQKQQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.4.0.tgz", + "integrity": "sha512-BsG3dmwQmgKHnRZecDgUsPjwcpnf1wgaZbolcMTByS10k1zYzIx97W51LzG7GvokRJ+wnzTX/GhC8Y3L2X0CQA==", "dependencies": { "bip68": "^1.0.4" } @@ -1922,29 +1924,26 @@ "dev": true }, "node_modules/@noble/curves": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", - "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dependencies": { - "@noble/hashes": "1.3.0" + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@noble/hashes": { "version": "1.3.1", @@ -2151,35 +2150,32 @@ } }, "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", + "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "dependencies": { - "@noble/hashes": "1.3.1" + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -2198,13 +2194,13 @@ } }, "node_modules/@scure/btc-signer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.0.1.tgz", - "integrity": "sha512-sPGK7p+qHJSIs6zyzTjXCdt5mizEMelaYC3JPJGr1+NfVdYFfcRxGf9h4QfNVngHIHFSn39fzJhTBa5LSNpA4w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.1.0.tgz", + "integrity": "sha512-kCX7WaaTJr0VZIXDvaY0wNZfzZoZuLnPz4G0qmKXN8bnNx5M86wb1cce9XrZcfzb0jrVAbZJqNpxmE1e7Ka2hA==", "dependencies": { - "@noble/curves": "~1.0.0", - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.1", + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.3", "micro-packed": "~0.3.2" }, "funding": { @@ -2212,9 +2208,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "1.7.3-4f2dd98", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.7.3-4f2dd98/a079b169590c7aaef0f39fd34ece42fa8998f444", - "integrity": "sha512-ZvEs+l3lSRBVm0r/1+buC0ddfFT9vU3UaVp5MkVRLXsDGIGmPHjrC5f+2xUj5A6/d46ORRykpMy09XpL6H7o1Q==", + "version": "1.8.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.0/237b5304fa9e9d03c757102ed66be27b4ead25ef", + "integrity": "sha512-u9dt1wXpECorrXmvHPBWxp+t2xM3tmqoa9pHNE0V/ndbzVF+45BY+vxLjGmv5hta8CYMWTmJnfZnyE5tlZyIUw==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -2430,14 +2426,14 @@ } }, "node_modules/@stacks/auth": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.5.5.tgz", - "integrity": "sha512-4hsyAqj1UU874CmHKo8lyGj5LUuQpBTV55vgytD/WSz5XE7iocGAsH5aaDYqpuwgLjbTDvBGQ7twVWifIujvqw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", + "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", "dependencies": { "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.5.5", + "@stacks/encryption": "^6.7.0", "@stacks/network": "^6.5.5", - "@stacks/profile": "^6.5.5", + "@stacks/profile": "^6.7.0", "cross-fetch": "^3.1.5", "jsontokens": "^4.0.1" } @@ -2469,9 +2465,9 @@ } }, "node_modules/@stacks/auth/node_modules/@stacks/encryption": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.5.tgz", - "integrity": "sha512-iFUq8drrR6pwoYmkKIReyjZ61wH6eUZ07KzZoZvAQwrSeaafGVc7EwdzC0krQQUODVo5LKkNNzMWTlLuL7mHBA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -2720,13 +2716,13 @@ } }, "node_modules/@stacks/profile": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.5.5.tgz", - "integrity": "sha512-J3TjqjGg3L6ULC+RbsjQjjJd3BHZSgpuyUcUe9CaotLmDhSDFijGztpSaMmiBMmRoKRSP4j8HkXhbSthZC/JSg==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", + "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", "dependencies": { "@stacks/common": "^6.5.5", "@stacks/network": "^6.5.5", - "@stacks/transactions": "^6.5.5", + "@stacks/transactions": "^6.7.0", "jsontokens": "^4.0.1", "schema-inspector": "^2.0.2", "zone-file": "^2.0.0-beta.3" @@ -2744,9 +2740,9 @@ ] }, "node_modules/@stacks/profile/node_modules/@stacks/transactions": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.5.tgz", - "integrity": "sha512-2lITkwN+ztsp8sZ0SUVRdJz9H3xL/H+cwOYB4eTR7F96rN/QzdMQRvoIqPBYp1Euovqn8aDnIvjwni7/TeJj4A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", + "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -2762,13 +2758,13 @@ "integrity": "sha512-zrjKPGJN4p1azzmh8j0Yj+ZjQ0L9F01qJjAxOtBpapmFbGr1NUuPT1GthIg76y+dobdjSDPN39LpoJG/FbWFLw==" }, "node_modules/@stacks/storage": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.5.5.tgz", - "integrity": "sha512-knhK/niNWyeKBea8yhSxnCfciHMUhvTtyWhUCS3pHEcoNgcBBDT5x1AZsGHLIPrvXqafUciyctG3RJvY+yeY5w==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", + "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", "dependencies": { - "@stacks/auth": "^6.5.5", + "@stacks/auth": "^6.7.0", "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.5.5", + "@stacks/encryption": "^6.7.0", "@stacks/network": "^6.5.5", "base64-js": "^1.5.1", "jsontokens": "^4.0.1" @@ -2801,9 +2797,9 @@ } }, "node_modules/@stacks/storage/node_modules/@stacks/encryption": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.5.tgz", - "integrity": "sha512-iFUq8drrR6pwoYmkKIReyjZ61wH6eUZ07KzZoZvAQwrSeaafGVc7EwdzC0krQQUODVo5LKkNNzMWTlLuL7mHBA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -6239,9 +6235,9 @@ } }, "node_modules/bip174": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.0.tgz", - "integrity": "sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", "engines": { "node": ">=8.0.0" } @@ -12938,6 +12934,11 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-sha256": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", + "integrity": "sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==" + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -14006,6 +14007,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mixpanel-browser": { + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz", + "integrity": "sha512-Ldrva0fRBEIFWmEibBQO1PulfpJVF3pf28Guk09lDirDaSQqqU/xs9zQLwN2rL5VwVtsP1aD3JaCgaa98EjojQ==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -14053,9 +14059,9 @@ } }, "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" }, "node_modules/nano-time": { "version": "1.0.0", @@ -16394,9 +16400,9 @@ } }, "node_modules/sha256-uint8array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.5.tgz", - "integrity": "sha512-KjYP8M6y8VvV62lnSSZwzutuwqphVOOVQamP+GmmClZcYhbq1HSIw/M2tlKgHndiaIwe3tFG5X38YYsQfUdItw==" + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", + "integrity": "sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -19265,9 +19271,9 @@ "dev": true }, "@bitcoinerlab/descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.0.2.tgz", - "integrity": "sha512-q/0NuNlIof5Hb+ll/diU6Ib7GJ1MLwYUDTE6s/Ui4//r28LtxRPjI12/tYaMLWgTmpfuxcEnZI7+6aNFeS1EXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.1.1.tgz", + "integrity": "sha512-AMFkbBBg9T1iWtEmWB23oADk7zaOQix6wUPLXalhTyFDjhkFXDd6pCRfto/HAdaPg/ccM4GMTVgYLee9WdYFyQ==", "requires": { "@bitcoinerlab/miniscript": "^1.2.1", "@bitcoinerlab/secp256k1": "^1.0.5", @@ -19277,9 +19283,9 @@ } }, "@bitcoinerlab/miniscript": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.2.1.tgz", - "integrity": "sha512-2Pkan4Vvq7afQNeveakFM/Np9D+DhlPtKITO/hTgKjPsPnLWqdOVyja1u/Qhr7Voi2bW9Tor6hLOYTw84QQKQQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.4.0.tgz", + "integrity": "sha512-BsG3dmwQmgKHnRZecDgUsPjwcpnf1wgaZbolcMTByS10k1zYzIx97W51LzG7GvokRJ+wnzTX/GhC8Y3L2X0CQA==", "requires": { "bip68": "^1.0.4" } @@ -20207,17 +20213,17 @@ "dev": true }, "@noble/curves": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", - "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "requires": { - "@noble/hashes": "1.3.0" + "@noble/hashes": "1.3.2" }, "dependencies": { "@noble/hashes": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", - "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" } } }, @@ -20339,27 +20345,24 @@ "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==" }, "@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", + "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==" }, "@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", "requires": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" }, "dependencies": { - "@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "requires": { - "@noble/hashes": "1.3.1" - } + "@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" } } }, @@ -20373,20 +20376,20 @@ } }, "@scure/btc-signer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.0.1.tgz", - "integrity": "sha512-sPGK7p+qHJSIs6zyzTjXCdt5mizEMelaYC3JPJGr1+NfVdYFfcRxGf9h4QfNVngHIHFSn39fzJhTBa5LSNpA4w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.1.0.tgz", + "integrity": "sha512-kCX7WaaTJr0VZIXDvaY0wNZfzZoZuLnPz4G0qmKXN8bnNx5M86wb1cce9XrZcfzb0jrVAbZJqNpxmE1e7Ka2hA==", "requires": { - "@noble/curves": "~1.0.0", - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.1", + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.3", "micro-packed": "~0.3.2" } }, "@secretkeylabs/xverse-core": { - "version": "1.7.3-4f2dd98", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.7.3-4f2dd98/a079b169590c7aaef0f39fd34ece42fa8998f444", - "integrity": "sha512-ZvEs+l3lSRBVm0r/1+buC0ddfFT9vU3UaVp5MkVRLXsDGIGmPHjrC5f+2xUj5A6/d46ORRykpMy09XpL6H7o1Q==", + "version": "1.8.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.0/237b5304fa9e9d03c757102ed66be27b4ead25ef", + "integrity": "sha512-u9dt1wXpECorrXmvHPBWxp+t2xM3tmqoa9pHNE0V/ndbzVF+45BY+vxLjGmv5hta8CYMWTmJnfZnyE5tlZyIUw==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -20578,14 +20581,14 @@ } }, "@stacks/auth": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.5.5.tgz", - "integrity": "sha512-4hsyAqj1UU874CmHKo8lyGj5LUuQpBTV55vgytD/WSz5XE7iocGAsH5aaDYqpuwgLjbTDvBGQ7twVWifIujvqw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", + "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", "requires": { "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.5.5", + "@stacks/encryption": "^6.7.0", "@stacks/network": "^6.5.5", - "@stacks/profile": "^6.5.5", + "@stacks/profile": "^6.7.0", "cross-fetch": "^3.1.5", "jsontokens": "^4.0.1" }, @@ -20605,9 +20608,9 @@ } }, "@stacks/encryption": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.5.tgz", - "integrity": "sha512-iFUq8drrR6pwoYmkKIReyjZ61wH6eUZ07KzZoZvAQwrSeaafGVc7EwdzC0krQQUODVo5LKkNNzMWTlLuL7mHBA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -20851,13 +20854,13 @@ } }, "@stacks/profile": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.5.5.tgz", - "integrity": "sha512-J3TjqjGg3L6ULC+RbsjQjjJd3BHZSgpuyUcUe9CaotLmDhSDFijGztpSaMmiBMmRoKRSP4j8HkXhbSthZC/JSg==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", + "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", "requires": { "@stacks/common": "^6.5.5", "@stacks/network": "^6.5.5", - "@stacks/transactions": "^6.5.5", + "@stacks/transactions": "^6.7.0", "jsontokens": "^4.0.1", "schema-inspector": "^2.0.2", "zone-file": "^2.0.0-beta.3" @@ -20869,9 +20872,9 @@ "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==" }, "@stacks/transactions": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.5.tgz", - "integrity": "sha512-2lITkwN+ztsp8sZ0SUVRdJz9H3xL/H+cwOYB4eTR7F96rN/QzdMQRvoIqPBYp1Euovqn8aDnIvjwni7/TeJj4A==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", + "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -20889,13 +20892,13 @@ "integrity": "sha512-zrjKPGJN4p1azzmh8j0Yj+ZjQ0L9F01qJjAxOtBpapmFbGr1NUuPT1GthIg76y+dobdjSDPN39LpoJG/FbWFLw==" }, "@stacks/storage": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.5.5.tgz", - "integrity": "sha512-knhK/niNWyeKBea8yhSxnCfciHMUhvTtyWhUCS3pHEcoNgcBBDT5x1AZsGHLIPrvXqafUciyctG3RJvY+yeY5w==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", + "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", "requires": { - "@stacks/auth": "^6.5.5", + "@stacks/auth": "^6.7.0", "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.5.5", + "@stacks/encryption": "^6.7.0", "@stacks/network": "^6.5.5", "base64-js": "^1.5.1", "jsontokens": "^4.0.1" @@ -20916,9 +20919,9 @@ } }, "@stacks/encryption": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.5.tgz", - "integrity": "sha512-iFUq8drrR6pwoYmkKIReyjZ61wH6eUZ07KzZoZvAQwrSeaafGVc7EwdzC0krQQUODVo5LKkNNzMWTlLuL7mHBA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", @@ -23830,9 +23833,9 @@ } }, "bip174": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.0.tgz", - "integrity": "sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==" }, "bip32": { "version": "4.0.0", @@ -28863,6 +28866,11 @@ } } }, + "js-sha256": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", + "integrity": "sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==" + }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -29689,6 +29697,11 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "mixpanel-browser": { + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz", + "integrity": "sha512-Ldrva0fRBEIFWmEibBQO1PulfpJVF3pf28Guk09lDirDaSQqqU/xs9zQLwN2rL5VwVtsP1aD3JaCgaa98EjojQ==" + }, "mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -29727,9 +29740,9 @@ } }, "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" }, "nano-time": { "version": "1.0.0", @@ -31472,9 +31485,9 @@ } }, "sha256-uint8array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.5.tgz", - "integrity": "sha512-KjYP8M6y8VvV62lnSSZwzutuwqphVOOVQamP+GmmClZcYhbq1HSIw/M2tlKgHndiaIwe3tFG5X38YYsQfUdItw==" + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", + "integrity": "sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==" }, "shallow-clone": { "version": "3.0.1", diff --git a/package.json b/package.json index ed3af1e6c..4ca4e9845 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "xverse-web-extension", "description": "A Bitcoin wallet for Web3", - "version": "0.18.2", + "version": "0.19.0", "private": true, "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.7.3-4f2dd98", + "@secretkeylabs/xverse-core": "1.8.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -29,7 +29,9 @@ "crypto-browserify": "^3.12.0", "date-fns": "^2.29.3", "i18next": "^21.9.1", + "js-sha256": "^0.10.1", "jsontokens": "^4.0.1", + "mixpanel-browser": "^2.47.0", "moment": "^2.29.4", "nanoid": "^4.0.0", "p-queue": "^7.3.4", diff --git a/src/app/App.tsx b/src/app/App.tsx index 271e5c1c0..215a33c1b 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -9,12 +9,27 @@ import { RouterProvider } from 'react-router-dom'; import { PersistGate } from 'redux-persist/integration/react'; import { ThemeProvider } from 'styled-components'; import '../locales'; +import { useEffect } from 'react'; +import mixpanel from 'mixpanel-browser'; +import { MIX_PANEL_TOKEN } from '@utils/constants'; import Theme from '../theme'; import GlobalStyle from '../theme/global'; import SessionGuard from './components/guards/session'; import router from './routes'; function App(): JSX.Element { + useEffect(() => { + if (!MIX_PANEL_TOKEN) { + return; + } + + mixpanel.init(MIX_PANEL_TOKEN, { + debug: process.env.NODE_ENV === 'development', + ip: false, + persistence: 'localStorage', + }); + }, []); + return ( <> diff --git a/src/app/components/bottomModal/index.tsx b/src/app/components/bottomModal/index.tsx index c78d6245d..7ebb7e832 100644 --- a/src/app/components/bottomModal/index.tsx +++ b/src/app/components/bottomModal/index.tsx @@ -25,6 +25,7 @@ interface Props { children: React.ReactNode; onClose: () => void; overlayStylesOverriding?: {}; + contentStylesOverriding?: {}; } const CustomisedModal = styled(Modal)` @@ -32,11 +33,17 @@ const CustomisedModal = styled(Modal)` &::-webkit-scrollbar { display: none; } - bottom: 0; position: absolute; `; -function BottomModal({ header, children, visible, onClose, overlayStylesOverriding }: Props) { +function BottomModal({ + header, + children, + visible, + onClose, + overlayStylesOverriding, + contentStylesOverriding, +}: Props) { const theme = useTheme(); const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const customStyles = { @@ -61,6 +68,7 @@ function BottomModal({ header, children, visible, onClose, overlayStylesOverridi borderTopRightRadius: isGalleryOpen ? 12 : 20, borderBottomRightRadius: isGalleryOpen ? 12 : 0, borderBottomLeftRadius: isGalleryOpen ? 12 : 0, + ...contentStylesOverriding, }, }; diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 5c5e7170f..e4fc3a82c 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -21,14 +21,14 @@ import { signNonOrdinalBtcSendTransaction, signOrdinalSendTransaction, } from '@secretkeylabs/xverse-core/transactions/btc'; -import { StoreState } from '@stores/index'; import { useMutation } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; +import InfoContainer from '@components/infoContainer'; +import useWalletSelector from '@hooks/useWalletSelector'; import TransactionDetailComponent from '../transactionDetailComponent'; const OuterContainer = styled.div` @@ -153,13 +153,13 @@ function ConfirmBtcTransactionComponent({ const { t } = useTranslation('translation'); const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const [loading, setLoading] = useState(false); - const { btcAddress, selectedAccount, seedPhrase, network, btcFiatRate } = useSelector( - (state: StoreState) => state.walletState, - ); + const { btcAddress, selectedAccount, seedPhrase, network, btcFiatRate, feeMultipliers } = + useWalletSelector(); const [showFeeSettings, setShowFeeSettings] = useState(false); const [error, setError] = useState(''); const [signedTx, setSignedTx] = useState(signedTxHex); const [total, setTotal] = useState(new BigNumber(0)); + const [showFeeWarning, setShowFeeWarning] = useState(false); const { isLoading, data, @@ -264,6 +264,17 @@ function ConfirmBtcTransactionComponent({ } }, [signedNonOrdinalBtcSend]); + useEffect(() => { + if ( + feeMultipliers && + currentFee.isGreaterThan(new BigNumber(feeMultipliers.thresholdHighSatsFee)) + ) { + setShowFeeWarning(true); + } else if (showFeeWarning) { + setShowFeeWarning(false); + } + }, [currentFee, feeMultipliers]); + const onAdvancedSettingClick = () => { setShowFeeSettings(true); }; @@ -280,7 +291,9 @@ function ConfirmBtcTransactionComponent({ feeRate?: string; nonce?: string; }) => { - setCurrentFee(new BigNumber(modifiedFee)); + const newFee = new BigNumber(modifiedFee); + + setCurrentFee(newFee); setCurrentFeeRate(new BigNumber(feeRate)); if (ordinalTxUtxo) ordinalMutate(modifiedFee); else if (isRestoreFundFlow) { @@ -344,6 +357,13 @@ function ConfirmBtcTransactionComponent({ )} + {showFeeWarning && ( + + )} + {children} {t('CONFIRM_TRANSACTION.REVIEW_TRANSACTION')} diff --git a/src/app/components/confirmStxTransactionComponent/index.tsx b/src/app/components/confirmStxTransactionComponent/index.tsx index d5493110b..adadb12d2 100644 --- a/src/app/components/confirmStxTransactionComponent/index.tsx +++ b/src/app/components/confirmStxTransactionComponent/index.tsx @@ -25,6 +25,7 @@ import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default. import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; import { ledgerDelay } from '@common/utils/ledger'; import { isHardwareAccount } from '@utils/helper'; +import InfoContainer from '@components/infoContainer'; const Container = styled.div` display: flex; @@ -111,6 +112,10 @@ const TitleContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(16), })); +const WarningWrapper = styled.div((props) => ({ + marginBottom: props.theme.spacing(8), +})); + interface Props { initialStxTransactions: StacksTransaction[]; loading: boolean; @@ -142,7 +147,7 @@ function ConfirmStxTransationComponent({ }); const selectedNetwork = useNetworkSelector(); const [showFeeSettings, setShowFeeSettings] = useState(false); - const { selectedAccount, seedPhrase } = useWalletSelector(); + const { selectedAccount, seedPhrase, feeMultipliers } = useWalletSelector(); const [openTransactionSettingModal, setOpenTransactionSettingModal] = useState(false); const [buttonLoading, setButtonLoading] = useState(loading); const [isModalVisible, setIsModalVisible] = useState(false); @@ -152,11 +157,22 @@ function ConfirmStxTransationComponent({ const [isConnectFailed, setIsConnectFailed] = useState(false); const [isTxApproved, setIsTxApproved] = useState(false); const [isTxRejected, setIsTxRejected] = useState(false); + const [showFeeWarning, setShowFeeWarning] = useState(false); useEffect(() => { setButtonLoading(loading); }, [loading]); + useEffect(() => { + const fee = new BigNumber(initialStxTransactions[0].auth.spendingCondition.fee.toString()); + + if (feeMultipliers && fee.isGreaterThan(new BigNumber(feeMultipliers.thresholdHighStacksFee))) { + setShowFeeWarning(true); + } else if (showFeeWarning) { + setShowFeeWarning(false); + } + }, [initialStxTransactions, feeMultipliers]); + const getFee = () => isSponsored ? new BigNumber(0) @@ -219,6 +235,13 @@ function ConfirmStxTransationComponent({ nonce?: string; }) => { const fee = stxToMicrostacks(new BigNumber(settingFee)); + + if (feeMultipliers && fee.isGreaterThan(new BigNumber(feeMultipliers.thresholdHighStacksFee))) { + setShowFeeWarning(true); + } else if (showFeeWarning) { + setShowFeeWarning(false); + } + setFee(initialStxTransactions[0], BigInt(fee.toString())); if (nonce && nonce !== '') { setNonce(initialStxTransactions[0], BigInt(nonce)); @@ -251,11 +274,11 @@ function ConfirmStxTransationComponent({ await ledgerDelay(1500); setCurrentStepIndex(1); try { - const signedTxs = await signLedgerStxTransaction( + const signedTxs = await signLedgerStxTransaction({ transport, - initialStxTransactions[0].serialize(), - selectedAccount.deviceAccountIndex, - ); + transactionBuffer: initialStxTransactions[0].serialize(), + addressIndex: selectedAccount.deviceAccountIndex, + }); setIsTxApproved(true); await ledgerDelay(1500); onConfirmClick([signedTxs]); @@ -283,6 +306,13 @@ function ConfirmStxTransationComponent({ )} {!!subTitle && {subTitle}} + + {showFeeWarning && ( + + + + )} + {children} {initialStxTransactions[0]?.payload?.amount && ( diff --git a/src/app/components/sendForm/index.tsx b/src/app/components/sendForm/index.tsx index 16785ca53..6138d6d24 100644 --- a/src/app/components/sendForm/index.tsx +++ b/src/app/components/sendForm/index.tsx @@ -297,7 +297,7 @@ function SendForm({ setFiatAmount(amountInCurrency); }; - function getTokenEquivalent(tokenAmount: string): string { + const getTokenEquivalent = (tokenAmount: string): string => { if ((currencyType === 'FT' && !fungibleToken?.tokenFiatRate) || currencyType === 'NFT') { return ''; } @@ -320,7 +320,7 @@ function SendForm({ default: return ''; } - } + }; const getAmountLabel = () => { if (switchToFiat) return fiatCurrency; diff --git a/src/app/hooks/queries/useFeeMultipliers.ts b/src/app/hooks/queries/useFeeMultipliers.ts index 5f0652db6..5aa1ba085 100644 --- a/src/app/hooks/queries/useFeeMultipliers.ts +++ b/src/app/hooks/queries/useFeeMultipliers.ts @@ -1,15 +1,15 @@ import { useDispatch } from 'react-redux'; import { useQuery } from '@tanstack/react-query'; -import { FeesMultipliers } from '@secretkeylabs/xverse-core/types'; +import { AppInfo } from '@secretkeylabs/xverse-core/types'; import { fetchAppInfo } from '@secretkeylabs/xverse-core/api'; import { setFeeMultiplierAction } from '@stores/wallet/actions/actionCreators'; export const useFeeMultipliers = () => { const dispatch = useDispatch(); - const fetchFeeMultiplierData = async (): Promise => { + const fetchFeeMultiplierData = async (): Promise => { try { - const response: FeesMultipliers = await fetchAppInfo(); + const response: AppInfo = await fetchAppInfo(); dispatch(setFeeMultiplierAction(response)); return response; } catch (err) { diff --git a/src/app/hooks/useWalletReducer.ts b/src/app/hooks/useWalletReducer.ts index d994dc6c1..38cc7411f 100644 --- a/src/app/hooks/useWalletReducer.ts +++ b/src/app/hooks/useWalletReducer.ts @@ -4,7 +4,12 @@ import useStxWalletData from '@hooks/queries/useStxWalletData'; import useNetworkSelector from '@hooks/useNetwork'; import { createWalletAccount, restoreWalletWithAccounts } from '@secretkeylabs/xverse-core/account'; import { getBnsName } from '@secretkeylabs/xverse-core/api/stacks'; -import { Account, SettingsNetwork, StacksNetwork } from '@secretkeylabs/xverse-core/types'; +import { + Account, + AnalyticsEvents, + SettingsNetwork, + StacksNetwork, +} from '@secretkeylabs/xverse-core/types'; import { newWallet, walletFromSeedPhrase } from '@secretkeylabs/xverse-core/wallet'; import { ChangeNetworkAction, @@ -22,6 +27,7 @@ import { import { useQueryClient } from '@tanstack/react-query'; import { decryptSeedPhrase, encryptSeedPhrase, generatePasswordHash } from '@utils/encryptionUtils'; import { isHardwareAccount, isLedgerAccount } from '@utils/helper'; +import { resetMixPanel, trackMixPanel } from '@utils/mixpanel'; import { useDispatch } from 'react-redux'; import useWalletSelector from './useWalletSelector'; import useWalletSession from './useWalletSession'; @@ -122,6 +128,7 @@ const useWalletReducer = () => { }; const resetWallet = () => { + resetMixPanel(); dispatch(resetWalletAction()); chrome.storage.local.clear(); chrome.storage.session.clear(); @@ -146,6 +153,8 @@ const useWalletReducer = () => { stxPublicKey: wallet.stxPublicKey, bnsName: wallet.bnsName, }; + trackMixPanel(AnalyticsEvents.RestoreWallet); + const encryptSeed = await encryptSeedPhrase(seed, password); const bnsName = await getBnsName(wallet.stxAddress, selectedNetwork); dispatch(storeEncryptedSeedAction(encryptSeed)); @@ -205,6 +214,8 @@ const useWalletReducer = () => { stxPublicKey: wallet.stxPublicKey, bnsName: wallet.bnsName, }; + trackMixPanel(AnalyticsEvents.CreateNewWallet); + dispatch(setWalletAction(wallet)); dispatch(fetchAccountAction(account, [account])); setSessionStartTime(); diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index be5f0c073..6aeedbc7e 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -64,6 +64,7 @@ import TransactionRequest from '@screens/transactionRequest'; import TransactionStatus from '@screens/transactionStatus'; import WalletExists from '@screens/walletExists'; import { createHashRouter } from 'react-router-dom'; +import PrivacyPreferencesScreen from '@screens/settings/privacyPreferences'; const router = createHashRouter([ { @@ -303,6 +304,10 @@ const router = createHashRouter([ path: 'fiat-currency', element: , }, + { + path: 'privacy-preferences', + element: , + }, { path: 'change-password', element: , diff --git a/src/app/screens/authenticationRequest/index.tsx b/src/app/screens/authenticationRequest/index.tsx index e79ee2cf4..ce50ef4a6 100644 --- a/src/app/screens/authenticationRequest/index.tsx +++ b/src/app/screens/authenticationRequest/index.tsx @@ -167,11 +167,11 @@ function AuthenticationRequest() { }; try { - const authResponse = await handleLedgerStxJWTAuth( + const authResponse = await handleLedgerStxJWTAuth({ transport, - selectedAccount.deviceAccountIndex, + addressIndex: selectedAccount.deviceAccountIndex, profile, - ); + }); setIsTxApproved(true); await ledgerDelay(1500); chrome.tabs.sendMessage(+(params.get('tabId') ?? '0'), { diff --git a/src/app/screens/confirmBrc20Transaction/index.tsx b/src/app/screens/confirmBrc20Transaction/index.tsx index 489418d55..94f6935e8 100644 --- a/src/app/screens/confirmBrc20Transaction/index.tsx +++ b/src/app/screens/confirmBrc20Transaction/index.tsx @@ -22,10 +22,11 @@ import { } from '@utils/brc20'; import { isInOptions, isLedgerAccount } from '@utils/helper'; import BigNumber from 'bignumber.js'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import InfoContainer from '@components/infoContainer'; import Brc20FeesComponent from './brc20FeesComponent'; import { EditFees, OnChangeFeeRate } from './editFees'; import RecipientCard, { RecipientCardProps } from './recipientCard'; @@ -129,11 +130,19 @@ const useConfirmBrc20Transfer = (): { recipient: RecipientCardProps; showFeeSettings: boolean; txFee: BigNumber; + showFeeWarning: boolean; } => { /* hooks */ const { t } = useTranslation('translation'); - const { network, btcFiatRate, fiatCurrency, selectedAccount, btcAddress, ordinalsAddress } = - useWalletSelector(); + const { + network, + btcFiatRate, + fiatCurrency, + selectedAccount, + btcAddress, + ordinalsAddress, + feeMultipliers, + } = useWalletSelector(); const navigate = useNavigate(); const { recipientAddress, @@ -141,6 +150,7 @@ const useConfirmBrc20Transfer = (): { estimatedFees: initEstimatedFees, token, }: ConfirmBrc20TransferState = useLocation().state; + const [showFeeWarning, setShowFeeWarning] = useState(false); useResetUserFlow('/confirm-brc20-tx'); @@ -164,6 +174,14 @@ const useConfirmBrc20Transfer = (): { const { txFee, inscriptionFee, totalFee, transferUtxoValue } = getFeeValuesForBrc20OneStepTransfer(commitValueBreakdown ?? initEstimatedFees.valueBreakdown); + useEffect(() => { + if (feeMultipliers && txFee.isGreaterThan(new BigNumber(feeMultipliers.thresholdHighSatsFee))) { + setShowFeeWarning(true); + } else if (showFeeWarning) { + setShowFeeWarning(false); + } + }, [txFee, feeMultipliers]); + /* callbacks */ const handleClickConfirm = () => { setIsConfirmLoading(true); @@ -265,6 +283,7 @@ const useConfirmBrc20Transfer = (): { recipient, showFeeSettings, txFee, + showFeeWarning, }; }; @@ -286,6 +305,7 @@ export function ConfirmBrc20Transaction() { recipient, showFeeSettings, txFee, + showFeeWarning, } = useConfirmBrc20Transfer(); return ( @@ -294,6 +314,13 @@ export function ConfirmBrc20Transaction() { + {showFeeWarning && ( + + )} + {t('CONFIRM_TRANSACTION.REVIEW_TRANSACTION')} diff --git a/src/app/screens/createWalletSuccess/index.tsx b/src/app/screens/createWalletSuccess/index.tsx index 0de371a84..f14995102 100644 --- a/src/app/screens/createWalletSuccess/index.tsx +++ b/src/app/screens/createWalletSuccess/index.tsx @@ -84,7 +84,8 @@ const ContinueButton = styled.button((props) => ({ function CreateWalletSuccess(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'WALLET_SUCCESS_SCREEN' }); const { action } = useParams(); - const handleOpenWallet = () => { + + const handleCloseTab = () => { window.close(); }; @@ -97,7 +98,7 @@ function CreateWalletSuccess(): JSX.Element { {action === 'restore' ? t('RESTORE_SCREEN_SUBTITLE') : t('SCREEN_SUBTITLE')} - {t('CLOSE_TAB')} + {t('CLOSE_TAB')} {`1. ${t('CLICK')}`} diff --git a/src/app/screens/home/index.tsx b/src/app/screens/home/index.tsx index aa6651e4a..473ff1e49 100644 --- a/src/app/screens/home/index.tsx +++ b/src/app/screens/home/index.tsx @@ -13,6 +13,8 @@ import AccountHeaderComponent from '@components/accountHeader'; import BottomModal from '@components/bottomModal'; import ActionButton from '@components/button'; import ReceiveCardComponent from '@components/receiveCardComponent'; +import { isLedgerAccount } from '@utils/helper'; +import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import ShowBtcReceiveAlert from '@components/showBtcReceiveAlert'; import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; import BottomBar from '@components/tabBar'; @@ -29,11 +31,13 @@ import { Plus } from '@phosphor-icons/react'; import CoinSelectModal from '@screens/home/coinSelectModal'; import { FungibleToken } from '@secretkeylabs/xverse-core/types'; import { CurrencyTypes } from '@utils/constants'; -import { isLedgerAccount } from '@utils/helper'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import styled from 'styled-components'; +import dashboardIcon from '@assets/img/dashboard-icon.svg'; +import { useDispatch } from 'react-redux'; +import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; +import styled, { useTheme } from 'styled-components'; import Theme from 'theme'; import BalanceCard from './balanceCard'; import SquareButton from './squareButton'; @@ -135,11 +139,53 @@ const AddStxButtonContainer = styled.div((props) => ({ marginTop: props.theme.spacing(6), })); +const ModalContent = styled.div((props) => ({ + padding: props.theme.spacing(8), + paddingTop: 0, + paddingBottom: props.theme.spacing(16), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +})); + +const ModalIcon = styled.img((props) => ({ + marginBottom: props.theme.spacing(10), +})); + +const ModalTitle = styled.div((props) => ({ + fontSize: '1rem', + fontWeight: 700, + marginBottom: props.theme.spacing(4), + textAlign: 'center', +})); + +const ModalDescription = styled.div((props) => ({ + fontSize: '0.875rem', + color: props.theme.colors.white['200'], + marginBottom: props.theme.spacing(16), + textAlign: 'center', + lineHeight: '1.25rem', +})); + +const ModalControlsContainer = styled.div({ + display: 'flex', + width: '100%', +}); + +const ModalButtonContainer = styled.div((props) => ({ + width: '100%', + '&:first-child': { + marginRight: props.theme.spacing(6), + }, +})); + function Home() { const { t } = useTranslation('translation', { keyPrefix: 'DASHBOARD_SCREEN', }); + const theme = useTheme(); const navigate = useNavigate(); + const dispatch = useDispatch(); const [openReceiveModal, setOpenReceiveModal] = useState(false); const [openSendModal, setOpenSendModal] = useState(false); const [openBuyModal, setOpenBuyModal] = useState(false); @@ -154,6 +200,7 @@ function Home() { brcCoinsList, showBtcReceiveAlert, showOrdinalReceiveAlert, + showDataCollectionAlert, } = useWalletSelector(); const [areReceivingAddressesVisible, setAreReceivingAddressesVisible] = useState( !isLedgerAccount(selectedAccount), @@ -387,6 +434,16 @@ function Home() { ); + const handleDataCollectionDeny = () => { + optOutMixPanel(); + dispatch(changeShowDataCollectionAlertAction(false)); + }; + + const handleDataCollectionAllow = () => { + optInMixPanel(selectedAccount?.masterPubKey); + dispatch(changeShowDataCollectionAlertAction(false)); + }; + const showSwaps = !isLedgerAccount(selectedAccount); return ( @@ -504,6 +561,44 @@ function Home() { /> + + + + + {t('DATA_COLLECTION_POPUP.TITLE')} + {t('DATA_COLLECTION_POPUP.DESCRIPTION')} + + + + + + + + + + ); } diff --git a/src/app/screens/ledger/addStxAddress/index.tsx b/src/app/screens/ledger/addStxAddress/index.tsx index 804e05907..18f0caa1f 100644 --- a/src/app/screens/ledger/addStxAddress/index.tsx +++ b/src/app/screens/ledger/addStxAddress/index.tsx @@ -17,26 +17,35 @@ import LedgerFailView from '@components/ledger/failLedgerView'; import LedgerAddressComponent from '@components/ledger/ledgerAddressComponent'; import useResetUserFlow from '@hooks/useResetUserFlow'; import { useLocation } from 'react-router-dom'; +import { DEFAULT_TRANSITION_OPTIONS } from '@utils/constants'; import { Credential } from '../importLedgerAccount'; +import { + Container, + OnBoardingActionsContainer, + OnBoardingContentContainer, +} from '../importLedgerAccount/index.styled'; import { ActionButtonContainer, AddAddressDetailsContainer, AddAddressHeaderContainer, AddressAddedContainer, ConfirmationText, - Container, LedgerFailButtonsContainer, LedgerFailViewContainer, - OnBoardingActionsContainer, - OnBoardingContentContainer, SelectAssetText, SelectAssetTitle, -} from '../importLedgerAccount/index.styled'; +} from '../importLedgerAccount/steps/index.styled'; + +enum Steps { + ConnectLedger = 0, + VerifyAddress = 1, + AddressAdded = 2, +} function AddStxAddress(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'LEDGER_IMPORT_SCREEN' }); - const [currentStepIndex, setCurrentStepIndex] = useState(0); + const [currentStep, setCurrentStep] = useState(Steps.ConnectLedger); const [isConnectSuccess, setIsConnectSuccess] = useState(false); const [isConnectFailed, setIsConnectFailed] = useState(false); const [isButtonDisabled, setIsButtonDisabled] = useState(false); @@ -47,21 +56,12 @@ function AddStxAddress(): JSX.Element { const { search } = useLocation(); const params = new URLSearchParams(search); const mismatch = params.get('mismatch') ?? ''; - const transition = useTransition(currentStepIndex, { - from: { - x: 24, - opacity: 0, - }, - enter: { - x: 0, - opacity: 1, - }, - }); + const transition = useTransition(currentStep, DEFAULT_TRANSITION_OPTIONS); useResetUserFlow('/add-stx-address-ledger'); const handleClickNext = async () => { - setCurrentStepIndex((prevStepIndex) => prevStepIndex + 1); + setCurrentStep((prevStepIndex) => prevStepIndex + 1); }; const saveAddressToWallet = async (stacksCreds: { address: string; publicKey: string }) => { @@ -76,7 +76,7 @@ function AddStxAddress(): JSX.Element { }; await updateLedgerAccounts(ledgerAccount); await ledgerDelay(1000); - setCurrentStepIndex(2); + setCurrentStep(Steps.AddressAdded); setIsButtonDisabled(false); }; @@ -91,13 +91,13 @@ function AddStxAddress(): JSX.Element { throw new Error('Account not found'); } - const stacksCreds = await importStacksAccountFromLedger( + const stacksCreds = await importStacksAccountFromLedger({ transport, - network.type, - 0, + network: network.type, + accountIndex: 0, addressIndex, showAddress, - ); + }); setStacksCredentials(stacksCreds); await transport.close(); @@ -133,7 +133,7 @@ function AddStxAddress(): JSX.Element { throw new Error('No response'); } await saveAddressToWallet(stacksCreds); - } catch (err) { + } catch (err: any) { console.error(err); setIsConnectSuccess(false); setIsConnectFailed(true); @@ -147,7 +147,7 @@ function AddStxAddress(): JSX.Element { setIsConnectFailed(false); setIsAddressRejected(false); - setCurrentStepIndex(0); + setCurrentStep(Steps.ConnectLedger); }; const handleWindowClose = () => { @@ -156,6 +156,106 @@ function AddStxAddress(): JSX.Element { } }; + const renderContent = () => { + switch (currentStep) { + case Steps.ConnectLedger: + return ( + + ); + case Steps.VerifyAddress: + if (isConnectFailed || isAddressRejected) { + return ( + + ); + } + + return ( + <> + + stacks + {t('LEDGER_ADD_ADDRESS.TITLE_VERIFY_STX')} + + + {t('LEDGER_ADD_ADDRESS.SUBTITLE')} + + + {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} + + ); + case Steps.AddressAdded: + return ( + + Success + {t('LEDGER_STX_WALLET_ADDED.TITLE')} + {t('LEDGER_STX_WALLET_ADDED.SUBTITLE')} + + ); + default: + return null; + } + }; + + const renderActionButton = () => { + switch (currentStep) { + case Steps.ConnectLedger: + return ( + + ); + case Steps.VerifyAddress: + if (isConnectFailed) { + return ( + + ); + } + break; + case Steps.AddressAdded: + return ( + + ); + default: + return null; + } + }; + if (mismatch) { return ( @@ -177,86 +277,8 @@ function AddStxAddress(): JSX.Element { {transition((style) => ( <> - - {currentStepIndex === 0 && ( - - )} - {currentStepIndex === 1 && - (isConnectFailed || isAddressRejected ? ( - - ) : ( - <> - - stacks - {t('LEDGER_ADD_ADDRESS.TITLE_VERIFY_STX')} - - - {t('LEDGER_ADD_ADDRESS.SUBTITLE')} - - - {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} - - ))} - {currentStepIndex === 2 && ( - - Success - {t('LEDGER_STX_WALLET_ADDED.TITLE')} - {t('LEDGER_STX_WALLET_ADDED.SUBTITLE')} - - )} - - - {currentStepIndex === 0 && ( - - )} - {currentStepIndex === 1 && (isConnectFailed || isAddressRejected) && ( - - )} - {currentStepIndex === 2 && ( - - )} - + {renderContent()} + {renderActionButton()} ))} diff --git a/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts b/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts new file mode 100644 index 000000000..c2a87b3eb --- /dev/null +++ b/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts @@ -0,0 +1,105 @@ +import styled from 'styled-components'; +import { animated } from '@react-spring/web'; + +export const Container = styled.div` + display: flex; + width: 100%; + margin-left: auto; + margin-right: auto; + flex-direction: column; + flex: 1; + &::-webkit-scrollbar { + display: none; + } +`; +export const OnBoardingContentContainer = styled(animated.div)((props) => ({ + display: 'flex', + flexDirection: 'column', + flex: 1, + justifyContent: 'center', + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), +})); + +export const SuccessActionsContainer = styled.div((props) => ({ + width: '100%', + display: 'flex', + flexDirection: 'column', + gap: props.theme.spacing(6), + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), + marginBottom: props.theme.spacing(30), +})); + +export const TxConfirmedContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; + > :first-child { + margin-bottom: 26px; + } +`; +export const TxConfirmedTitle = styled.h1((props) => ({ + ...props.theme.headline_s, +})); + +export const TxConfirmedDescription = styled.p((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[200], +})); + +export const InfoImage = styled.img({ + width: 64, + height: 64, +}); + +export const ConnectLedgerTitle = styled.h1((props) => ({ + ...props.theme.headline_s, + marginBottom: props.theme.spacing(6), +})); + +export const ConnectLedgerTextAdvanced = styled.p<{ + isCompleted?: boolean; +}>((props) => ({ + ...props.theme.body_m, + display: 'flex', + alignItems: 'flex-start', + color: props.isCompleted ? props.theme.colors.white[400] : props.theme.colors.white[200], + textAlign: 'center', + marginBottom: props.theme.spacing(16), +})); + +export const InfoContainerWrapper = styled.div((props) => ({ + textAlign: 'left', + marginTop: props.theme.spacing(8), +})); + +export const TxDetails = styled.div((props) => ({ + marginTop: props.theme.spacing(36), + width: '100%', + fontSize: '0.875rem', + fontWeight: 500, +})); + +export const TxDetailsRow = styled.div((props) => ({ + display: 'flex', + justifyContent: 'space-between', + marginBottom: props.theme.spacing(6), +})); + +export const TxDetailsTitle = styled.div((props) => ({ + color: props.theme.colors.white[200], +})); + +export const RecipientsWrapper = styled.div({ + display: 'flex', + flexDirection: 'column', +}); + +export const ConfirmTxIconBig = styled.img((props) => ({ + width: 32, + height: 32, + marginBottom: props.theme.spacing(8), +})); diff --git a/src/app/screens/ledger/confirmLedgerTransaction/index.tsx b/src/app/screens/ledger/confirmLedgerTransaction/index.tsx index bf7ead17c..92415da64 100644 --- a/src/app/screens/ledger/confirmLedgerTransaction/index.tsx +++ b/src/app/screens/ledger/confirmLedgerTransaction/index.tsx @@ -1,8 +1,7 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; import { useLocation } from 'react-router-dom'; -import { animated, useTransition } from '@react-spring/web'; +import { useTransition } from '@react-spring/web'; import Transport from '@ledgerhq/hw-transport-webusb'; import ActionButton from '@components/button'; import { @@ -37,115 +36,36 @@ import LedgerFailView from '@components/ledger/failLedgerView'; import { UTXO } from '@secretkeylabs/xverse-core/types'; import Stepper from '@components/stepper'; import { LedgerTransactionType } from '@common/types/ledger'; +import { DEFAULT_TRANSITION_OPTIONS } from '@utils/constants'; -const Container = styled.div` - display: flex; - width: 100%; - margin-left: auto; - margin-right: auto; - flex-direction: column; - flex: 1; - &::-webkit-scrollbar { - display: none; - } -`; -const OnBoardingContentContainer = styled(animated.div)((props) => ({ - display: 'flex', - flexDirection: 'column', - flex: 1, - justifyContent: 'center', - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), -})); - -const SuccessActionsContainer = styled.div((props) => ({ - width: '100%', - display: 'flex', - flexDirection: 'column', - gap: props.theme.spacing(6), - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - marginBottom: props.theme.spacing(30), -})); - -const TxConfirmedContainer = styled.div` - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - gap: 8px; - > :first-child { - margin-bottom: 26px; - } -`; -const TxConfirmedTitle = styled.h1((props) => ({ - ...props.theme.headline_s, -})); - -const TxConfirmedDescription = styled.p((props) => ({ - ...props.theme.body_m, - color: props.theme.colors.white[200], -})); - -const InfoImage = styled.img` - width: 64px; - height: 64px; -`; - -export const ConnectLedgerTitle = styled.h1((props) => ({ - ...props.theme.headline_s, - marginBottom: props.theme.spacing(6), -})); - -interface ConnectLedgerTextAdvancedProps { - isCompleted?: boolean; +import { + Container, + OnBoardingContentContainer, + RecipientsWrapper, + ConfirmTxIconBig, + TxDetails, + TxDetailsRow, + TxDetailsTitle, + ConnectLedgerTitle, + ConnectLedgerTextAdvanced, + InfoImage, + SuccessActionsContainer, + TxConfirmedContainer, + TxConfirmedTitle, + TxConfirmedDescription, + InfoContainerWrapper, +} from './index.styled'; + +enum Steps { + ConnectLedger = 0, + ExternalInputs = 0.5, + ConfirmTransaction = 1, + ConfirmFees = 1.5, + TransactionConfirmed = 2, } -export const ConnectLedgerTextAdvanced = styled.p((props) => ({ - ...props.theme.body_m, - display: 'flex', - alignItems: 'flex-start', - color: props.isCompleted ? props.theme.colors.white[400] : props.theme.colors.white[200], - textAlign: 'center', - marginBottom: props.theme.spacing(16), -})); - -const InfoContainerWrapper = styled.div( - (props) => ` - text-align: left; - margin-top: ${props.theme.spacing(8)}px; -`, -); - -const TxDetails = styled.div((props) => ({ - marginTop: props.theme.spacing(36), - width: '100%', - fontSize: '0.875rem', - fontWeight: 500, -})); - -const TxDetailsRow = styled.div((props) => ({ - display: 'flex', - justifyContent: 'space-between', - marginBottom: props.theme.spacing(6), -})); - -const TxDetailsTitle = styled.div((props) => ({ - color: props.theme.colors.white[200], -})); - -const RecipientsWrapper = styled.div({ - display: 'flex', - flexDirection: 'column', -}); - -const ConfirmTxIconBig = styled.img((props) => ({ - width: 32, - height: 32, - marginBottom: props.theme.spacing(8), -})); function ConfirmLedgerTransaction(): JSX.Element { - const [currentStepIndex, setCurrentStepIndex] = useState(0); + const [currentStep, setCurrentStep] = useState(Steps.ConnectLedger); const [txId, setTxId] = useState(undefined); const [isButtonDisabled, setIsButtonDisabled] = useState(false); @@ -181,39 +101,30 @@ function ConfirmLedgerTransaction(): JSX.Element { fee?: BigNumber; } = location.state; - const transition = useTransition(currentStepIndex, { - from: { - x: 24, - opacity: 0, - }, - enter: { - x: 0, - opacity: 1, - }, - }); - - const signAndBroadcastOrdinalsTx = async (transport: Transport, accountId: number) => { + const transition = useTransition(currentStep, DEFAULT_TRANSITION_OPTIONS); + + const signAndBroadcastOrdinalsTx = async (transport: Transport, addressIndex: number) => { try { - const result = await signLedgerMixedBtcTransaction( + const result = await signLedgerMixedBtcTransaction({ transport, - network.type, - accountId, - recipients as Recipient[], - feeRateInput?.toString(), + network: network.type, + addressIndex, + recipients: recipients as Recipient[], + feeRate: feeRateInput?.toString(), ordinalUtxo, - ); + }); const { value: psbtCreatedValue } = await result.next(); const { value: taprootSignedValue } = await result.next(); setIsTxApproved(true); - setCurrentStepIndex(1.5); + setCurrentStep(Steps.ConfirmFees); const { value: txHex } = await result.next(); setIsFinalTxApproved(true); await ledgerDelay(1500); const transactionId = await btcClient.sendRawTransaction(txHex || taprootSignedValue); setTxId(transactionId.tx.hash); - setCurrentStepIndex(2); + setCurrentStep(Steps.TransactionConfirmed); } catch (err) { console.error(err); setIsTxRejected(true); @@ -223,20 +134,20 @@ function ConfirmLedgerTransaction(): JSX.Element { } }; - const signAndBroadcastBtcTx = async (transport: Transport, accountId: number) => { + const signAndBroadcastBtcTx = async (transport: Transport, addressIndex: number) => { try { - const result = await signLedgerNativeSegwitBtcTransaction( + const result = await signLedgerNativeSegwitBtcTransaction({ transport, - network.type, - accountId, - recipients as Recipient[], - feeRateInput?.toString(), - ); + network: network.type, + addressIndex, + recipients: recipients as Recipient[], + feeRate: feeRateInput?.toString(), + }); setIsFinalTxApproved(true); await ledgerDelay(1500); const transactionId = await btcClient.sendRawTransaction(result); setTxId(transactionId.tx.hash); - setCurrentStepIndex(2); + setCurrentStep(Steps.TransactionConfirmed); } catch (err) { console.error(err); setIsTxRejected(true); @@ -246,14 +157,18 @@ function ConfirmLedgerTransaction(): JSX.Element { } }; - const signAndBroadcastStxTx = async (transport: Transport, accountId: number) => { + const signAndBroadcastStxTx = async (transport: Transport, addressIndex: number) => { try { - const result = await signLedgerStxTransaction(transport, unsignedTx, accountId); + const result = await signLedgerStxTransaction({ + transport, + transactionBuffer: unsignedTx, + addressIndex, + }); setIsFinalTxApproved(true); await ledgerDelay(1500); const transactionHash = await broadcastSignedTransaction(result, selectedNetwork); setTxId(transactionHash); - setCurrentStepIndex(2); + setCurrentStep(Steps.TransactionConfirmed); } catch (err) { console.error(err); setIsTxRejected(true); @@ -281,9 +196,9 @@ function ConfirmLedgerTransaction(): JSX.Element { return; } - const accountId = selectedAccount.deviceAccountIndex; + const addressIndex = selectedAccount.deviceAccountIndex; - if (accountId === undefined) { + if (addressIndex === undefined) { setIsConnectSuccess(false); setIsConnectFailed(true); setIsWrongDevice(true); @@ -294,25 +209,29 @@ function ConfirmLedgerTransaction(): JSX.Element { setIsConnectSuccess(true); await ledgerDelay(1500); - if (type === 'ORDINALS' && currentStepIndex !== 0.5 && currentStepIndex !== 1) { - setCurrentStepIndex(0.5); + if ( + type === 'ORDINALS' && + currentStep !== Steps.ExternalInputs && + currentStep !== Steps.ConfirmTransaction + ) { + setCurrentStep(Steps.ExternalInputs); return; } - if (currentStepIndex !== 1) { - setCurrentStepIndex(1); + if (currentStep !== Steps.ConfirmTransaction) { + setCurrentStep(Steps.ConfirmTransaction); } switch (type) { case 'BTC': case 'BRC-20': - await signAndBroadcastBtcTx(transport as Transport, accountId); + await signAndBroadcastBtcTx(transport as Transport, addressIndex); break; case 'STX': - await signAndBroadcastStxTx(transport as Transport, accountId); + await signAndBroadcastStxTx(transport as Transport, addressIndex); break; case 'ORDINALS': - await signAndBroadcastOrdinalsTx(transport as Transport, accountId); + await signAndBroadcastOrdinalsTx(transport as Transport, addressIndex); break; default: break; @@ -327,7 +246,7 @@ function ConfirmLedgerTransaction(): JSX.Element { }; const goToConfirmationStep = () => { - setCurrentStepIndex(1); + setCurrentStep(Steps.ConfirmTransaction); handleConnectAndConfirm(); }; @@ -338,7 +257,7 @@ function ConfirmLedgerTransaction(): JSX.Element { setIsConnectFailed(false); setIsWrongDevice(false); setIsTxApproved(false); - setCurrentStepIndex(0); + setCurrentStep(Steps.ConnectLedger); }; const handleClose = () => { @@ -396,7 +315,7 @@ function ConfirmLedgerTransaction(): JSX.Element { {fee && ( - Fees + {t('FEES')} {type === 'STX' ? (
{microstacksToStx(fee).toString()} STX
) : ( @@ -411,8 +330,8 @@ function ConfirmLedgerTransaction(): JSX.Element { <> {renderTxDetails()} @@ -423,8 +342,8 @@ function ConfirmLedgerTransaction(): JSX.Element { type === 'STX' ? 'CONNECT.STX_ERROR_SUBTITLE' : 'CONNECT.BTC_ERROR_SUBTITLE'; const renderLedgerConfirmationView = () => { - switch (currentStepIndex) { - case 0: + switch (currentStep) { + case Steps.ConnectLedger: return (
); - case 0.5: + case Steps.ExternalInputs: if (isTxRejected || isConnectFailed) { return ( @@ -456,7 +375,7 @@ function ConfirmLedgerTransaction(): JSX.Element { ); - case 1: + case Steps.ConfirmTransaction: if (type === 'ORDINALS') { if (isTxRejected || isConnectFailed) { return ( @@ -494,7 +413,7 @@ function ConfirmLedgerTransaction(): JSX.Element { {renderTxDetails()} ); - case 1.5: + case Steps.ConfirmFees: if (type === 'ORDINALS') { if (isTxRejected || isConnectFailed) { return ( @@ -518,7 +437,7 @@ function ConfirmLedgerTransaction(): JSX.Element { ); } return null; - case 2: + case Steps.TransactionConfirmed: return ( Success @@ -537,8 +456,8 @@ function ConfirmLedgerTransaction(): JSX.Element { }; const renderLedgerConfirmationControls = () => { - switch (currentStepIndex) { - case 0.5: + switch (currentStep) { + case Steps.ExternalInputs: if (isTxRejected || isConnectFailed) { return ( @@ -563,8 +482,8 @@ function ConfirmLedgerTransaction(): JSX.Element { ); - case 1: - case 1.5: + case Steps.ConfirmTransaction: + case Steps.ConfirmFees: if (type === 'ORDINALS' && !isTxRejected && !isConnectFailed) { return ( @@ -589,7 +508,7 @@ function ConfirmLedgerTransaction(): JSX.Element { /> ); - case 2: + case Steps.TransactionConfirmed: return ( diff --git a/src/app/screens/ledger/importLedgerAccount/index.styled.ts b/src/app/screens/ledger/importLedgerAccount/index.styled.ts index f11b4389d..bcbc17d9b 100644 --- a/src/app/screens/ledger/importLedgerAccount/index.styled.ts +++ b/src/app/screens/ledger/importLedgerAccount/index.styled.ts @@ -1,6 +1,5 @@ import styled from 'styled-components'; import { animated } from '@react-spring/web'; -import Switch from 'react-switch'; export const Container = styled.div` display: flex; @@ -31,296 +30,3 @@ export const OnBoardingActionsContainer = styled.div((props) => ({ paddingRight: props.theme.spacing(8), marginBottom: props.theme.spacing(30), })); - -export const ImportStartImage = styled.img((props) => ({ - marginLeft: props.theme.spacing(0), -})); - -export const ImportStartContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - maxWidth: '328px', -}); - -export const ImportBeforeStartContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - maxWidth: '328px', - paddingTop: props.theme.spacing(16), -})); - -export const ButtonContainer = styled.div((props) => ({ - marginLeft: 3, - marginRight: 3, - marginTop: props.theme.spacing(4), - width: '100%', -})); - -export const ImportStartTitle = styled.h1((props) => ({ - ...props.theme.headline_s, - marginTop: props.theme.spacing(40), - textAlign: 'center', -})); -export const ImportStartText = styled.p((props) => ({ - ...props.theme.body_m, - textAlign: 'center', - marginTop: props.theme.spacing(6), - color: props.theme.colors.white[200], -})); - -export const ImportBeforeStartTitle = styled.h1((props) => ({ - ...props.theme.headline_s, - marginTop: props.theme.spacing(5), - textAlign: 'left', - alignSelf: 'flex-start', -})); -export const ImportBeforeStartText = styled.p((props) => ({ - ...props.theme.body_m, - textAlign: 'left', - marginTop: props.theme.spacing(6), - color: props.theme.colors.white[200], -})); - -export const ImportCardContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - gap: props.theme.spacing(6), -})); - -export const SelectAssetTextContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(20), - marginBottom: props.theme.spacing(16), - display: 'flex', - flexDirection: 'column', - gap: props.theme.spacing(6), -})); - -export const SelectAssetTitle = styled.h1((props) => ({ - ...props.theme.headline_s, -})); - -interface SelectAssetTextProps { - centered?: boolean; -} -export const SelectAssetText = styled.p((props) => ({ - ...props.theme.body_m, - color: props.theme.colors.white[200], - textAlign: props.centered ? 'center' : 'left', -})); - -export const SelectAssetFootNote = styled.p((props) => ({ - ...props.theme.body_xs, - color: props.theme.colors.white[200], - marginTop: props.theme.spacing(6), -})); - -export const AddAddressHeaderContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - gap: props.theme.spacing(8), - marginTop: props.theme.spacing(20), - marginBottom: props.theme.spacing(8), -})); - -export const CreateAnotherAccountContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - gap: props.theme.spacing(8), - paddingTop: props.theme.spacing(90), - marginBottom: props.theme.spacing(16), -})); - -export const AddAddressDetailsContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'flex-start', - gap: props.theme.spacing(20), -})); - -export const AddressAddedContainer = styled.div` - display: flex; - flex-direction: column; - align-items: center; - margin: auto; - text-align: center; - gap: 8px; - > :first-child { - margin-bottom: 26px; - } -`; - -export const AddAccountNameContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(20), - width: '100%', - display: 'flex', - flexDirection: 'column', - gap: props.theme.spacing(6), -})); - -export const AddAccountNameTitleContainer = styled.div((props) => ({ - width: '100%', - display: 'flex', - flexDirection: 'column', - gap: props.theme.spacing(4), - marginBottom: props.theme.spacing(22), -})); - -export const CreateMultipleAccountsText = styled.h3((props) => ({ - ...props.theme.body_l, - textAlign: 'center', -})); - -export const EndScreenContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -}); - -export const EndScreenTextContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - textAlign: 'center', - gap: props.theme.spacing(6), - marginBottom: props.theme.spacing(20), -})); - -export const AssetSelectionButton = styled.button((props) => ({ - position: 'absolute', - left: props.theme.spacing(105), - top: props.theme.spacing(60), - backgroundColor: 'transparent', - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - gap: props.theme.spacing(3), -})); - -export const AssetSelectionButtonText = styled.p((props) => ({ - ...props.theme.body_m, - color: props.theme.colors.white[0], -})); - -export const ConfirmationText = styled.p((props) => ({ - fontSize: '0.875rem', - fontWeight: 500, - textAlign: 'center', - marginTop: props.theme.spacing(50), -})); - -export const ConfirmationStepsContainer = styled.div((props) => ({ - display: 'flex', - justifyContent: 'center', - marginTop: props.theme.spacing(12), -})); - -export const OptionsContainer = styled.div((props) => ({ - width: '100%', - marginTop: props.theme.spacing(16), -})); - -interface OptionProps { - selected?: boolean; -} -export const Option = styled.div((props) => ({ - width: '100%', - backgroundColor: '#21253C', - padding: props.theme.spacing(8), - paddingTop: props.theme.spacing(7), - paddingBottom: props.theme.spacing(7), - borderRadius: props.theme.radius(2), - fontSize: '0.75rem', - marginBottom: props.theme.spacing(6), - border: `1px solid ${props.selected ? 'rgba(115, 131, 255, 0.40)' : 'transparent'}`, - cursor: 'pointer', - userSelect: 'none', - display: 'flex', - alignItems: 'center', - transition: 'border 0.2s ease', -})); - -export const OptionIcon = styled.div((props) => ({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: 15, - height: 15, - borderRadius: '50%', - border: `1px solid ${props.theme.colors.white[0]}`, - marginRight: props.theme.spacing(10), - flex: 'none', - '&::after': { - content: '""', - display: props.selected ? 'block' : 'none', - width: 8, - height: 8, - borderRadius: 100, - backgroundColor: props.theme.colors.white[0], - }, -})); - -interface ConfirmationStepProps { - isCompleted: boolean; -} -export const ConfirmationStep = styled.div((props) => ({ - width: 32, - height: 4, - backgroundColor: props.isCompleted ? props.theme.colors.white[0] : props.theme.colors.white[900], - borderRadius: props.theme.radius(1), - transition: 'background-color 0.2s ease', - ':first-child': { - marginRight: props.theme.spacing(4), - }, -})); - -export const CustomSwitch = styled(Switch)` - .react-switch-handle { - background-color: ${({ checked }) => - checked ? '#FFFFFF' : 'rgba(255, 255, 255, 0.2)'} !important; - border: ${({ checked }) => (checked ? '' : '4px solid rgba(255, 255, 255, 0.2)')} !important; - } -`; - -export const TogglerContainer = styled.div((props) => ({ - display: 'flex', - alignItems: 'center', - marginTop: props.theme.spacing(18), -})); - -export const TogglerText = styled.p((props) => ({ - marginLeft: props.theme.spacing(8), - fontWeight: 500, - fontSize: '0.875rem', - lineHeight: '140%', -})); - -export const CustomLink = styled.a((props) => ({ - color: props.theme.colors.orange_main, -})); - -export const WarningIcon = styled.img({ - width: 32, - height: 32, - alignSelf: 'flex-start', -}); - -export const LedgerFailViewContainer = styled.div((props) => ({ - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - margin: 'auto', -})); - -export const LedgerFailButtonsContainer = styled.div((props) => ({ - width: '100%', - marginTop: props.theme.spacing(25), -})); - -export const ActionButtonContainer = styled.div((props) => ({ - '&:not(:last-of-type)': { - marginBottom: props.theme.spacing(8), - }, -})); diff --git a/src/app/screens/ledger/importLedgerAccount/index.tsx b/src/app/screens/ledger/importLedgerAccount/index.tsx index 270c42066..bedaf52c1 100644 --- a/src/app/screens/ledger/importLedgerAccount/index.tsx +++ b/src/app/screens/ledger/importLedgerAccount/index.tsx @@ -1,9 +1,7 @@ import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useTheme } from 'styled-components'; import { useTransition } from '@react-spring/web'; import Transport from '@ledgerhq/hw-transport-webusb'; -import ActionButton from '@components/button'; import { Account, getMasterFingerPrint, @@ -13,83 +11,23 @@ import { } from '@secretkeylabs/xverse-core'; import useWalletReducer from '@hooks/useWalletReducer'; import { getDeviceNewAccountIndex, getNewAccountId, ledgerDelay } from '@common/utils/ledger'; -import LedgerAddressComponent from '@components/ledger/ledgerAddressComponent'; import useWalletSelector from '@hooks/useWalletSelector'; -import LedgerInput from '@components/ledger/ledgerInput'; import FullScreenHeader from '@components/ledger/fullScreenHeader'; -import warningIcon from '@assets/img/Warning_red.svg'; import { LedgerErrors } from '@secretkeylabs/xverse-core/ledger/types'; +import { DEFAULT_TRANSITION_OPTIONS } from '@utils/constants'; +import { ImportLedgerSteps, LedgerLiveOptions } from './types'; +import StepControls from './stepControls'; +import Steps from './steps'; -import ledgerImportStartIcon from '@assets/img/ledger/ledger_import_start.svg'; -import btcOrdinalsIcon from '@assets/img/ledger/btc_ordinals_icon.svg'; -import btcIcon from '@assets/img/ledger/btc_icon.svg'; -import ordinalsIcon from '@assets/img/ledger/ordinals_icon.svg'; -import stxIcon from '@assets/img/ledger/stx_icon.svg'; -import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.svg'; -import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; -import checkCircleIcon from '@assets/img/ledger/check_circle.svg'; -import ledgerAccountSwitchIcon from '@assets/img/ledger/account_switch.svg'; -import arrowLeftIcon from '@assets/img/ledger/arrow_left_icon.svg'; -import LedgerFailView from '@components/ledger/failLedgerView'; -import LedgerAssetSelectCard from '@components/ledger/ledgerAssetSelectCard'; -import LedgerConnectionView from '../../../components/ledger/connectLedgerView'; - -import { - AddAccountNameContainer, - AddAccountNameTitleContainer, - AddAddressDetailsContainer, - AddAddressHeaderContainer, - AddressAddedContainer, - AssetSelectionButton, - AssetSelectionButtonText, - ButtonContainer, - ConfirmationStep, - ConfirmationStepsContainer, - ConfirmationText, - Container, - CreateAnotherAccountContainer, - CreateMultipleAccountsText, - CustomLink, - CustomSwitch, - EndScreenContainer, - EndScreenTextContainer, - ImportBeforeStartContainer, - ImportBeforeStartText, - ImportBeforeStartTitle, - ImportCardContainer, - ImportStartContainer, - ImportStartImage, - ImportStartText, - ImportStartTitle, - OnBoardingActionsContainer, - OnBoardingContentContainer, - Option, - OptionIcon, - OptionsContainer, - SelectAssetFootNote, - SelectAssetText, - SelectAssetTextContainer, - SelectAssetTitle, - TogglerContainer, - TogglerText, - WarningIcon, -} from './index.styled'; - -const LINK_TO_LEDGER_ACCOUNT_ISSUE_GUIDE = - 'https://support.xverse.app/hc/en-us/articles/17901278165773'; -const LINK_TO_LEDGER_PASSPHRASE_GUIDE = - 'https://support.xverse.app/hc/en-us/articles/17901278165773'; +import { Container, OnBoardingContentContainer, OnBoardingActionsContainer } from './index.styled'; export interface Credential { publicKey: string; address: string; } -type LedgerLiveOption = 'using' | 'not using'; - function ImportLedger(): JSX.Element { - const theme = useTheme(); - const [currentStepIndex, setCurrentStepIndex] = useState(0); + const [currentStep, setCurrentStep] = useState(ImportLedgerSteps.START); const [isBitcoinSelected, setIsBitcoinSelected] = useState(true); const [isStacksSelected, setIsStacksSelected] = useState(false); const [bitcoinCredentials, setBitcoinCredentials] = useState(undefined); @@ -109,21 +47,11 @@ function ImportLedger(): JSX.Element { const [isOrdinalsAddressRejected, setIsOrdinalsAddressRejected] = useState(false); const { t } = useTranslation('translation', { keyPrefix: 'LEDGER_IMPORT_SCREEN' }); const { addLedgerAccount, updateLedgerAccounts } = useWalletReducer(); - const [selectedLedgerLiveOption, setSelectedLedgerLiveOption] = useState( - null, - ); + const [selectedLedgerLiveOption, setSelectedLedgerLiveOption] = + useState(null); const [isTogglerChecked, setIsTogglerChecked] = useState(false); const { ledgerAccountsList, network } = useWalletSelector(); - const transition = useTransition(currentStepIndex, { - from: { - x: 24, - opacity: 0, - }, - enter: { - x: 0, - opacity: 1, - }, - }); + const transition = useTransition(currentStep, DEFAULT_TRANSITION_OPTIONS); const importBtcAccounts = async (showAddress: boolean, masterFingerPrint?: string) => { let btcCreds; @@ -137,13 +65,13 @@ function ImportLedger(): JSX.Element { ); if (isBitcoinSelected) { try { - const bitcoinAccount = await importNativeSegwitAccountFromLedger( + const bitcoinAccount = await importNativeSegwitAccountFromLedger({ transport, - network.type, - 0, - deviceNewAccountIndex, + network: network.type, + accountIndex: 0, + addressIndex: deviceNewAccountIndex, showAddress, - ); + }); btcCreds = { address: bitcoinAccount.address, publicKey: bitcoinAccount.publicKey, @@ -151,9 +79,10 @@ function ImportLedger(): JSX.Element { setBitcoinCredentials(btcCreds); if (showAddress) { setIsBtcAddressConfirmed(true); - setCurrentStepIndex(3.5); + setCurrentStep(ImportLedgerSteps.ADD_ORDINALS_ADDRESS); } } catch (err: any) { + console.error(err); if (err.statusCode === 27013) { setIsBtcAddressRejected(true); } else { @@ -164,13 +93,13 @@ function ImportLedger(): JSX.Element { return; } try { - const ordinalsAccount = await importTaprootAccountFromLedger( + const ordinalsAccount = await importTaprootAccountFromLedger({ transport, - network.type, - 0, - deviceNewAccountIndex, + network: network.type, + accountIndex: 0, + addressIndex: deviceNewAccountIndex, showAddress, - ); + }); ordinalsCreds = { address: ordinalsAccount.address, publicKey: ordinalsAccount.publicKey, @@ -180,6 +109,7 @@ function ImportLedger(): JSX.Element { setIsOrdinalsAddressConfirmed(true); } } catch (err: any) { + console.error(err); if (err.statusCode === 27013) { setIsOrdinalsAddressRejected(true); } else { @@ -202,13 +132,13 @@ function ImportLedger(): JSX.Element { const transport = await Transport.create(); try { - const stacksCreds = await importStacksAccountFromLedger( + const stacksCreds = await importStacksAccountFromLedger({ transport, - network.type, - 0, - deviceAccountIndex, + network: network.type, + accountIndex: 0, + addressIndex: deviceAccountIndex, showAddress, - ); + }); setStacksCredentials(stacksCreds); await transport.close(); @@ -227,34 +157,19 @@ function ImportLedger(): JSX.Element { const handleClickNext = async () => { /* - Go back to step 2 if user wants to add the stacks account as well + Go back to Connect Ledger step if user wants to add the stacks account as well */ - if (currentStepIndex === 4 && isBitcoinSelected && isStacksSelected) { + if (currentStep === ImportLedgerSteps.ADDRESS_ADDED && isBitcoinSelected && isStacksSelected) { setIsBitcoinSelected(false); setIsButtonDisabled(false); setIsConnectSuccess(false); setIsConnectFailed(false); - setCurrentStepIndex(2); - return; - } - - if (currentStepIndex === 1) { - setCurrentStepIndex(1.5); - return; - } - - if (currentStepIndex === 1.5) { - setCurrentStepIndex(1.75); + setCurrentStep(ImportLedgerSteps.CONNECT_LEDGER); return; } - if (currentStepIndex === 1.75) { - setCurrentStepIndex(2); - return; - } - - setCurrentStepIndex((prevStepIndex) => prevStepIndex + 1); + setCurrentStep((prevStepIndex) => prevStepIndex + 1); }; const saveAddressToWallet = async ({ @@ -296,7 +211,7 @@ function ImportLedger(): JSX.Element { }; await addLedgerAccount(ledgerAccount); await ledgerDelay(1000); - setCurrentStepIndex(4); + setCurrentStep(ImportLedgerSteps.ADDRESS_ADDED); setIsButtonDisabled(false); return; } @@ -311,7 +226,7 @@ function ImportLedger(): JSX.Element { }; await updateLedgerAccounts(ledgerAccount); await ledgerDelay(1000); - setCurrentStepIndex(4); + setCurrentStep(ImportLedgerSteps.ADDRESS_ADDED); setIsButtonDisabled(false); return; } @@ -324,7 +239,7 @@ function ImportLedger(): JSX.Element { }; await updateLedgerAccounts(ledgerAccount); await ledgerDelay(1000); - setCurrentStepIndex(4); + setCurrentStep(ImportLedgerSteps.ADDRESS_ADDED); setIsButtonDisabled(false); } @@ -338,7 +253,7 @@ function ImportLedger(): JSX.Element { const handleClickMultipleAccounts = async () => { try { - setCurrentStepIndex(3); + setCurrentStep(ImportLedgerSteps.ADD_ADDRESS); setIsButtonDisabled(true); if (isBitcoinSelected) { const { btcCreds, ordinalsCreds, newAccountId } = await importBtcAccounts(true); @@ -378,7 +293,7 @@ function ImportLedger(): JSX.Element { ledgerAccountsList?.find((account) => account.masterPubKey === masterFingerPrint) ) { setIsButtonDisabled(false); - setCurrentStepIndex(2.5); + setCurrentStep(ImportLedgerSteps.ADD_MULTIPLE_ACCOUNTS); return; } handleClickNext(); @@ -432,12 +347,6 @@ function ImportLedger(): JSX.Element { } }; - const handleWindowClose = () => { - if (typeof window !== 'undefined') { - window.close(); - } - }; - const backToAssetSelection = () => { setBitcoinCredentials(undefined); setOrdinalsCredentials(undefined); @@ -449,13 +358,13 @@ function ImportLedger(): JSX.Element { if (isStxAddressRejected) { setIsStxAddressRejected(false); - setCurrentStepIndex(2); + setCurrentStep(ImportLedgerSteps.CONNECT_LEDGER); return; } setAccountId(0); setIsStacksSelected(false); - setCurrentStepIndex(0); + setCurrentStep(ImportLedgerSteps.START); }; const handleAssetSelect = (e: React.ChangeEvent) => { @@ -465,13 +374,15 @@ function ImportLedger(): JSX.Element { }; const validateAccountName = () => { - if (accountName.length > 20) { - setAccountNameError('Account name should not be longer than 20 characters.'); + const MAX_LENGTH = 20; + + if (accountName.length > MAX_LENGTH) { + setAccountNameError(t('LEDGER_ADD_ACCOUNT_NAME.ERRORS.MAX_LENGTH', { number: MAX_LENGTH })); return; } if (ledgerAccountsList.find((account) => account.accountName === accountName)) { - setAccountNameError('Account with the same name already exists. Please choose another name.'); + setAccountNameError(t('LEDGER_ADD_ACCOUNT_NAME.ERRORS.ALREADY_EXISTS')); return; } @@ -488,410 +399,68 @@ function ImportLedger(): JSX.Element { {transition((style) => ( <> - {currentStepIndex === 0 && ( - - - {t('LEDGER_IMPORT_1_TITLE')} - {t('LEDGER_IMPORT_1_SUBTITLE')} - - )} - {currentStepIndex === 1 && ( -
- - {t('LEDGER_IMPORT_2_TITLE')} - {t('LEDGER_IMPORT_2_SUBTITLE')} - - - - - - - {t('LEDGER_IMPORT_2_FOOTNOTE')} - -
- )} - {currentStepIndex === 1.5 && ( - - - {t('LEDGER_BEFORE_GETTING_STARTED.TITLE')} - - - {t('LEDGER_BEFORE_GETTING_STARTED.DESCRIPTION')} - - - - - - - )} - {currentStepIndex === 1.75 && ( - - - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TITLE')} - - {selectedLedgerLiveOption === 'using' ? ( - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_1')} -
- - {t('LEARN_MORE')} - -
-
- {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_2')}{' '} - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.PASSPHRASE_FOR_ORDINALS')} - - . -
-
- {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_3')} -
- ) : ( - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_1')}{' '} - - {t('LEARN_MORE')} - -
-
- {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_2')}{' '} - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.PASSPHRASE_FOR_ORDINALS')} - - . -
- )} - - setIsTogglerChecked(!isTogglerChecked)} - checked={isTogglerChecked} - uncheckedIcon={false} - checkedIcon={false} - /> - {selectedLedgerLiveOption === 'using' ? ( - - {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.UNDERSTAND_THE_RISKS')} - - ) : ( - - {t( - 'LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.UNDERSTAND_SHOULD_NOT_USE_LEDGER_LIVE', - )} - - )} - -
- )} - {currentStepIndex === 2 && ( - - )} - {currentStepIndex === 2.5 && ( - - {isBitcoinSelected - - {t( - isBitcoinSelected - ? 'LEDGER_ADD_ADDRESS.TITLE_BTC' - : 'LEDGER_ADD_ADDRESS.TITLE_STX', - )} - - - {t('LEDGER_ADD_ADDRESS.ALREADY_CONNECTED_WARNING')} - - - )} - {currentStepIndex === 3 && - (isConnectFailed || isBtcAddressRejected || isStxAddressRejected ? ( - - ) : ( - <> - - {isBitcoinSelected - - {t( - isBitcoinSelected - ? 'LEDGER_ADD_ADDRESS.TITLE_VERIFY_BTC' - : 'LEDGER_ADD_ADDRESS.TITLE_STX', - )} - - - - {t('LEDGER_ADD_ADDRESS.SUBTITLE')} - {isBitcoinSelected ? ( - - ) : ( - - )} - - {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} - {isBitcoinSelected && ( - - - - - )} - - ))} - {currentStepIndex === 3.5 && - (isConnectFailed || isOrdinalsAddressRejected ? ( - - ) : ( - <> - - ordinals - - {t('LEDGER_ADD_ADDRESS.TITLE_VERIFY_ORDINALS')} - - - - {t('LEDGER_ADD_ADDRESS.SUBTITLE')} - - - {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} - - - - - - ))} - {currentStepIndex === 4 && ( - - Success - - {t( - isBitcoinSelected - ? 'LEDGER_ADDRESS_ADDED.TITLE_BTC_ORDINALS' - : 'LEDGER_ADDRESS_ADDED.TITLE_STX', - )} - - - {t( - isBitcoinSelected - ? 'LEDGER_ADDRESS_ADDED.SUBTITLE' - : 'LEDGER_ADDRESS_ADDED.SUBTITLE_STX', - )} - - - )} - {currentStepIndex === 5 && ( - - - {t('LEDGER_ADD_ACCOUNT_NAME.TITLE')} - {t('LEDGER_ADD_ACCOUNT_NAME.SUBTITLE')} - - setAccountName(e.target.value)} - error={accountNameError} - /> - - )} - {currentStepIndex === 6 && ( - - - {t('LEDGER_IMPORT_END.TITLE')} - {t('LEDGER_IMPORT_END.SUBTITLE')} - - Wallet created - - )} +
- {currentStepIndex === 0 && ( - - )} - {currentStepIndex === 1 && ( - - )} - {currentStepIndex === 1.5 && ( - - )} - {currentStepIndex === 1.75 && ( - - )} - {currentStepIndex === 2 && ( - - )} - {currentStepIndex === 2.5 && ( - <> - - - - - - - - )} - {(currentStepIndex === 3 || currentStepIndex === 3.5) && - (isConnectFailed || - isBtcAddressRejected || - isOrdinalsAddressRejected || - isStxAddressRejected) && ( - - )} - {currentStepIndex === 4 && ( - - )} - {currentStepIndex === 5 && ( - - )} - {currentStepIndex === 6 && ( - - )} + ))} diff --git a/src/app/screens/ledger/importLedgerAccount/stepControls.tsx b/src/app/screens/ledger/importLedgerAccount/stepControls.tsx new file mode 100644 index 000000000..f553a6e18 --- /dev/null +++ b/src/app/screens/ledger/importLedgerAccount/stepControls.tsx @@ -0,0 +1,166 @@ +import styled from 'styled-components'; +import ActionButton from '@components/button'; +import { useTranslation } from 'react-i18next'; +import { ImportLedgerSteps } from './types'; + +const ButtonContainer = styled.div((props) => ({ + marginLeft: 3, + marginRight: 3, + marginTop: props.theme.spacing(4), + width: '100%', +})); + +interface Props { + isBitcoinSelected: boolean; + isStacksSelected: boolean; + isTogglerChecked: boolean; + isButtonDisabled: boolean; + currentStep: ImportLedgerSteps; + selectedLedgerLiveOption: any; + checkDeviceConnection: () => void; + handleClickNext: () => void; + handleClickMultipleAccounts: () => void; + backToAssetSelection: () => void; + updateAccountName: () => void; + errors: { + isConnectFailed: boolean; + isBtcAddressRejected: boolean; + isOrdinalsAddressRejected: boolean; + isStxAddressRejected: boolean; + accountNameError?: string; + }; +} + +function StepControls({ + isBitcoinSelected, + isStacksSelected, + isTogglerChecked, + isButtonDisabled, + currentStep, + selectedLedgerLiveOption, + checkDeviceConnection, + handleClickNext, + handleClickMultipleAccounts, + backToAssetSelection, + updateAccountName, + errors, +}: Props) { + const { t } = useTranslation('translation', { keyPrefix: 'LEDGER_IMPORT_SCREEN' }); + const { + isConnectFailed, + isBtcAddressRejected, + isOrdinalsAddressRejected, + isStxAddressRejected, + accountNameError, + } = errors; + + const handleWindowClose = () => { + if (typeof window !== 'undefined') { + window.close(); + } + }; + + switch (currentStep) { + case ImportLedgerSteps.START: + return ; + case ImportLedgerSteps.SELECT_ASSET: + return ( + + ); + case ImportLedgerSteps.BEFORE_START: + return ( + + ); + case ImportLedgerSteps.IMPORTANT_WARNING: + return ( + + ); + case ImportLedgerSteps.CONNECT_LEDGER: + return ( + + ); + case ImportLedgerSteps.ADD_MULTIPLE_ACCOUNTS: + return ( + <> + + + + + + + + ); + case ImportLedgerSteps.ADD_ADDRESS: + case ImportLedgerSteps.ADD_ORDINALS_ADDRESS: + if ( + isConnectFailed || + isBtcAddressRejected || + isOrdinalsAddressRejected || + isStxAddressRejected + ) { + return ( + + ); + } + break; + case ImportLedgerSteps.ADDRESS_ADDED: + return ; + case ImportLedgerSteps.ADD_ACCOUNT_NAME: + return ( + + ); + case ImportLedgerSteps.IMPORT_END: + return ( + + ); + default: + return null; + } +} + +export default StepControls; diff --git a/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts b/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts new file mode 100644 index 000000000..2630936d1 --- /dev/null +++ b/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts @@ -0,0 +1,286 @@ +import styled from 'styled-components'; +import Switch from 'react-switch'; + +export const ImportStartImage = styled.img((props) => ({ + marginLeft: props.theme.spacing(0), +})); + +export const ImportStartContainer = styled.div({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + maxWidth: '328px', +}); + +export const ImportBeforeStartContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + maxWidth: '328px', + paddingTop: props.theme.spacing(16), +})); + +export const ImportStartTitle = styled.h1((props) => ({ + ...props.theme.headline_s, + marginTop: props.theme.spacing(40), + textAlign: 'center', +})); +export const ImportStartText = styled.p((props) => ({ + ...props.theme.body_m, + textAlign: 'center', + marginTop: props.theme.spacing(6), + color: props.theme.colors.white[200], +})); + +export const ImportBeforeStartTitle = styled.h1((props) => ({ + ...props.theme.headline_s, + marginTop: props.theme.spacing(5), + textAlign: 'left', + alignSelf: 'flex-start', +})); +export const ImportBeforeStartText = styled.p((props) => ({ + ...props.theme.body_m, + textAlign: 'left', + marginTop: props.theme.spacing(6), + color: props.theme.colors.white[200], +})); + +export const ImportCardContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + gap: props.theme.spacing(6), +})); + +export const SelectAssetTextContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(20), + marginBottom: props.theme.spacing(16), + display: 'flex', + flexDirection: 'column', + gap: props.theme.spacing(6), +})); + +export const SelectAssetTitle = styled.h1((props) => ({ + ...props.theme.headline_s, +})); + +export const SelectAssetText = styled.p<{ + centered?: boolean; +}>((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[200], + textAlign: props.centered ? 'center' : 'left', +})); + +export const SelectAssetFootNote = styled.p((props) => ({ + ...props.theme.body_xs, + color: props.theme.colors.white[200], + marginTop: props.theme.spacing(6), +})); + +export const AddAddressHeaderContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: props.theme.spacing(8), + marginTop: props.theme.spacing(20), + marginBottom: props.theme.spacing(8), +})); + +export const CreateAnotherAccountContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: props.theme.spacing(8), + paddingTop: props.theme.spacing(90), + marginBottom: props.theme.spacing(16), +})); + +export const AddAddressDetailsContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + gap: props.theme.spacing(20), +})); + +export const AddressAddedContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + margin: auto; + text-align: center; + gap: 8px; + > :first-child { + margin-bottom: 26px; + } +`; + +export const AddAccountNameContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(20), + width: '100%', + display: 'flex', + flexDirection: 'column', + gap: props.theme.spacing(6), +})); + +export const AddAccountNameTitleContainer = styled.div((props) => ({ + width: '100%', + display: 'flex', + flexDirection: 'column', + gap: props.theme.spacing(4), + marginBottom: props.theme.spacing(22), +})); + +export const CreateMultipleAccountsText = styled.h3((props) => ({ + ...props.theme.body_l, + textAlign: 'center', +})); + +export const EndScreenContainer = styled.div({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +}); + +export const EndScreenTextContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + textAlign: 'center', + gap: props.theme.spacing(6), + marginBottom: props.theme.spacing(20), +})); + +export const AssetSelectionButton = styled.button((props) => ({ + position: 'absolute', + left: props.theme.spacing(105), + top: props.theme.spacing(60), + backgroundColor: 'transparent', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + gap: props.theme.spacing(3), +})); + +export const AssetSelectionButtonText = styled.p((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[0], +})); + +export const ConfirmationText = styled.p((props) => ({ + fontSize: '0.875rem', + fontWeight: 500, + textAlign: 'center', + marginTop: props.theme.spacing(50), +})); + +export const ConfirmationStepsContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + marginTop: props.theme.spacing(12), +})); + +export const OptionsContainer = styled.div((props) => ({ + width: '100%', + marginTop: props.theme.spacing(16), +})); + +interface OptionProps { + selected?: boolean; +} +export const Option = styled.div((props) => ({ + width: '100%', + backgroundColor: '#21253C', + padding: props.theme.spacing(8), + paddingTop: props.theme.spacing(7), + paddingBottom: props.theme.spacing(7), + borderRadius: props.theme.radius(2), + fontSize: '0.75rem', + marginBottom: props.theme.spacing(6), + border: `1px solid ${props.selected ? 'rgba(115, 131, 255, 0.40)' : 'transparent'}`, + cursor: 'pointer', + userSelect: 'none', + display: 'flex', + alignItems: 'center', + transition: 'border 0.2s ease', +})); + +export const OptionIcon = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 15, + height: 15, + borderRadius: '50%', + border: `1px solid ${props.theme.colors.white[0]}`, + marginRight: props.theme.spacing(10), + flex: 'none', + '&::after': { + content: '""', + display: props.selected ? 'block' : 'none', + width: 8, + height: 8, + borderRadius: 100, + backgroundColor: props.theme.colors.white[0], + }, +})); + +export const ConfirmationStep = styled.div<{ + isCompleted: boolean; +}>((props) => ({ + width: 32, + height: 4, + backgroundColor: props.isCompleted ? props.theme.colors.white[0] : props.theme.colors.white[900], + borderRadius: props.theme.radius(1), + transition: 'background-color 0.2s ease', + ':first-child': { + marginRight: props.theme.spacing(4), + }, +})); + +export const CustomSwitch = styled(Switch)` + .react-switch-handle { + background-color: ${({ checked }) => + checked ? '#FFFFFF' : 'rgba(255, 255, 255, 0.2)'} !important; + border: ${({ checked }) => (checked ? '' : '4px solid rgba(255, 255, 255, 0.2)')} !important; + } +`; + +export const TogglerContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'center', + marginTop: props.theme.spacing(18), +})); + +export const TogglerText = styled.p((props) => ({ + marginLeft: props.theme.spacing(8), + fontWeight: 500, + fontSize: '0.875rem', + lineHeight: '140%', +})); + +export const CustomLink = styled.a((props) => ({ + color: props.theme.colors.orange_main, +})); + +export const WarningIcon = styled.img({ + width: 32, + height: 32, + alignSelf: 'flex-start', +}); + +export const LedgerFailViewContainer = styled.div((props) => ({ + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), + margin: 'auto', +})); + +export const LedgerFailButtonsContainer = styled.div((props) => ({ + width: '100%', + marginTop: props.theme.spacing(25), +})); + +export const ActionButtonContainer = styled.div((props) => ({ + '&:not(:last-of-type)': { + marginBottom: props.theme.spacing(8), + }, +})); diff --git a/src/app/screens/ledger/importLedgerAccount/steps/index.tsx b/src/app/screens/ledger/importLedgerAccount/steps/index.tsx new file mode 100644 index 000000000..2aca4d4a0 --- /dev/null +++ b/src/app/screens/ledger/importLedgerAccount/steps/index.tsx @@ -0,0 +1,444 @@ +import LedgerAddressComponent from '@components/ledger/ledgerAddressComponent'; +import LedgerInput from '@components/ledger/ledgerInput'; +import warningIcon from '@assets/img/Warning_red.svg'; +import { useTranslation } from 'react-i18next'; +import ledgerImportStartIcon from '@assets/img/ledger/ledger_import_start.svg'; +import btcOrdinalsIcon from '@assets/img/ledger/btc_ordinals_icon.svg'; +import btcIcon from '@assets/img/ledger/btc_icon.svg'; +import ordinalsIcon from '@assets/img/ledger/ordinals_icon.svg'; +import stxIcon from '@assets/img/ledger/stx_icon.svg'; +import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.svg'; +import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; +import checkCircleIcon from '@assets/img/ledger/check_circle.svg'; +import ledgerAccountSwitchIcon from '@assets/img/ledger/account_switch.svg'; +import LedgerFailView from '@components/ledger/failLedgerView'; +import LedgerAssetSelectCard from '@components/ledger/ledgerAssetSelectCard'; +import { useTheme } from 'styled-components'; +import LedgerConnectionView from '../../../../components/ledger/connectLedgerView'; +import { ImportLedgerSteps, LedgerLiveOptions } from '../types'; + +import { + AddAccountNameContainer, + AddAccountNameTitleContainer, + AddAddressDetailsContainer, + AddAddressHeaderContainer, + AddressAddedContainer, + ConfirmationStep, + ConfirmationStepsContainer, + ConfirmationText, + CreateAnotherAccountContainer, + CreateMultipleAccountsText, + CustomLink, + CustomSwitch, + EndScreenContainer, + EndScreenTextContainer, + ImportBeforeStartContainer, + ImportBeforeStartText, + ImportBeforeStartTitle, + ImportCardContainer, + ImportStartContainer, + ImportStartImage, + ImportStartText, + ImportStartTitle, + Option, + OptionIcon, + OptionsContainer, + SelectAssetFootNote, + SelectAssetText, + SelectAssetTextContainer, + SelectAssetTitle, + TogglerContainer, + TogglerText, + WarningIcon, +} from './index.styled'; + +const LINK_TO_LEDGER_ACCOUNT_ISSUE_GUIDE = + 'https://support.xverse.app/hc/en-us/articles/17901278165773'; +const LINK_TO_LEDGER_PASSPHRASE_GUIDE = + 'https://support.xverse.app/hc/en-us/articles/17901278165773'; + +interface Props { + isConnectSuccess: boolean; + isBitcoinSelected: boolean; + isStacksSelected: boolean; + isTogglerChecked: boolean; + isBtcAddressConfirmed: boolean; + isOrdinalsAddressConfirmed: boolean; + currentStep: ImportLedgerSteps; + accountName: string; + accountId: number; + selectedLedgerLiveOption: LedgerLiveOptions | null; + handleAssetSelect: (event: React.ChangeEvent) => void; + setSelectedLedgerLiveOption: (option: LedgerLiveOptions) => void; + setIsTogglerChecked: (checked: boolean) => void; + setAccountName: (name: string) => void; + creds: { + bitcoinCredentials: any; + ordinalsCredentials: any; + stacksCredentials: any; + }; + errors: { + isConnectFailed: boolean; + isBtcAddressRejected: boolean; + isOrdinalsAddressRejected: boolean; + isStxAddressRejected: boolean; + accountNameError?: string; + }; +} + +function Steps({ + isConnectSuccess, + isBitcoinSelected, + isStacksSelected, + isTogglerChecked, + isBtcAddressConfirmed, + isOrdinalsAddressConfirmed, + currentStep, + accountName, + accountId, + selectedLedgerLiveOption, + handleAssetSelect, + setSelectedLedgerLiveOption, + setIsTogglerChecked, + setAccountName, + creds, + errors, +}: Props) { + const { t } = useTranslation('translation', { keyPrefix: 'LEDGER_IMPORT_SCREEN' }); + const theme = useTheme(); + const { bitcoinCredentials, ordinalsCredentials, stacksCredentials } = creds; + const { + isConnectFailed, + isBtcAddressRejected, + isOrdinalsAddressRejected, + isStxAddressRejected, + accountNameError, + } = errors; + + switch (currentStep) { + case ImportLedgerSteps.START: + return ( + + + {t('LEDGER_IMPORT_1_TITLE')} + {t('LEDGER_IMPORT_1_SUBTITLE')} + + ); + case ImportLedgerSteps.SELECT_ASSET: + return ( +
+ + {t('LEDGER_IMPORT_2_TITLE')} + {t('LEDGER_IMPORT_2_SUBTITLE')} + + + + + + + {t('LEDGER_IMPORT_2_FOOTNOTE')} + +
+ ); + case ImportLedgerSteps.BEFORE_START: + return ( + + + {t('LEDGER_BEFORE_GETTING_STARTED.TITLE')} + + + {t('LEDGER_BEFORE_GETTING_STARTED.DESCRIPTION')} + + + + + + + ); + case ImportLedgerSteps.IMPORTANT_WARNING: + return ( + + + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TITLE')} + + {selectedLedgerLiveOption === LedgerLiveOptions.USING ? ( + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_1')} +
+ + {t('LEARN_MORE')} + +
+
+ {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_2')}{' '} + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.PASSPHRASE_FOR_ORDINALS')} + + . +
+
+ {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_3')} +
+ ) : ( + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_1')}{' '} + + {t('LEARN_MORE')} + +
+
+ {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.TEXT_2')}{' '} + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.PASSPHRASE_FOR_ORDINALS')} + + . +
+ )} + + setIsTogglerChecked(!isTogglerChecked)} + checked={isTogglerChecked} + uncheckedIcon={false} + checkedIcon={false} + /> + {selectedLedgerLiveOption === LedgerLiveOptions.USING ? ( + + {t('LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.UNDERSTAND_THE_RISKS')} + + ) : ( + + {t( + 'LEDGER_BEFORE_GETTING_STARTED.IMPORTANT_WARNING.UNDERSTAND_SHOULD_NOT_USE_LEDGER_LIVE', + )} + + )} + +
+ ); + case ImportLedgerSteps.CONNECT_LEDGER: + return ( + + ); + case ImportLedgerSteps.ADD_MULTIPLE_ACCOUNTS: + return ( + + {isBitcoinSelected + + {t(isBitcoinSelected ? 'LEDGER_ADD_ADDRESS.TITLE_BTC' : 'LEDGER_ADD_ADDRESS.TITLE_STX')} + + + {t('LEDGER_ADD_ADDRESS.ALREADY_CONNECTED_WARNING')} + + + ); + case ImportLedgerSteps.ADD_ADDRESS: + if (isConnectFailed || isBtcAddressRejected || isStxAddressRejected) { + return ( + + ); + } + + return ( + <> + + {isBitcoinSelected + + {t( + isBitcoinSelected + ? 'LEDGER_ADD_ADDRESS.TITLE_VERIFY_BTC' + : 'LEDGER_ADD_ADDRESS.TITLE_STX', + )} + + + + {t('LEDGER_ADD_ADDRESS.SUBTITLE')} + {isBitcoinSelected ? ( + + ) : ( + + )} + + {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} + {isBitcoinSelected && ( + + + + + )} + + ); + case ImportLedgerSteps.ADD_ORDINALS_ADDRESS: + if (isConnectFailed || isOrdinalsAddressRejected) { + return ( + + ); + } + + return ( + <> + + ordinals + {t('LEDGER_ADD_ADDRESS.TITLE_VERIFY_ORDINALS')} + + + {t('LEDGER_ADD_ADDRESS.SUBTITLE')} + + + {t('LEDGER_ADD_ADDRESS.CONFIRM_TO_CONTINUE')} + + + + + + ); + case ImportLedgerSteps.ADDRESS_ADDED: + return ( + + Success + + {t( + isBitcoinSelected + ? 'LEDGER_ADDRESS_ADDED.TITLE_BTC_ORDINALS' + : 'LEDGER_ADDRESS_ADDED.TITLE_STX', + )} + + + {t( + isBitcoinSelected + ? 'LEDGER_ADDRESS_ADDED.SUBTITLE' + : 'LEDGER_ADDRESS_ADDED.SUBTITLE_STX', + )} + + + ); + case ImportLedgerSteps.ADD_ACCOUNT_NAME: + return ( + + + {t('LEDGER_ADD_ACCOUNT_NAME.TITLE')} + {t('LEDGER_ADD_ACCOUNT_NAME.SUBTITLE')} + + setAccountName(e.target.value)} + error={accountNameError} + /> + + ); + case ImportLedgerSteps.IMPORT_END: + return ( + + + {t('LEDGER_IMPORT_END.TITLE')} + {t('LEDGER_IMPORT_END.SUBTITLE')} + + Wallet created + + ); + default: + return null; + } +} + +export default Steps; diff --git a/src/app/screens/ledger/importLedgerAccount/types.ts b/src/app/screens/ledger/importLedgerAccount/types.ts new file mode 100644 index 000000000..e4a75029e --- /dev/null +++ b/src/app/screens/ledger/importLedgerAccount/types.ts @@ -0,0 +1,18 @@ +export enum ImportLedgerSteps { + START = 0, + SELECT_ASSET = 1, + BEFORE_START = 2, + IMPORTANT_WARNING = 3, + CONNECT_LEDGER = 4, + ADD_MULTIPLE_ACCOUNTS = 4.5, + ADD_ADDRESS = 5, + ADD_ORDINALS_ADDRESS = 5.5, + ADDRESS_ADDED = 6, + ADD_ACCOUNT_NAME = 7, + IMPORT_END = 8, +} + +export enum LedgerLiveOptions { + USING = 'using', + NOT_USING = 'not using', +} diff --git a/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts b/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts new file mode 100644 index 000000000..9315ffe30 --- /dev/null +++ b/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts @@ -0,0 +1,114 @@ +import styled from 'styled-components'; +import { animated } from '@react-spring/web'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + &::-webkit-scrollbar { + display: none; + } +`; + +export const OnBoardingContentContainer = styled(animated.div)((props) => ({ + display: 'flex', + width: '100%', + flexDirection: 'column', + flex: 1, + justifyContent: props.className === 'center' ? 'center' : 'none', + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), +})); + +export const OnBoardingActionsContainer = styled.div((props) => ({ + width: '100%', + display: 'flex', + alignItems: 'flex-start', + justifyContent: 'space-between', + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), + marginBottom: props.theme.spacing(30), +})); + +export const SelectAssetTitle = styled.h1((props) => ({ + ...props.theme.headline_s, +})); + +export const SelectAssetText = styled.p((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[200], + textAlign: 'center', +})); + +export const AddAddressHeaderContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: props.theme.spacing(8), + marginTop: props.theme.spacing(20), + marginBottom: props.theme.spacing(8), +})); + +export const AddAddressDetailsContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + gap: props.theme.spacing(20), +})); + +export const AddressAddedContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 8px; + > :first-child { + margin-bottom: 26px; + } +`; + +export const CopyContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: 328, + justifyContent: 'center', + marginTop: props.theme.spacing(11), +})); + +export const QRCodeContainer = styled.div((props) => ({ + display: 'flex', + aspectRatio: 1, + backgroundColor: props.theme.colors.white['0'], + justifyContent: 'center', + alignItems: 'center', + borderRadius: props.theme.radius(1), + padding: props.theme.spacing(5), + marginBottom: props.theme.spacing(12), +})); + +export const InfoAlertContainer = styled.div({ + width: '100%', +}); + +export const ActionButtonsContainer = styled.div({ + width: '100%', +}); + +export const ActionButtonContainer = styled.div((props) => ({ + '&:not(:last-of-type)': { + marginBottom: props.theme.spacing(8), + }, +})); + +export const LedgerFailViewContainer = styled.div((props) => ({ + paddingLeft: props.theme.spacing(8), + paddingRight: props.theme.spacing(8), + margin: 'auto', +})); + +export const LedgerFailButtonsContainer = styled.div((props) => ({ + width: '100%', + marginTop: props.theme.spacing(25), +})); diff --git a/src/app/screens/ledger/verifyLedgerAccountAddress/index.tsx b/src/app/screens/ledger/verifyLedgerAccountAddress/index.tsx index f98088383..4049f628a 100644 --- a/src/app/screens/ledger/verifyLedgerAccountAddress/index.tsx +++ b/src/app/screens/ledger/verifyLedgerAccountAddress/index.tsx @@ -1,7 +1,6 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import { animated, useTransition } from '@react-spring/web'; +import { useTransition } from '@react-spring/web'; import Transport from '@ledgerhq/hw-transport-webusb'; import ActionButton from '@components/button'; import { @@ -24,123 +23,36 @@ import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.s import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; import checkCircleIcon from '@assets/img/ledger/check_circle.svg'; import LedgerFailView from '@components/ledger/failLedgerView'; +import { DEFAULT_TRANSITION_OPTIONS } from '@utils/constants'; import useResetUserFlow from '@hooks/useResetUserFlow'; import LedgerConnectionView from '../../../components/ledger/connectLedgerView'; -const Container = styled.div` - display: flex; - flex-direction: column; - align-items: center; - flex: 1; - &::-webkit-scrollbar { - display: none; - } -`; - -const OnBoardingContentContainer = styled(animated.div)((props) => ({ - display: 'flex', - width: '100%', - flexDirection: 'column', - flex: 1, - justifyContent: props.className === 'center' ? 'center' : 'none', - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), -})); - -const OnBoardingActionsContainer = styled.div((props) => ({ - width: '100%', - display: 'flex', - alignItems: 'flex-start', - justifyContent: 'space-between', - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - marginBottom: props.theme.spacing(30), -})); - -const SelectAssetTitle = styled.h1((props) => ({ - ...props.theme.headline_s, -})); - -const SelectAssetText = styled.p((props) => ({ - ...props.theme.body_m, - color: props.theme.colors.white[200], - textAlign: 'center', -})); - -const AddAddressHeaderContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - gap: props.theme.spacing(8), - marginTop: props.theme.spacing(20), - marginBottom: props.theme.spacing(8), -})); - -const AddAddressDetailsContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'flex-start', - gap: props.theme.spacing(20), -})); - -const AddressAddedContainer = styled.div` - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - gap: 8px; - > :first-child { - margin-bottom: 26px; - } -`; - -const CopyContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - width: 328, - justifyContent: 'center', - marginTop: props.theme.spacing(11), -})); - -const QRCodeContainer = styled.div((props) => ({ - display: 'flex', - aspectRatio: 1, - backgroundColor: props.theme.colors.white['0'], - justifyContent: 'center', - alignItems: 'center', - borderRadius: 8, - padding: props.theme.spacing(5), - marginBottom: props.theme.spacing(12), -})); - -const InfoAlertContainer = styled.div({ - width: '100%', -}); - -const ActionButtonsContainer = styled.div({ - width: '100%', -}); - -const ActionButtonContainer = styled.div((props) => ({ - '&:not(:last-of-type)': { - marginBottom: props.theme.spacing(8), - }, -})); - -const LedgerFailViewContainer = styled.div((props) => ({ - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - margin: 'auto', -})); - -const LedgerFailButtonsContainer = styled.div((props) => ({ - width: '100%', - marginTop: props.theme.spacing(25), -})); +import { + Container, + OnBoardingContentContainer, + ActionButtonsContainer, + ActionButtonContainer, + AddAddressHeaderContainer, + SelectAssetTitle, + AddAddressDetailsContainer, + SelectAssetText, + QRCodeContainer, + CopyContainer, + InfoAlertContainer, + AddressAddedContainer, + OnBoardingActionsContainer, + LedgerFailViewContainer, + LedgerFailButtonsContainer, +} from './index.styled'; + +enum Steps { + ConnectLedger = 0, + VerifyAddress = 1, + AddressVerified = 2, +} function VerifyLedger(): JSX.Element { - const [currentStepIndex, setCurrentStepIndex] = useState(0); + const [currentStepIndex, setCurrentStepIndex] = useState(Steps.ConnectLedger); const [isButtonDisabled, setIsButtonDisabled] = useState(false); const [isConnectSuccess, setIsConnectSuccess] = useState(false); const [isConnectFailed, setIsConnectFailed] = useState(false); @@ -154,16 +66,7 @@ function VerifyLedger(): JSX.Element { const currency = params.get('currency') ?? ''; const { t } = useTranslation('translation', { keyPrefix: 'LEDGER_VERIFY_SCREEN' }); const { network } = useWalletSelector(); - const transition = useTransition(currentStepIndex, { - from: { - x: 24, - opacity: 0, - }, - enter: { - x: 0, - opacity: 1, - }, - }); + const transition = useTransition(currentStepIndex, DEFAULT_TRANSITION_OPTIONS); const isBitcoinSelected = currency === 'BTC'; const isOrdinalSelected = currency === 'ORD' || currency === 'brc-20'; @@ -197,15 +100,15 @@ function VerifyLedger(): JSX.Element { if (isBitcoinSelected) { try { - await importNativeSegwitAccountFromLedger( + await importNativeSegwitAccountFromLedger({ transport, - network.type, - 0, + network: network.type, + accountIndex: 0, addressIndex, showAddress, - ); + }); setIsButtonDisabled(false); - setCurrentStepIndex(2); + setCurrentStepIndex(Steps.AddressVerified); } catch (err: any) { if (err.statusCode === 27013) { setIsBtcAddressRejected(true); @@ -218,9 +121,15 @@ function VerifyLedger(): JSX.Element { } } else { try { - await importTaprootAccountFromLedger(transport, network.type, 0, addressIndex, showAddress); + await importTaprootAccountFromLedger({ + transport, + network: network.type, + accountIndex: 0, + addressIndex, + showAddress, + }); setIsButtonDisabled(false); - setCurrentStepIndex(2); + setCurrentStepIndex(Steps.AddressVerified); } catch (err: any) { if (err.statusCode === 27013) { setIsOrdinalsAddressRejected(true); @@ -241,9 +150,15 @@ function VerifyLedger(): JSX.Element { const addressIndex = selectedAccount?.deviceAccountIndex; try { - await importStacksAccountFromLedger(transport, network.type, 0, addressIndex, showAddress); + await importStacksAccountFromLedger({ + transport, + network: network.type, + accountIndex: 0, + addressIndex, + showAddress, + }); setIsButtonDisabled(false); - setCurrentStepIndex(2); + setCurrentStepIndex(Steps.AddressVerified); } catch (err: any) { console.error(err); setIsConnectFailed(true); @@ -299,7 +214,7 @@ function VerifyLedger(): JSX.Element { setIsBtcAddressRejected(false); setIsOrdinalsAddressRejected(false); - setCurrentStepIndex(0); + setCurrentStepIndex(Steps.ConnectLedger); }; const getTitle = () => { @@ -320,6 +235,156 @@ function VerifyLedger(): JSX.Element { ? 'STX_SUBTITLE_FAILED' : 'BTC_SUBTITLE_FAILED'; + const renderContent = () => { + switch (currentStepIndex) { + case Steps.ConnectLedger: + return ( + + ); + case Steps.VerifyAddress: + return isConnectFailed || isBtcAddressRejected || isOrdinalsAddressRejected ? ( + + ) : ( + <> + + {getTitle()} + + {isBitcoinSelected && t('TITLE_VERIFY_BTC')} + {isOrdinalSelected && t('TITLE_VERIFY_ORDINALS')} + {isStacksSelected && t('TITLE_VERIFY_STX')} + + + + {t('SUBTITLE_VERIFY')} + + + + + + + {isOrdinalSelected && ( + + + + )} + {isBitcoinSelected && ( + + + + )} + {isStacksSelected && ( + + + + )} + + + + + + ); + case Steps.AddressVerified: + return ( + + Success + + {isBitcoinSelected && t('BTC_TITLE_VERIFIED')} + {isOrdinalSelected && t('ORDINALS_TITLE_VERIFIED')} + {isStacksSelected && t('STACKS_TITLE_VERIFIED')} + + + ); + default: + return null; + } + }; + + const renderActionButton = () => { + switch (currentStepIndex) { + case Steps.ConnectLedger: + return ( + + ); + case Steps.VerifyAddress: + if (isConnectFailed || isBtcAddressRejected || isOrdinalsAddressRejected) { + return ( + + + + + + + + + ); + } + break; + case Steps.AddressVerified: + return ( + + + + + + + + + ); + default: + return null; + } + }; + if (mismatch) { return ( @@ -342,143 +407,16 @@ function VerifyLedger(): JSX.Element { {transition((style) => ( <> - {currentStepIndex === 0 && ( - - )} - {currentStepIndex === 1 && - (isConnectFailed || isBtcAddressRejected || isOrdinalsAddressRejected ? ( - - ) : ( - <> - - {getTitle()} - - {isBitcoinSelected && t('TITLE_VERIFY_BTC')} - {isOrdinalSelected && t('TITLE_VERIFY_ORDINALS')} - {isStacksSelected && t('TITLE_VERIFY_STX')} - - - - {t('SUBTITLE_VERIFY')} - - - - - - - {isOrdinalSelected && ( - - - - )} - {isBitcoinSelected && ( - - - - )} - {isStacksSelected && ( - - - - )} - - - - - - ))} - {currentStepIndex === 2 && ( - - Success - - {isBitcoinSelected && t('BTC_TITLE_VERIFIED')} - {isOrdinalSelected && t('ORDINALS_TITLE_VERIFIED')} - {isStacksSelected && t('STACKS_TITLE_VERIFIED')} - - - )} + {renderContent()} - - {currentStepIndex === 0 && ( - - )} - {currentStepIndex === 1 && - (isConnectFailed || isBtcAddressRejected || isOrdinalsAddressRejected) && ( - - - - - - - - - )} - {currentStepIndex === 2 && ( - - - - - - - - - )} - + {renderActionButton()} ))} diff --git a/src/app/screens/legalLinks/index.tsx b/src/app/screens/legalLinks/index.tsx index 945392239..349cc7a41 100644 --- a/src/app/screens/legalLinks/index.tsx +++ b/src/app/screens/legalLinks/index.tsx @@ -1,24 +1,31 @@ import LinkIcon from '@assets/img/linkIcon.svg'; +import ActionButton from '@components/button'; import Separator from '@components/separator'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { CustomSwitch } from '@screens/ledger/importLedgerAccount/index.styled'; import { PRIVACY_POLICY_LINK, TERMS_LINK } from '@utils/constants'; +import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import { saveIsTermsAccepted } from '@utils/localStorage'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useSearchParams } from 'react-router-dom'; -import styled from 'styled-components'; +import styled, { useTheme } from 'styled-components'; +import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; +import { useDispatch } from 'react-redux'; const Container = styled.div((props) => ({ flex: 1, display: 'flex', flexDirection: 'column', - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - paddingTop: props.theme.spacing(8), + padding: props.theme.spacing(8), + paddingTop: props.theme.spacing(28), + paddingBottom: props.theme.spacing(28), + justifyContent: 'space-between', })); const Title = styled.h1((props) => ({ ...props.theme.bold_tile_text, color: props.theme.colors.white['0'], - marginTop: props.theme.spacing(20), })); const SubTitle = styled.h1((props) => ({ @@ -27,7 +34,11 @@ const SubTitle = styled.h1((props) => ({ marginTop: props.theme.spacing(8), })); -const ActionButton = styled.a((props) => ({ +const LinksContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(20), +})); + +const Link = styled.a((props) => ({ ...props.theme.body_m, display: 'flex', justifyContent: 'space-between', @@ -35,7 +46,8 @@ const ActionButton = styled.a((props) => ({ color: props.theme.colors.white['0'], })); -const CustomisedActionButton = styled(ActionButton)` +const CustomizedLink = styled(Link)` + transition: opacity 0.1s ease; :hover { opacity: 0.8; } @@ -44,30 +56,32 @@ const CustomisedActionButton = styled(ActionButton)` } `; -const ActionButtonsContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(20), -})); - -const AcceptButton = styled.button((props) => ({ - ...props.theme.body_bold_m, +const SwitchContainer = styled.div((props) => ({ display: 'flex', - color: props.theme.colors.background.elevation0, + justifyContent: 'space-between', alignItems: 'center', - justifyContent: 'center', - marginTop: 'auto', - marginBottom: props.theme.spacing(32), - backgroundColor: props.theme.colors.action.classic, - borderRadius: props.theme.radius(1), - height: 44, - width: '100%', + marginTop: props.theme.spacing(8), + fontSize: '0.875rem', })); function LegalLinks() { const { t } = useTranslation('translation', { keyPrefix: 'LEGAL_SCREEN' }); const navigate = useNavigate(); + const dispatch = useDispatch(); + const { selectedAccount } = useWalletSelector(); const [searchParams] = useSearchParams(); + const theme = useTheme(); + const [isToggleEnabled, setIsToggleEnabled] = useState(false); + + const handleSwitchToggle = () => setIsToggleEnabled((prevEnabledState) => !prevEnabledState); const handleLegalAccept = () => { + if (isToggleEnabled) { + optInMixPanel(selectedAccount?.masterPubKey); + } else { + optOutMixPanel(); + } + dispatch(changeShowDataCollectionAlertAction(false)); saveIsTermsAccepted(true); const isRestore = !!searchParams.get('restore'); if (isRestore) { @@ -78,20 +92,34 @@ function LegalLinks() { }; return ( - {t('SCREEN_TITLE')} - {t('SCREEN_SUBTITLE')} - - - {t('TERMS_SERVICES_LINK_BUTTON')} - terms - - - - {t('PRIVACY_POLICY_LINK_BUTTON')} - privacy - - - {t('ACCEPT_LEGAL_BUTTON')} +
+ {t('SCREEN_TITLE')} + {t('SCREEN_SUBTITLE')} + + + {t('TERMS_SERVICES_LINK_BUTTON')} + terms + + + + {t('PRIVACY_POLICY_LINK_BUTTON')} + privacy + + + +
{t('AUTHORIZE_DATA_COLLECTION')}
+ +
+
+
+
); } diff --git a/src/app/screens/onboarding/index.tsx b/src/app/screens/onboarding/index.tsx index 9f7773ae2..f061f0aa4 100644 --- a/src/app/screens/onboarding/index.tsx +++ b/src/app/screens/onboarding/index.tsx @@ -4,6 +4,7 @@ import onboarding3 from '@assets/img/onboarding/onboarding3.png'; import ActionButton from '@components/button'; import Steps from '@components/steps'; import { animated, useTransition } from '@react-spring/web'; +import { DEFAULT_TRANSITION_OPTIONS } from '@utils/constants'; import { getIsTermsAccepted, saveHasFinishedOnboarding } from '@utils/localStorage'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -65,16 +66,7 @@ function Onboarding(): JSX.Element { const [currentStepIndex, setCurrentStepIndex] = useState(0); const { t } = useTranslation('translation', { keyPrefix: 'ONBOARDING_SCREEN' }); const navigate = useNavigate(); - const transition = useTransition(currentStepIndex, { - from: { - x: 24, - opacity: 0, - }, - enter: { - x: 0, - opacity: 1, - }, - }); + const transition = useTransition(currentStepIndex, DEFAULT_TRANSITION_OPTIONS); const [searchParams] = useSearchParams(); const onboardingViews = [ diff --git a/src/app/screens/settings/index.tsx b/src/app/screens/settings/index.tsx index 56e61de3b..5752e2627 100644 --- a/src/app/screens/settings/index.tsx +++ b/src/app/screens/settings/index.tsx @@ -79,6 +79,10 @@ function Setting() { navigate('/fiat-currency'); }; + const openPrivacyPreferencesScreen = () => { + navigate('/privacy-preferences'); + }; + const openChangeNetworkScreen = () => { navigate('/change-network'); }; @@ -173,6 +177,12 @@ function Setting() { textDetail={fiatCurrency} showDivider /> + {!isLedgerAccount(selectedAccount) && ( ({ + display: 'flex', + flexDirection: 'column', + flex: 1, + overflowY: 'auto', + padding: props.theme.spacing(8), + fontSize: '0.875rem', + color: props.theme.colors.white['200'], + '&::-webkit-scrollbar': { + display: 'none', + }, +})); + +const TextContiner = styled.div({ + lineHeight: '140%', +}); + +const SwitchContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginTop: props.theme.spacing(16), + fontWeight: 500, +})); + +const CustomSwitch = styled(Switch)` + .react-switch-handle { + background-color: ${({ checked }) => + checked ? '#FFFFFF' : 'rgba(255, 255, 255, 0.2)'} !important; + border: ${({ checked }) => (checked ? '' : '4px solid rgba(255, 255, 255, 0.2)')} !important; + } +`; + +function PrivacyPreferencesScreen() { + const { t } = useTranslation('translation', { keyPrefix: 'SETTING_SCREEN' }); + const { selectedAccount } = useWalletSelector(); + const navigate = useNavigate(); + const theme = useTheme(); + const [isEnabled, setIsEnabled] = useState(false); + + const handleBackButtonClick = () => { + navigate('/settings'); + }; + + const handleSwitchChange = (checked: boolean) => { + setIsEnabled(checked); + + if (checked) { + optInMixPanel(selectedAccount?.masterPubKey); + } else { + optOutMixPanel(); + } + }; + + const checkMixpanelTrackingStatus = async () => { + const hasOptedIn = await hasOptedInMixPanelTracking(); + + if (hasOptedIn) { + setIsEnabled(true); + } + }; + + useEffect(() => { + checkMixpanelTrackingStatus(); + }, []); + + return ( + <> + + + {t('PRIVACY_PREFERENCES.DESCRIPTION')} + +
{t('PRIVACY_PREFERENCES.AUTHORIZE_DATA_COLLECTION')}
+ +
+
+ + + ); +} + +export default PrivacyPreferencesScreen; diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index 6df54b18b..f3fc59703 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -96,7 +96,7 @@ const SuccessActionsContainer = styled.div((props) => ({ })); function SignPsbtRequest() { - const { btcAddress, ordinalsAddress, selectedAccount, network, btcFiatRate, ledgerAccountsList } = + const { btcAddress, ordinalsAddress, selectedAccount, network, btcFiatRate } = useWalletSelector(); const navigate = useNavigate(); const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' }); @@ -188,7 +188,7 @@ function SignPsbtRequest() { const onSignPsbtConfirmed = async () => { try { if (isLedgerAccount(selectedAccount)) { - setIsModalVisible(true); + // setIsModalVisible(true); return; } @@ -232,20 +232,21 @@ function SignPsbtRequest() { }; const handleLedgerPsbtSigning = async (transport: TransportType) => { - const accountId = selectedAccount?.deviceAccountIndex; + const addressIndex = selectedAccount?.deviceAccountIndex; + const { inputsToSign, psbtBase64, broadcast } = payload; - if (accountId === undefined) { + if (addressIndex === undefined) { throw new Error('Account not found'); } - const signingResponse = await signIncomingSingleSigPSBT( + const signingResponse = await signIncomingSingleSigPSBT({ transport, - network.type, - accountId, - payload.inputsToSign, - payload.psbtBase64, - payload.broadcast, - ); + network: network.type, + addressIndex, + inputsToSign, + psbtBase64, + finalize: broadcast, + }); let txId: string = ''; if (request.payload.broadcast) { @@ -346,45 +347,55 @@ function SignPsbtRequest() { ) : ( <> - - {t('REVIEW_TRANSACTION')} - {!payload.broadcast && } - {ordinalInfoData && - ordinalInfoData.map((ordinalData) => ( - - ))} - - - - - {payload.broadcast ? ( - + + + ) : ( + + {t('REVIEW_TRANSACTION')} + {!payload.broadcast && ( + + )} + {ordinalInfoData && + ordinalInfoData.map((ordinalData) => ( + + ))} + + - ) : null} - {hasOutputScript && } - + + + {payload.broadcast ? ( + + ) : null} + {hasOutputScript && } +
+ )} @@ -394,6 +405,7 @@ function SignPsbtRequest() { text={t('CONFIRM')} onPress={onSignPsbtConfirmed} processing={isSigning} + disabled={isLedgerAccount(selectedAccount)} /> diff --git a/src/app/screens/signatureRequest/index.tsx b/src/app/screens/signatureRequest/index.tsx index 624987e49..0a7628fdf 100644 --- a/src/app/screens/signatureRequest/index.tsx +++ b/src/app/screens/signatureRequest/index.tsx @@ -28,9 +28,9 @@ import { bytesToHex } from '@stacks/transactions'; import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import SignatureRequestMessage from './signatureRequestMessage'; import SignatureRequestStructuredData from './signatureRequestStructuredData'; import { finalizeMessageSignature } from './utils'; +import SignatureRequestMessage from './signatureRequestMessage'; import CollapsableContainer from './collapsableContainer'; const OuterContainer = styled.div({ @@ -275,7 +275,7 @@ function SignatureRequest(): JSX.Element { if (isSignMessageBip322) { const signature = await handleBip322LedgerMessageSigning({ transport, - accountId: selectedAccount.deviceAccountIndex, + addressIndex: selectedAccount.deviceAccountIndex, networkType: network.type, message: payload.message, }); @@ -290,12 +290,12 @@ function SignatureRequest(): JSX.Element { chrome.tabs.sendMessage(+tabId, signingMessage); window.close(); } else { - const signature = await signStxMessage( + const signature = await signStxMessage({ transport, - payload.message, - 0, - selectedAccount.deviceAccountIndex, - ); + message: payload.message, + accountIndex: 0, + addressIndex: selectedAccount.deviceAccountIndex, + }); if ( !!signature.errorMessage && signature.errorMessage !== 'No errors' && // @zondax/ledger-stacks npm package returns this string when there are no errors diff --git a/src/app/stores/wallet/actions/actionCreators.ts b/src/app/stores/wallet/actions/actionCreators.ts index 4852b1b9c..84dfed15d 100644 --- a/src/app/stores/wallet/actions/actionCreators.ts +++ b/src/app/stores/wallet/actions/actionCreators.ts @@ -235,6 +235,15 @@ export function ChangeShowOrdinalReceiveAlertAction( }; } +export function changeShowDataCollectionAlertAction( + showDataCollectionAlert: boolean | null, +): actions.ChangeShowDataCollectionAlert { + return { + type: actions.ChangeShowDataCollectionAlertKey, + showDataCollectionAlert, + }; +} + export function setBrcCoinsDataAction(brcCoinsList: FungibleToken[]): actions.SetBrcCoinsData { return { type: actions.SetBrcCoinsListKey, diff --git a/src/app/stores/wallet/actions/types.ts b/src/app/stores/wallet/actions/types.ts index 771905e4e..77e775835 100644 --- a/src/app/stores/wallet/actions/types.ts +++ b/src/app/stores/wallet/actions/types.ts @@ -1,6 +1,7 @@ -import { AccountType } from '@secretkeylabs/xverse-core'; import { Account, + AccountType, + AppInfo, BaseWallet, Coin, FeesMultipliers, @@ -39,6 +40,7 @@ export const ChangeHasActivatedOrdinalsKey = 'ChangeHasActivatedOrdinalsKey'; export const ChangeShowBtcReceiveAlertKey = 'ChangeShowBtcReceiveAlertKey'; export const ChangeShowOrdinalReceiveAlertKey = 'ChangeShowOrdinalReceiveAlertKey'; +export const ChangeShowDataCollectionAlertKey = 'ChangeShowDataCollectionAlertKey'; export const UpdateLedgerAccountsKey = 'UpdateLedgerAccountsKey'; export const SetBrcCoinsListKey = 'SetBrcCoinsList'; @@ -76,11 +78,12 @@ export interface WalletState { coinsList: FungibleToken[] | null; coins: Coin[]; brcCoinsList: FungibleToken[] | null; - feeMultipliers: FeesMultipliers | null; + feeMultipliers: AppInfo | null; networkAddress: string | undefined; hasActivatedOrdinalsKey: boolean | undefined; showBtcReceiveAlert: boolean | null; showOrdinalReceiveAlert: boolean | null; + showDataCollectionAlert: boolean | null; accountType: AccountType | undefined; accountName: string | undefined; btcApiUrl: string; @@ -209,6 +212,11 @@ export interface ChangeShowOrdinalReceiveAlert { showOrdinalReceiveAlert: boolean | null; } +export interface ChangeShowDataCollectionAlert { + type: typeof ChangeShowDataCollectionAlertKey; + showDataCollectionAlert: boolean | null; +} + export interface SetBrcCoinsData { type: typeof SetBrcCoinsListKey; brcCoinsList: FungibleToken[]; @@ -242,6 +250,6 @@ export type WalletActions = | ChangeActivateOrdinals | ChangeShowBtcReceiveAlert | ChangeShowOrdinalReceiveAlert + | ChangeShowDataCollectionAlert | SetBrcCoinsData - | SetWalletLockPeriod - | DisableWalletExistsGuard; + | SetWalletLockPeriod; diff --git a/src/app/stores/wallet/reducer.ts b/src/app/stores/wallet/reducer.ts index 28ec267f0..1c8c6bb1b 100644 --- a/src/app/stores/wallet/reducer.ts +++ b/src/app/stores/wallet/reducer.ts @@ -28,6 +28,7 @@ import { WalletActions, WalletSessionPeriods, WalletState, + ChangeShowDataCollectionAlertKey, } from './actions/types'; const initialWalletState: WalletState = { @@ -61,6 +62,7 @@ const initialWalletState: WalletState = { hasActivatedOrdinalsKey: undefined, showBtcReceiveAlert: true, showOrdinalReceiveAlert: true, + showDataCollectionAlert: true, accountType: 'software', accountName: undefined, walletLockPeriod: WalletSessionPeriods.STANDARD, @@ -199,6 +201,11 @@ const walletReducer = ( ...state, showOrdinalReceiveAlert: action.showOrdinalReceiveAlert, }; + case ChangeShowDataCollectionAlertKey: + return { + ...state, + showDataCollectionAlert: action.showDataCollectionAlert, + }; case SetBrcCoinsListKey: return { ...state, diff --git a/src/app/utils/constants.ts b/src/app/utils/constants.ts index 8c37b7dcd..8a55be965 100644 --- a/src/app/utils/constants.ts +++ b/src/app/utils/constants.ts @@ -23,6 +23,7 @@ export const TRANSAC_URL = 'https://global.transak.com'; export const TRANSAC_API_KEY = process.env.TRANSAC_API_KEY; export const MOON_PAY_URL = 'https://buy.moonpay.com'; export const MOON_PAY_API_KEY = process.env.MOON_PAY_API_KEY; +export const MIX_PANEL_TOKEN = process.env.MIX_PANEL_TOKEN; export type CurrencyTypes = 'STX' | 'BTC' | 'FT' | 'NFT' | 'Ordinal' | 'brc20' | 'brc20-Ordinal'; export enum LoaderSize { @@ -58,3 +59,14 @@ export const SEND_MANY_TOKEN_TRANSFER_CONTRACT_PRINCIPAL = export const SWAP_SPONSOR_DISABLED_SUPPORT_URL = 'https://support.xverse.app/hc/en-us/articles/18319388355981'; export const SUPPORT_URL_TAB_TARGET = 'SupportURLTabTarget'; + +export const DEFAULT_TRANSITION_OPTIONS = { + from: { + x: 24, + opacity: 0, + }, + enter: { + x: 0, + opacity: 1, + }, +}; diff --git a/src/app/utils/ledger.ts b/src/app/utils/ledger.ts index 5cb2a9c24..533ff16a7 100644 --- a/src/app/utils/ledger.ts +++ b/src/app/utils/ledger.ts @@ -3,23 +3,23 @@ import { Transport } from '@secretkeylabs/xverse-core/ledger/types'; export const handleBip322LedgerMessageSigning = async ({ transport, - accountId, + addressIndex, networkType, message, }: { transport: Transport; - accountId?: number; + addressIndex?: number; networkType: NetworkType; message: string; }) => { - if (accountId === undefined) { + if (addressIndex === undefined) { throw new Error('Account not found'); } const signature = await signSimpleBip322Message({ transport, networkType, - addressIndex: accountId, + addressIndex, message, }); diff --git a/src/app/utils/mixpanel.ts b/src/app/utils/mixpanel.ts new file mode 100644 index 000000000..a862fccbc --- /dev/null +++ b/src/app/utils/mixpanel.ts @@ -0,0 +1,53 @@ +import mixpanel from 'mixpanel-browser'; +import { sha256 } from 'js-sha256'; +import { AnalyticsEvents } from '@secretkeylabs/xverse-core/types'; +import { MIX_PANEL_TOKEN } from './constants'; + +export const isMixPanelInited = () => !!MIX_PANEL_TOKEN && !!mixpanel.config; + +export const trackMixPanel = (event: string, properties?: any, options?: any, callback?: any) => { + if (!isMixPanelInited()) { + return; + } + + mixpanel.track(event, properties, options, callback); +}; + +export const optOutMixPanel = () => { + if (!isMixPanelInited()) { + return; + } + + trackMixPanel(AnalyticsEvents.OptOut, undefined, { send_immediately: true }, () => { + mixpanel.opt_out_tracking(); + }); +}; + +export const optInMixPanel = (masterPubKey?: string) => { + if (!isMixPanelInited()) { + return; + } + + mixpanel.opt_in_tracking(); + + if (masterPubKey) { + mixpanel.identify(sha256(masterPubKey)); + } +}; + +export const hasOptedInMixPanelTracking = async () => { + if (!isMixPanelInited()) { + return false; + } + + const hasOptedIn = await mixpanel.has_opted_in_tracking(); + return hasOptedIn; +}; + +export const resetMixPanel = () => { + if (!isMixPanelInited()) { + return; + } + + mixpanel.reset(); +}; diff --git a/src/assets/img/dashboard-icon.svg b/src/assets/img/dashboard-icon.svg new file mode 100644 index 000000000..babd09c91 --- /dev/null +++ b/src/assets/img/dashboard-icon.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 9e3083fc7..72592d7db 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -65,7 +65,12 @@ "LEDGER_ADD_ACCOUNT_NAME": { "TITLE": "Name your Ledger wallet", "SUBTITLE": "You can give your wallet a custom name.", - "INPUT": "Wallet name" + "INPUT": "Wallet name", + "PLACEHOLDER": "My ledger", + "ERRORS": { + "MAX_LENGTH": "Account name should not be longer than {{number}} characters.", + "ALREADY_EXISTS": "Account with the same name already exists. Please choose another name." + } }, "LEDGER_IMPORT_END": { "TITLE": "Your wallet is ready!", @@ -177,7 +182,10 @@ "CLOSE_BUTTON": "Close", "CANCEL_BUTTON": "Cancel", "SEE_TRANSACTION_BUTTON": "See transaction", - "RETRY_BUTTON": "Try again" + "SEND_ORDINAL": "Send ordinal", + "CONFIRM_FEES": "Confirm fees", + "RETRY_BUTTON": "Try again", + "FEES": "Fees" }, "DASHBOARD_SCREEN": { "TOTAL_BALANCE": "total balance", @@ -197,7 +205,13 @@ "VIEW_ADDRESSES": "View addresses", "ADD_STACKS_ADDRESS": "Add a Stacks address", "REMOVE_FROM_LIST_TITLE": "Remove from list", - "REMOVE_FROM_LIST_DESCRIPTION": "This will disconnect and remove the account from Xverse. You can import the same account again later by reconnecting your hardware wallet device." + "REMOVE_FROM_LIST_DESCRIPTION": "This will disconnect and remove the account from Xverse. You can import the same account again later by reconnecting your hardware wallet device.", + "DATA_COLLECTION_POPUP": { + "TITLE": "Help us improve Xverse!", + "DESCRIPTION": "Help improve the app experience, by allowing Xverse to collect anonymized usage data. This data cannot be used to identify your wallet individually.", + "DENY": "Deny", + "ALLOW": "Allow" + } }, "TOKEN_SCREEN": { "ADD_COINS": "Manage tokens" @@ -296,7 +310,6 @@ "YOU_WILL_RECEIVE": "You will receive", "SCRIPT_OUTPUT": "Script output", "SCRIPT_OUTPUT_TX": "This transaction contains a script output. Be sure you trust the source of this transaction before confirming it.", - "ORDINAL": "Ordinal", "ORDINAL_DETECTED_WARNING": "Ordinal inscription detected in transaction. Continuing will cause your ordinal to be transferred away.", "ORDINAL_DETECTED_ACTION": "Move to my ordinals address", @@ -304,6 +317,7 @@ "BTC_TRANSFER_DANGER_ALERT_DESC": "You are about to make a Bitcoin transfer which contains an ordinal inscription. Once transferred out of the wallet, you will not be able to recover them.", "CONITNUE": "Continue", "BACK": "Back", + "HIGH_FEE_WARNING_TEXT": "The estimated transaction fee for this transaction is very high.", "LEDGER": { "CONNECT": { "TITLE": "Connect your hardware wallet", @@ -374,7 +388,8 @@ "SCREEN_SUBTITLE": "Please review the Xverse Wallet Privacy Policy and Terms of Services.", "TERMS_SERVICES_LINK_BUTTON": "Terms of Service", "PRIVACY_POLICY_LINK_BUTTON": "Privacy Policy", - "ACCEPT_LEGAL_BUTTON": "Accept" + "ACCEPT_LEGAL_BUTTON": "Accept", + "AUTHORIZE_DATA_COLLECTION": "Authorize data collection" }, "BACKUP_WALLET_SCREEN": { "SCREEN_TITLE": "Backup your wallet", @@ -610,6 +625,11 @@ "SETTING_SCREEN": { "GENERAL": "General", "CURRENCY": "Fiat Currency", + "PRIVACY_PREFERENCES": { + "TITLE": "Privacy Preferences", + "DESCRIPTION": "Help improve the app experience, by allowing Xverse to collect anonymized usage data. This data cannot be used to identify your wallet individually.", + "AUTHORIZE_DATA_COLLECTION": "Authorize data collection" + }, "NETWORK": "Network", "SECURITY": "Security", "UPDATE_PASSWORD": "Update Password", From 783d8543b8c0dd6c305ced6413480266c491a35c Mon Sep 17 00:00:00 2001 From: Tim Man Date: Tue, 3 Oct 2023 22:48:36 +0800 Subject: [PATCH 02/28] chore: allow ci build version to pass env vars to build (#27) --- .github/workflows/build.yml | 4 ++++ .github/workflows/release.yml | 4 ++++ webpack/webpack.config.js | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f60a41461..3560149b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,10 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_REGISTRY_TOKEN }} - name: Build + env: + TRANSAC_API_KEY: ${{ secrets.TRANSAC_API_KEY }} + MOON_PAY_API_KEY: ${{ secrets.MOON_PAY_API_KEY }} + MIX_PANEL_TOKEN: ${{ secrets.MIX_PANEL_TOKEN }} run: npm run build --if-present # - name: Test # run: npm test --passWithNoTests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8e705ed1..038b6fe40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,6 +22,10 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_REGISTRY_TOKEN }} - name: Build + env: + TRANSAC_API_KEY: ${{ secrets.TRANSAC_API_KEY }} + MOON_PAY_API_KEY: ${{ secrets.MOON_PAY_API_KEY }} + MIX_PANEL_TOKEN: ${{ secrets.MIX_PANEL_TOKEN }} run: npm run build --if-present # - name: Test # run: npm test --passWithNoTests diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js index e458e64f3..25314db70 100644 --- a/webpack/webpack.config.js +++ b/webpack/webpack.config.js @@ -111,7 +111,7 @@ var options = { }, }, plugins: [ - new Dotenv(), + new Dotenv({ safe: true, systemvars: true }), new CleanWebpackPlugin({ verbose: false }), new webpack.ProgressPlugin(), // expose and write the allowed env vars on the compiled bundle From f48e78c4ab1d370480ba8b2d23b518ed6af73a4c Mon Sep 17 00:00:00 2001 From: Tim Man Date: Wed, 4 Oct 2023 00:29:55 +0800 Subject: [PATCH 03/28] feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov --- package-lock.json | 49 +- package.json | 3 +- src/app/components/accountHeader/index.tsx | 10 +- src/app/components/accountRow/index.tsx | 7 +- .../components/bundleAsset/bundleAsset.tsx | 42 ++ .../bundleAsset/rareSatsCollage.tsx | 61 +++ .../confirmBtcTransactionComponent/index.tsx | 25 +- .../components/rareSatAsset/rareSatAsset.tsx | 84 +++ .../components/rareSatIcon/rareSatIcon.tsx | 108 ++++ .../components/recipientComponent/index.tsx | 51 +- src/app/components/sendForm/index.tsx | 5 +- src/app/components/topRow/index.tsx | 3 +- src/app/components/webGalleryButton/index.tsx | 41 ++ .../ordinals/useAddressInscriptions.ts | 12 +- .../queries/ordinals/useAddressRareSats.ts | 68 +++ src/app/hooks/stores/useSatBundleReducer.ts | 25 + src/app/hooks/useResetUserFlow.ts | 3 + src/app/routes/index.tsx | 28 + .../confirmOrdinalTransaction/index.tsx | 68 +-- src/app/screens/legalLinks/index.tsx | 2 +- .../screens/nftDashboard/collectiblesTabs.tsx | 220 ++++++++ src/app/screens/nftDashboard/index.tsx | 470 +++++++++-------- src/app/screens/nftDashboard/nft.tsx | 47 +- src/app/screens/nftDashboard/nftImage.tsx | 3 +- src/app/screens/nftDashboard/notice.tsx | 89 ++++ .../nftDashboard/rareSatsTabGridItem.tsx | 70 +++ .../nftDashboard/supportedRarities/index.tsx | 96 ++++ .../supportedRarities/rarityTile.tsx | 78 +++ src/app/screens/ordinalDetail/index.tsx | 87 +++- .../ordinalAttributeComponent.tsx | 66 ++- src/app/screens/ordinals/brc20Tile.tsx | 13 +- src/app/screens/ordinals/index.tsx | 28 +- src/app/screens/ordinals/ordinalImage.tsx | 46 +- src/app/screens/rareSatsBundle/index.tsx | 284 ++++++++++ .../rareSatsBundle/rareSatsBundleGridItem.tsx | 87 ++++ .../screens/rareSatsDetail/rareSatsDetail.tsx | 489 ++++++++++++++++++ src/app/screens/sendOrdinal/index.tsx | 2 +- src/app/screens/sendRareSat/index.tsx | 258 +++++++++ src/app/screens/settings/index.tsx | 31 +- .../settings/settingComponent/index.tsx | 89 +++- .../stores/nftData/actions/actionCreator.ts | 18 + src/app/stores/nftData/actions/types.ts | 21 +- src/app/stores/nftData/reducer.ts | 21 +- .../stores/wallet/actions/actionCreators.ts | 18 + src/app/stores/wallet/actions/types.ts | 14 + src/app/stores/wallet/reducer.ts | 14 + src/app/ui-library/common.styled.ts | 41 +- src/app/ui-library/dialog.tsx | 149 ++++++ src/app/utils/constants.ts | 12 +- src/app/utils/helper.ts | 12 +- src/app/utils/rareSats.test.ts | 186 +++++++ src/app/utils/rareSats.ts | 232 +++++++++ src/assets/img/nftDashboard/nft_fallback.svg | 6 +- .../img/nftDashboard/rareSats/NewFeature.svg | 24 + src/assets/img/nftDashboard/rareSats/epic.svg | 9 + .../img/nftDashboard/rareSats/legendary.svg | 10 + .../img/nftDashboard/rareSats/mythic.svg | 19 + src/assets/img/nftDashboard/rareSats/rare.svg | 7 + .../img/nftDashboard/rareSats/uncommon.svg | 8 + src/locales/en.json | 77 ++- src/theme/index.ts | 22 +- 61 files changed, 3719 insertions(+), 449 deletions(-) create mode 100644 src/app/components/bundleAsset/bundleAsset.tsx create mode 100644 src/app/components/bundleAsset/rareSatsCollage.tsx create mode 100644 src/app/components/rareSatAsset/rareSatAsset.tsx create mode 100644 src/app/components/rareSatIcon/rareSatIcon.tsx create mode 100644 src/app/components/webGalleryButton/index.tsx create mode 100644 src/app/hooks/queries/ordinals/useAddressRareSats.ts create mode 100644 src/app/hooks/stores/useSatBundleReducer.ts create mode 100644 src/app/screens/nftDashboard/collectiblesTabs.tsx create mode 100644 src/app/screens/nftDashboard/notice.tsx create mode 100644 src/app/screens/nftDashboard/rareSatsTabGridItem.tsx create mode 100644 src/app/screens/nftDashboard/supportedRarities/index.tsx create mode 100644 src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx create mode 100644 src/app/screens/rareSatsBundle/index.tsx create mode 100644 src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx create mode 100644 src/app/screens/rareSatsDetail/rareSatsDetail.tsx create mode 100644 src/app/screens/sendRareSat/index.tsx create mode 100644 src/app/ui-library/dialog.tsx create mode 100644 src/app/utils/rareSats.test.ts create mode 100644 src/app/utils/rareSats.ts create mode 100644 src/assets/img/nftDashboard/rareSats/NewFeature.svg create mode 100644 src/assets/img/nftDashboard/rareSats/epic.svg create mode 100644 src/assets/img/nftDashboard/rareSats/legendary.svg create mode 100644 src/assets/img/nftDashboard/rareSats/mythic.svg create mode 100644 src/assets/img/nftDashboard/rareSats/rare.svg create mode 100644 src/assets/img/nftDashboard/rareSats/uncommon.svg diff --git a/package-lock.json b/package-lock.json index d815080fb..a4b80a5e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.0", + "@secretkeylabs/xverse-core": "1.8.1", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -55,6 +55,7 @@ "react-share": "^4.4.1", "react-spinners": "^0.13.7", "react-switch": "^7.0.0", + "react-tabs": "^6.0.2", "react-tooltip": "^5.4.0", "redux": "^4.0.5", "redux-persist": "^6.0.0", @@ -2208,9 +2209,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "1.8.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.0/237b5304fa9e9d03c757102ed66be27b4ead25ef", - "integrity": "sha512-u9dt1wXpECorrXmvHPBWxp+t2xM3tmqoa9pHNE0V/ndbzVF+45BY+vxLjGmv5hta8CYMWTmJnfZnyE5tlZyIUw==", + "version": "1.8.1", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.1/e8656470eb2f1c662353883a03e675330303791b", + "integrity": "sha512-8rzgQLSHEHLLrEsBs6BE7p6W55/zSU4ySKw5v/q9n55p1HVnt3WfZoEzJcQ4fd6Hrxaz2gSlnf2ut9EuEDegUQ==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -7031,6 +7032,14 @@ "node": ">=6" } }, + "node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -15631,6 +15640,18 @@ "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-tabs": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", + "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", + "dependencies": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/react-tooltip": { "version": "5.19.0", "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz", @@ -20387,9 +20408,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "1.8.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.0/237b5304fa9e9d03c757102ed66be27b4ead25ef", - "integrity": "sha512-u9dt1wXpECorrXmvHPBWxp+t2xM3tmqoa9pHNE0V/ndbzVF+45BY+vxLjGmv5hta8CYMWTmJnfZnyE5tlZyIUw==", + "version": "1.8.1", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.1/e8656470eb2f1c662353883a03e675330303791b", + "integrity": "sha512-8rzgQLSHEHLLrEsBs6BE7p6W55/zSU4ySKw5v/q9n55p1HVnt3WfZoEzJcQ4fd6Hrxaz2gSlnf2ut9EuEDegUQ==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -24460,6 +24481,11 @@ "shallow-clone": "^3.0.0" } }, + "clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -30873,6 +30899,15 @@ "prop-types": "^15.7.2" } }, + "react-tabs": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", + "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", + "requires": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + } + }, "react-tooltip": { "version": "5.19.0", "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz", diff --git a/package.json b/package.json index 4ca4e9845..00ad41b2b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.0", + "@secretkeylabs/xverse-core": "1.8.1", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -51,6 +51,7 @@ "react-share": "^4.4.1", "react-spinners": "^0.13.7", "react-switch": "^7.0.0", + "react-tabs": "^6.0.2", "react-tooltip": "^5.4.0", "redux": "^4.0.5", "redux-persist": "^6.0.0", diff --git a/src/app/components/accountHeader/index.tsx b/src/app/components/accountHeader/index.tsx index a645ae374..9a5751d23 100644 --- a/src/app/components/accountHeader/index.tsx +++ b/src/app/components/accountHeader/index.tsx @@ -11,14 +11,16 @@ import styled from 'styled-components'; import OptionsDialog, { OPTIONS_DIALOG_WIDTH } from '@components/optionsDialog/optionsDialog'; import useWalletSelector from '@hooks/useWalletSelector'; -const SelectedAccountContainer = styled.div((props) => ({ +const SelectedAccountContainer = styled.div<{ showBorderBottom?: boolean }>((props) => ({ display: 'flex', flexDirection: 'row', position: 'relative', alignItems: 'center', justifyContent: 'space-between', padding: `${props.theme.spacing(10)}px ${props.theme.spacing(8)}px`, - borderBottom: `0.5px solid ${props.theme.colors.background.elevation3}`, + borderBottom: props.showBorderBottom + ? `0.5px solid ${props.theme.colors.background.elevation3}` + : 'none', })); const ResetWalletContainer = styled.div((props) => ({ @@ -70,11 +72,13 @@ const WarningButton = styled(ButtonRow)` interface AccountHeaderComponentProps { disableMenuOption?: boolean; disableAccountSwitch?: boolean; + showBorderBottom?: boolean; } function AccountHeaderComponent({ disableMenuOption = false, disableAccountSwitch = false, + showBorderBottom = true, }: AccountHeaderComponentProps) { const navigate = useNavigate(); const { selectedAccount } = useWalletSelector(); @@ -163,7 +167,7 @@ function AccountHeaderComponent({ /> )} - + ((props) => ({ - width: 40, - height: 40, + width: 20, + height: 20, borderRadius: 25, background: `linear-gradient(to bottom,${props.firstGradient}, ${props.secondGradient},${props.thirdGradient} )`, })); @@ -52,6 +53,7 @@ const CurrentAcountContainer = styled.div((props) => ({ const CurrentAccountTextContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', + alignItems: 'center', gap: props.theme.spacing(4), })); @@ -238,6 +240,7 @@ function AccountRow({ {getName()} )} {isHardwareAccount(account) && Ledger icon} + {isSelected && !disabledAccountSelect && } )} diff --git a/src/app/components/bundleAsset/bundleAsset.tsx b/src/app/components/bundleAsset/bundleAsset.tsx new file mode 100644 index 000000000..4ab31b673 --- /dev/null +++ b/src/app/components/bundleAsset/bundleAsset.tsx @@ -0,0 +1,42 @@ +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import { Bundle } from '@utils/rareSats'; +import styled from 'styled-components'; + +import RareSatsCollage from './rareSatsCollage'; + +const ImageContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + aspect-ratio: 1; + overflow: hidden; + border-radius: ${(props) => props.theme.radius(1)}px; +`; + +const IndividualAssetContainer = styled.div` + display: flex; + width: 100%; + background: ${(props) => props.theme.colors.elevation1}; +`; + +interface Props { + bundle: Bundle; +} + +function BundleAsset({ bundle }: Props) { + const isMoreThanOneItem = bundle.items?.length > 1; + return ( + + {isMoreThanOneItem ? ( + + ) : ( + + + + )} + + ); +} + +export default BundleAsset; diff --git a/src/app/components/bundleAsset/rareSatsCollage.tsx b/src/app/components/bundleAsset/rareSatsCollage.tsx new file mode 100644 index 000000000..b5d0a7466 --- /dev/null +++ b/src/app/components/bundleAsset/rareSatsCollage.tsx @@ -0,0 +1,61 @@ +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import { BundleItem } from '@utils/rareSats'; +import styled from 'styled-components'; + +const CollageContainer = styled.div` + display: flex; + flex-wrap: wrap; + padding: calc(7%); + gap: calc(6%); + align-items: center; + width: 100%; + aspect-ratio: 1; + border: 1px solid ${(props) => props.theme.colors.white_800}; + border-radius: ${(props) => props.theme.radius(1)}px; +`; + +const CollageItem = styled.div` + width: calc(50% - 3%); + height: calc(50% - 3%); + overflow: hidden; +`; + +const RemainingAmountOfAssets = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + height: '100%', + aspectRatio: 1, + overflow: 'hidden', + borderRadius: props.theme.radius(1), + background: props.theme.colors.elevation1, + p: { + ...props.theme.body_medium_m, + fontSize: 'calc(2vw + 2vh)', + color: props.theme.colors.white_0, + }, +})); + +function RareSatsCollage({ items }: { items: Array }) { + const moreThanFourItems = items.length > 4; + + return ( + + {items.slice(0, 4).map((item, index) => ( + // eslint-disable-next-line react/no-array-index-key + + {moreThanFourItems && index === 3 ? ( + +

+{items.length - 4}

+
+ ) : ( + + )} +
+ ))} +
+ ); +} + +export default RareSatsCollage; diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index e4fc3a82c..c4226f9af 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -22,6 +22,7 @@ import { signOrdinalSendTransaction, } from '@secretkeylabs/xverse-core/transactions/btc'; import { useMutation } from '@tanstack/react-query'; +import { CurrencyTypes } from '@utils/constants'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -30,6 +31,7 @@ import styled from 'styled-components'; import InfoContainer from '@components/infoContainer'; import useWalletSelector from '@hooks/useWalletSelector'; import TransactionDetailComponent from '../transactionDetailComponent'; +import Callout from '@ui-library/callout'; const OuterContainer = styled.div` display: flex; @@ -111,6 +113,11 @@ const ReviewTransactionText = styled.h1((props) => textAlign: props.isOridnalTx ? 'center' : 'left', })); +const CalloutContainer = styled.div((props) => ({ + marginBottom: props.theme.spacing(8), + marginhorizontal: props.theme.spacing(8), +})); + interface Props { currentFee: BigNumber; feePerVByte: BigNumber; // TODO tim: is this the same as currentFeeRate? refactor to be clear @@ -120,9 +127,12 @@ interface Props { recipients: Recipient[]; children?: ReactNode; assetDetail?: string; + assetDetailValue?: string; isRestoreFundFlow?: boolean; nonOrdinalUtxos?: BtcUtxoDataResponse[]; isBtcSendBrowserTx?: boolean; + currencyType?: CurrencyTypes; + isPartOfBundle?: boolean; currentFeeRate: BigNumber; setCurrentFee: (feeRate: BigNumber) => void; setCurrentFeeRate: (feeRate: BigNumber) => void; @@ -140,9 +150,12 @@ function ConfirmBtcTransactionComponent({ recipients, children, assetDetail, + assetDetailValue, isRestoreFundFlow, nonOrdinalUtxos, isBtcSendBrowserTx, + isPartOfBundle, + currencyType, currentFeeRate, setCurrentFee, setCurrentFeeRate, @@ -369,12 +382,22 @@ function ConfirmBtcTransactionComponent({ {t('CONFIRM_TRANSACTION.REVIEW_TRANSACTION')} + {isPartOfBundle && ( + + + + )} + {ordinalTxUtxo ? ( ) : ( diff --git a/src/app/components/rareSatAsset/rareSatAsset.tsx b/src/app/components/rareSatAsset/rareSatAsset.tsx new file mode 100644 index 000000000..7d3ec4fb9 --- /dev/null +++ b/src/app/components/rareSatAsset/rareSatAsset.tsx @@ -0,0 +1,84 @@ +import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { Inscription } from '@secretkeylabs/xverse-core'; +import { BundleItem } from '@utils/rareSats'; +import styled from 'styled-components'; + +const Container = styled.div` + width: 100%; + height: 100%; +`; + +const InscriptionContainer = styled.div` + width: 100%; + height: 100%; + position: relative; +`; + +const RareSatIconContainer = styled.div<{ isGallery: boolean }>((props) => ({ + display: 'flex', + position: 'absolute', + zIndex: 1, + left: props.isGallery ? 20 : 8, + top: props.isGallery ? 20 : 8, +})); + +const RareSatsContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + aspectRatio: '1', + overflow: 'hidden', + position: 'relative', + backgroundColor: props.theme.colors.elevation1, + borderRadius: 8, +})); + +const DynamicSizeContainer = styled.div<{ isCollage: boolean }>((props) => ({ + width: props.isCollage ? '40%' : '50%', + height: props.isCollage ? '40%' : '50%', +})); + +interface Props { + item: BundleItem; + isCollage?: boolean; +} + +function RareSatAsset({ item, isCollage = false }: Props) { + const isGallery: boolean = document.documentElement.clientWidth > 360; + const isInscription = item.type === 'inscription' || item.type === 'inscribed-sat'; + + return ( + + {isInscription ? ( + + {!isCollage && item.rarity_ranking !== 'common' && ( + + + + )} + + + ) : ( + + + + + + )} + + ); +} + +export default RareSatAsset; diff --git a/src/app/components/rareSatIcon/rareSatIcon.tsx b/src/app/components/rareSatIcon/rareSatIcon.tsx new file mode 100644 index 000000000..94a7bb8e1 --- /dev/null +++ b/src/app/components/rareSatIcon/rareSatIcon.tsx @@ -0,0 +1,108 @@ +import Epic from '@assets/img/nftDashboard/rareSats/epic.svg'; +import Legendary from '@assets/img/nftDashboard/rareSats/legendary.svg'; +import Mythic from '@assets/img/nftDashboard/rareSats/mythic.svg'; +import Rare from '@assets/img/nftDashboard/rareSats/rare.svg'; +import Uncommon from '@assets/img/nftDashboard/rareSats/uncommon.svg'; +import { RareSatsType, getRareSatsColorsByRareSatsType } from '@utils/rareSats'; +import styled from 'styled-components'; +import { Question } from '@phosphor-icons/react'; + +import Theme from '../../../theme'; + +const Container = styled.div<{ bgColor: string; padding: number }>((props) => ({ + backgroundColor: props.bgColor, + padding: props.padding, + borderRadius: props.bgColor && props.padding ? '100%' : 0, +})); +const ImageContainer = styled.div<{ size: number; dynamicSize: boolean }>((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: props.dynamicSize ? '100%' : props.size, + height: props.dynamicSize ? '100%' : props.size, + position: 'relative', +})); +const Image = styled.img` + width: 100%; + height: 100%; + zindex: 2; +`; +const QuestionIcon = styled(Question)((props) => ({ + color: props.theme.colors.white_0, +})); +type GlowProps = { + color: string; + outerColor: string; + isCollage: boolean; + isGallery: boolean; +}; +const Glow = styled.div((props) => { + const boxShadow = { + 'extension-collage': `0 0 calc(5vw) calc(1.5vw) ${props.color}`, + 'extension-one-item': `0 0 calc(12vw) calc(2vw) ${props.color}`, + 'gallery-collage': `0 0 calc(3.5vw) calc(0.8vw) ${props.color}`, + 'gallery-one-item': `0 0 calc(7vw) calc(1.5vw) ${props.color}`, + }[`${props.isGallery ? 'gallery' : 'extension'}-${props.isCollage ? 'collage' : 'one-item'}`]; + return { + position: 'absolute', + zIndex: 1, + width: '10%', + height: '10%', + borderRadius: '100%', + boxShadow, + }; +}); + +interface Props { + type: RareSatsType; + size?: number; + bgColor?: keyof (typeof Theme)['colors']['background']; + padding?: number; + isDynamicSize?: boolean; + isCollage?: boolean; + glow?: boolean; +} + +function RareSatIcon({ + type, + size = 24, + bgColor, + padding = 0, + isDynamicSize = false, + isCollage = false, + glow = true, +}: Props) { + const isGallery: boolean = document.documentElement.clientWidth > 360; + const src = { + epic: Epic, + legendary: Legendary, + mythic: Mythic, + rare: Rare, + uncommon: Uncommon, + }[type]; + const backgroundColor = bgColor ? Theme.colors.background[bgColor] : 'transparent'; + const { color, backgroundColor: outerColor } = getRareSatsColorsByRareSatsType(type); + return ( + + + {type === 'unknown' ? ( + + ) : ( + <> + {glow && ( + + )} + {type} + + )} + + + ); +} + +export default RareSatIcon; diff --git a/src/app/components/recipientComponent/index.tsx b/src/app/components/recipientComponent/index.tsx index 0b4ac2995..075d12757 100644 --- a/src/app/components/recipientComponent/index.tsx +++ b/src/app/components/recipientComponent/index.tsx @@ -13,6 +13,7 @@ import { CurrencyTypes } from '@utils/constants'; import useWalletSelector from '@hooks/useWalletSelector'; import { useEffect, useState } from 'react'; import { getTicker } from '@utils/helper'; +import { CubeTransparent } from '@phosphor-icons/react'; const Container = styled.div((props) => ({ display: 'flex', @@ -92,11 +93,24 @@ const TokenContainer = styled.div({ marginRight: 10, }); +const IconContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + borderRadius: 30, + backgroundColor: props.theme.colors.elevation3, + width: 32, + height: 32, + marginRight: props.theme.spacing(4), +})); + interface Props { address?: string; value: string; title: string; currencyType: CurrencyTypes; + valueDetail?: string; recipientIndex?: number; totalRecipient?: number; icon?: string; @@ -109,6 +123,7 @@ function RecipientComponent({ address, value, totalRecipient, + valueDetail, title, fungibleToken, icon, @@ -167,6 +182,26 @@ function RecipientComponent({ return ''; }; + const renderIcon = () => { + if (currencyType === 'RareSat') { + return ( + + + + ); + } + + if (icon) { + return ; + } + + return ( + + + + ); + }; + return ( {recipientIndex && totalRecipient && totalRecipient !== 1 && ( @@ -176,22 +211,12 @@ function RecipientComponent({ )} {heading && {heading}} - {icon ? ( - - ) : ( - - - - )} + {renderIcon()} {title} - {currencyType === 'NFT' || currencyType === 'Ordinal' ? ( + {currencyType === 'NFT' || currencyType === 'Ordinal' || currencyType === 'RareSat' ? ( {value} + {valueDetail && {valueDetail}} ) : ( diff --git a/src/app/components/sendForm/index.tsx b/src/app/components/sendForm/index.tsx index 6138d6d24..2fd9310d8 100644 --- a/src/app/components/sendForm/index.tsx +++ b/src/app/components/sendForm/index.tsx @@ -180,6 +180,7 @@ interface Props { disableAmountInput?: boolean; balance?: number; hideMemo?: boolean; + hideTokenImage?: boolean; buttonText?: string; processing?: boolean; children?: ReactNode; @@ -200,6 +201,7 @@ function SendForm({ disableAmountInput, balance, hideMemo = false, + hideTokenImage = false, buttonText, processing, children, @@ -446,7 +448,8 @@ function SendForm({ {currencyType !== 'NFT' && currencyType !== 'Ordinal' && - currencyType !== 'brc20-Ordinal' && ( + currencyType !== 'brc20-Ordinal' && + !hideTokenImage && ( ({ display: 'flex', minHeight: 18, - marginTop: props.theme.spacing(11), + marginTop: props.theme.spacing(12), + marginBottom: props.theme.spacing(9), marginLeft: props.theme.spacing(8), flexDirection: 'row', justifyContent: 'center', diff --git a/src/app/components/webGalleryButton/index.tsx b/src/app/components/webGalleryButton/index.tsx new file mode 100644 index 000000000..d5b412a41 --- /dev/null +++ b/src/app/components/webGalleryButton/index.tsx @@ -0,0 +1,41 @@ +import { SquaresFour } from '@phosphor-icons/react'; +import { StyledP } from '@ui-library/common.styled'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; + +const StyledButton = styled.button` + display: flex; + justify-content: flex-start; + align-items: center; + gap: ${(props) => props.theme.space.xs}; + background-color: transparent; + color: ${(props) => props.theme.colors.white_0}; + :hover:enabled { + color: ${(props) => props.theme.colors.white_200}; + } + :active ; + :disabled { + color: ${(props) => props.theme.colors.white_400}; + } + svg { + flex-grow: 0; + flex-shrink: 0; + } +`; + +export function WebGalleryButton({ + className, + onClick, +}: { + className?: string; + onClick: React.MouseEventHandler; +}) { + const { t } = useTranslation('translation'); + return ( + + + {t('NFT_DETAIL_SCREEN.WEB_GALLERY')} + + ); +} +export default WebGalleryButton; diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts index 26db8047d..98ddaf6bf 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts @@ -10,15 +10,11 @@ const useAddressInscriptions = () => { const PageSize = 30; const getInscriptionsByAddress = async ({ pageParam = 0 }) => { - try { - if (!ordinalsAddress) { - throw new InvalidParamsError('ordinalsAddress is required'); - } - const response = await ordinalsApi.getInscriptions(ordinalsAddress, pageParam || 0, PageSize); - return response; - } catch (err) { - return Promise.reject(err); + if (!ordinalsAddress) { + throw new InvalidParamsError('ordinalsAddress is required'); } + const response = await ordinalsApi.getInscriptions(ordinalsAddress, pageParam || 0, PageSize); + return response; }; const { isLoading, data, isFetchingNextPage, hasNextPage, error, refetch, fetchNextPage } = diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts new file mode 100644 index 000000000..faeb45a12 --- /dev/null +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -0,0 +1,68 @@ +import useWalletSelector from '@hooks/useWalletSelector'; +import { getAddressUtxoOrdinalBundles, getUtxoOrdinalBundle } from '@secretkeylabs/xverse-core'; +import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; +import { InvalidParamsError, handleRetries } from '@utils/query'; +import { mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; + +const PAGE_SIZE = 30; + +export const useAddressRareSats = () => { + const { ordinalsAddress } = useWalletSelector(); + + const getRareSatsByAddress = async ({ pageParam = 0 }) => { + if (!ordinalsAddress) { + throw new InvalidParamsError('ordinalsAddress is required'); + } + + const bundleResponse = await getAddressUtxoOrdinalBundles( + ordinalsAddress, + pageParam, + PAGE_SIZE, + { + hideUnconfirmed: true, + hideInscriptionOnly: true, + }, + ); + return bundleResponse; + }; + + return useInfiniteQuery(['rare-sats', ordinalsAddress], getRareSatsByAddress, { + refetchOnMount: false, + refetchOnWindowFocus: false, + retry: handleRetries, + getNextPageParam: (lastPage, allPages) => { + const currentLength = allPages.map((page) => page.results).flat().length; + if (currentLength < lastPage.total) { + return currentLength; + } + }, + }); +}; + +export const useGetUtxoOrdinalBundle = (output?: string, shouldMakeTheCall?: boolean) => { + const getUtxoOrdinalBundleByOutput = async () => { + if (!output) { + throw new InvalidParamsError('output is required'); + } + + const [txid, vout] = output.split(':'); + const bundleResponse = await getUtxoOrdinalBundle(txid, parseInt(vout, 10)); + return bundleResponse; + }; + + const { data, isLoading } = useQuery({ + enabled: !!(output && shouldMakeTheCall), + refetchOnMount: false, + refetchOnWindowFocus: false, + queryKey: ['rare-sats', output], + queryFn: getUtxoOrdinalBundleByOutput, + retry: handleRetries, + }); + const bundle = data?.txid ? mapRareSatsAPIResponseToRareSats(data) : undefined; + + return { + bundle, + isPartOfABundle: (bundle?.items ?? []).length > 1, + isLoading, + }; +}; diff --git a/src/app/hooks/stores/useSatBundleReducer.ts b/src/app/hooks/stores/useSatBundleReducer.ts new file mode 100644 index 000000000..56a66e616 --- /dev/null +++ b/src/app/hooks/stores/useSatBundleReducer.ts @@ -0,0 +1,25 @@ +import { + setSelectedSatBundleAction, + setSelectedSatBundleItemIndexAction, +} from '@stores/nftData/actions/actionCreator'; +import { NftDataState } from '@stores/nftData/actions/types'; +import { useDispatch } from 'react-redux'; + +const useSatBundleDataReducer = () => { + const dispatch = useDispatch(); + + const setSelectedSatBundleDetails = (data: NftDataState['selectedSatBundle']) => { + dispatch(setSelectedSatBundleAction(data)); + }; + + const setSelectedSatBundleItemIndex = (data: NftDataState['selectedSatBundleItemIndex']) => { + dispatch(setSelectedSatBundleItemIndexAction(data)); + }; + + return { + setSelectedSatBundleDetails, + setSelectedSatBundleItemIndex, + }; +}; + +export default useSatBundleDataReducer; diff --git a/src/app/hooks/useResetUserFlow.ts b/src/app/hooks/useResetUserFlow.ts index 1a00078a4..d13a3e73b 100644 --- a/src/app/hooks/useResetUserFlow.ts +++ b/src/app/hooks/useResetUserFlow.ts @@ -22,6 +22,9 @@ const userFlowConfig: Record = { '/confirm-nft-tx': { resetTo: '/nft-dashboard' }, '/verify-ledger': { resetTo: '/verify-ledger?mismatch=true' }, '/add-stx-address-ledger': { resetTo: '/add-stx-address-ledger?mismatch=true' }, + '/rare-sats-detail': { resetTo: '/nft-dashboard?tab=rareSats' }, + '/rare-sats-bundle': { resetTo: '/nft-dashboard?tab=rareSats' }, + '/send-rare-sat': { resetTo: '/nft-dashboard?tab=rareSats' }, }; type UserFlowConfigKey = keyof typeof userFlowConfig; diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index 6aeedbc7e..dacdfe0bf 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -49,6 +49,7 @@ import SendFtScreen from '@screens/sendFt'; import SendNft from '@screens/sendNft'; import SendOrdinal from '@screens/sendOrdinal'; import SendStxScreen from '@screens/sendStx'; +import SendRareSat from '@screens/sendRareSat'; import Setting from '@screens/settings'; import BackupWalletScreen from '@screens/settings/backupWallet'; import ChangeNetworkScreen from '@screens/settings/changeNetwork'; @@ -65,6 +66,9 @@ import TransactionStatus from '@screens/transactionStatus'; import WalletExists from '@screens/walletExists'; import { createHashRouter } from 'react-router-dom'; import PrivacyPreferencesScreen from '@screens/settings/privacyPreferences'; +import SupportedRarities from '@screens/nftDashboard/supportedRarities'; +import RareSatsDetailScreen from '@screens/rareSatsDetail/rareSatsDetail'; +import RareSatsBundle from '@screens/rareSatsBundle'; const router = createHashRouter([ { @@ -416,6 +420,14 @@ const router = createHashRouter([ ), }, + { + path: 'nft-dashboard/rare-sats-bundle', + element: ( + + + + ), + }, { path: 'nft-dashboard/nft-detail/:id', element: , @@ -424,6 +436,10 @@ const router = createHashRouter([ path: 'nft-dashboard/ordinal-detail', element: , }, + { + path: 'nft-dashboard/rare-sats-detail', + element: , + }, { path: 'nft-dashboard/nft-detail/:id/send-nft', element: , @@ -436,6 +452,18 @@ const router = createHashRouter([ ), }, + { + path: 'nft-dashboard/send-rare-sat', + element: ( + + + + ), + }, + { + path: 'nft-dashboard/supported-rarity-scale', + element: , + }, { path: 'restoreWallet', element: ( diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 86538c167..c2065a12f 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -13,9 +13,11 @@ import { useMutation } from '@tanstack/react-query'; import { isLedgerAccount } from '@utils/helper'; import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import { getBundleId, getBundleSubText } from '@utils/rareSats'; +import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; +import BundleAsset from '@components/bundleAsset/bundleAsset'; const ScrollContainer = styled.div` display: flex; @@ -30,38 +32,6 @@ const ScrollContainer = styled.div` margin: auto; `; -const ButtonContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'row', - marginLeft: '15%', - marginTop: props.theme.spacing(40), -})); - -const Button = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-end', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - opacity: 0.8, - marginTop: props.theme.spacing(5), -})); - -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', -})); - const BottomBarContainer = styled.h1((props) => ({ marginTop: props.theme.spacing(3), })); @@ -87,14 +57,20 @@ const NftContainer = styled.div((props) => ({ })); function ConfirmOrdinalTransaction() { - const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' }); const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; - const { selectedAccount } = useWalletSelector(); + const { selectedAccount, hasActivatedRareSatsKey } = useWalletSelector(); const navigate = useNavigate(); const btcClient = useBtcClient(); const [recipientAddress, setRecipientAddress] = useState(''); const location = useLocation(); - const { fee, feePerVByte, signedTxHex, ordinalUtxo } = location.state; + const { fee, feePerVByte, signedTxHex, ordinalUtxo, isRareSat } = location.state; + const { selectedOrdinal, selectedSatBundle } = useNftDataSelector(); + const { refetch } = useBtcWalletData(); + const [currentFee, setCurrentFee] = useState(fee); + const [currentFeeRate, setCurrentFeeRate] = useState(feePerVByte); + + const bundleId = selectedSatBundle ? getBundleId(selectedSatBundle) : ''; + const bundleSubText = selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; const { isLoading, @@ -104,10 +80,6 @@ function ConfirmOrdinalTransaction() { } = useMutation({ mutationFn: async ({ signedTx }) => btcClient.sendRawTransaction(signedTx), }); - const { selectedOrdinal } = useNftDataSelector(); - const { refetch } = useBtcWalletData(); - const [currentFee, setCurrentFee] = useState(fee); - const [currentFeeRate, setCurrentFeeRate] = useState(feePerVByte); useEffect(() => { setRecipientAddress(location.state.recipientAddress); @@ -142,6 +114,11 @@ function ConfirmOrdinalTransaction() { } }, [txError]); + const { isPartOfABundle } = useGetUtxoOrdinalBundle( + selectedOrdinal?.output, + hasActivatedRareSatsKey, + ); + const handleOnConfirmClick = (txHex: string) => { if (isLedgerAccount(selectedAccount)) { const txType: LedgerTransactionType = 'ORDINALS'; @@ -191,15 +168,22 @@ function ConfirmOrdinalTransaction() { onCancelClick={handleOnCancelClick} onBackButtonClick={handleOnCancelClick} ordinalTxUtxo={ordinalUtxo} - assetDetail={selectedOrdinal?.number.toString()} + assetDetail={bundleSubText ?? selectedOrdinal?.number.toString()} + assetDetailValue={bundleId ?? ''} currentFee={currentFee} setCurrentFee={setCurrentFee} currentFeeRate={currentFeeRate} setCurrentFeeRate={setCurrentFeeRate} + currencyType={isRareSat ? 'RareSat' : 'Ordinal'} + isPartOfBundle={isPartOfABundle} > - + {selectedSatBundle && isRareSat ? ( + + ) : ( + + )} diff --git a/src/app/screens/legalLinks/index.tsx b/src/app/screens/legalLinks/index.tsx index 349cc7a41..9e5f8b019 100644 --- a/src/app/screens/legalLinks/index.tsx +++ b/src/app/screens/legalLinks/index.tsx @@ -2,7 +2,7 @@ import LinkIcon from '@assets/img/linkIcon.svg'; import ActionButton from '@components/button'; import Separator from '@components/separator'; import useWalletSelector from '@hooks/useWalletSelector'; -import { CustomSwitch } from '@screens/ledger/importLedgerAccount/index.styled'; +import { CustomSwitch } from '@screens/ledger/importLedgerAccount/steps/index.styled'; import { PRIVACY_POLICY_LINK, TERMS_LINK } from '@utils/constants'; import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import { saveIsTermsAccepted } from '@utils/localStorage'; diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx new file mode 100644 index 000000000..9ac35a761 --- /dev/null +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -0,0 +1,220 @@ +import { Wrench } from '@phosphor-icons/react'; +import { StyledP, StyledTab, StyledTabList } from '@ui-library/common.styled'; +import { ApiBundle, Bundle, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { TabPanel, Tabs } from 'react-tabs'; +import styled from 'styled-components'; +import { MoonLoader } from 'react-spinners'; +import type { NftDashboardState } from '.'; +import Notice from './notice'; +import RareSatsTabGridItem from './rareSatsTabGridItem'; + +export const GridContainer = styled.div<{ + isGalleryOpen: boolean; +}>((props) => ({ + display: 'grid', + columnGap: props.isGalleryOpen ? props.theme.space.xl : props.theme.space.m, + rowGap: props.isGalleryOpen ? props.theme.space.xl : props.theme.space.l, + marginTop: props.theme.space.l, + gridTemplateColumns: props.isGalleryOpen + ? 'repeat(auto-fill,minmax(220px,1fr))' + : 'repeat(auto-fill,minmax(150px,1fr))', +})); + +const StyledTotalItems = styled(StyledP)` + margin-top: ${(props) => props.theme.space.s}; +`; + +const NoticeContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(8), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +})); + +const NoCollectiblesText = styled.div((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white['200'], + marginTop: props.theme.spacing(16), + textAlign: 'center', +})); + +const ErrorContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(20), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +})); + +const ErrorTextContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(8), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +})); + +const ErrorText = styled.div((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white['200'], +})); + +const LoaderContainer = styled.div((props) => ({ + display: 'flex', + flex: 1, + justifyContent: 'center', + alignItems: 'center', + marginTop: props.theme.spacing(12), +})); + +const LoadMoreButtonContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginBottom: props.theme.spacing(30), + marginTop: props.theme.space.xl, +})); + +const LoadMoreButton = styled.button((props) => ({ + ...props.theme.body_medium_l, + fontSize: 13, + width: 98, + height: 34, + color: props.theme.colors.white['0'], + border: `1px solid ${props.theme.colors.background.elevation3}`, + background: props.theme.colors.background.elevation0, + borderRadius: 24, + padding: '8px, 16px, 8px, 16px', + ':hover': { + background: props.theme.colors.background.elevation9, + }, + ':focus': { + background: props.theme.colors.background.elevation10, + }, +})); + +const tabNameToIndex = { + inscriptions: 0, + rareSats: 1, +}; + +const tabIndexToName = { + 0: 'inscriptions', + 1: 'rareSats', +}; + +export default function CollectiblesTabs({ + className, + nftListView, + nftDashboard, +}: { + className?: string; + nftListView: React.ReactNode; + nftDashboard: NftDashboardState; +}) { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); + const [tabIndex, setTabIndex] = useState(tabNameToIndex[searchParams?.get('tab') ?? ''] ?? 0); + const { + isGalleryOpen, + hasActivatedOrdinalsKey, + rareSatsQuery, + totalNfts, + hasActivatedRareSatsKey, + showNoticeAlert, + onDismissRareSatsNotice, + onLoadMoreRareSatsButtonClick, + } = nftDashboard; + + const handleSelectTab = (index: number) => { + setTabIndex(index); + }; + + useEffect(() => { + setSearchParams({ tab: tabIndexToName[tabIndex] }); + }, [tabIndex, setSearchParams]); + + const ordinalBundleCount = rareSatsQuery?.data?.pages?.[0]?.total || 0; + const showNoBundlesNotice = + ordinalBundleCount === 0 && !rareSatsQuery.isLoading && !rareSatsQuery.error; + + return ( + + {hasActivatedRareSatsKey && ( + + {t('NFTS')} + {t('RARE_SATS')} + + )} + + {totalNfts > 0 && ( + + {t('TOTAL_ITEMS', { total: totalNfts || 0 })} + + )} + {nftListView} + + + {ordinalBundleCount > 0 && ( + + {t('TOTAL_ITEMS', { total: ordinalBundleCount })} + + )} + + {showNoticeAlert && ( + + { + onDismissRareSatsNotice(); + }} + seeRarities={() => { + navigate('supported-rarity-scale'); + }} + /> + + )} + {showNoBundlesNotice && {t('NO_COLLECTIBLES')}} + + {!!rareSatsQuery.error && ( + + + + {t('ERROR_RETRIEVING')} + {t('TRY_AGAIN')} + + + )} + {rareSatsQuery.isLoading && ( + + + + )} + + {hasActivatedOrdinalsKey && + !rareSatsQuery.error && + !rareSatsQuery.isLoading && + rareSatsQuery.data?.pages + ?.map((page) => page?.results) + .flat() + .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) + .map((bundle: Bundle) => )} + + {rareSatsQuery.hasNextPage && ( + + {rareSatsQuery.isFetchingNextPage ? ( + + ) : ( + + {t('LOAD_MORE')} + + )} + + )} + + + ); +} diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index 3cc74d3f9..4938d5cc0 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -1,24 +1,29 @@ -import styled from 'styled-components'; -import { MoonLoader } from 'react-spinners'; -import useWalletSelector from '@hooks/useWalletSelector'; -import BottomTabBar from '@components/tabBar'; -import { useTranslation } from 'react-i18next'; -import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; -import ArrowDownLeft from '@assets/img/dashboard/arrow_down_left.svg'; -import ActionButton from '@components/button'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import BarLoader from '@components/barLoader'; -import { GAMMA_URL, LoaderSize } from '@utils/constants'; -import ShareDialog from '@components/shareNft'; +import FeatureIcon from '@assets/img/nftDashboard/rareSats/NewFeature.svg'; import AccountHeaderComponent from '@components/accountHeader'; -import Ordinal from '@screens/ordinals'; -import { ChangeActivateOrdinalsAction } from '@stores/wallet/actions/actionCreators'; -import { useDispatch } from 'react-redux'; -import { InscriptionsList } from '@secretkeylabs/xverse-core/types'; -import AlertMessage from '@components/alertMessage'; +import ActionButton from '@components/button'; +import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; +import BottomTabBar from '@components/tabBar'; +import WebGalleryButton from '@components/webGalleryButton'; import useAddressInscriptions from '@hooks/queries/ordinals/useAddressInscriptions'; +import { useAddressRareSats } from '@hooks/queries/ordinals/useAddressRareSats'; import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; -import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { ArrowDown, Wrench } from '@phosphor-icons/react'; +import Ordinal from '@screens/ordinals'; +import { InscriptionsList } from '@secretkeylabs/xverse-core/types'; +import { + ChangeActivateOrdinalsAction, + ChangeActivateRareSatsAction, + SetRareSatsNoticeDismissedAction, +} from '@stores/wallet/actions/actionCreators'; +import { useDispatch } from 'react-redux'; +import { StyledHeading } from '@ui-library/common.styled'; +import Dialog from '@ui-library/dialog'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { MoonLoader } from 'react-spinners'; +import styled from 'styled-components'; +import CollectiblesTabs, { GridContainer } from './collectiblesTabs'; import Nft from './nft'; import ReceiveNftModal from './receiveNft'; @@ -26,34 +31,33 @@ const Container = styled.div` display: flex; flex-direction: column; flex: 1; - margin-left: 5%; - margin-right: 5%; overflow-y: auto; - &::-webkit-scrollbar { - display: none; - } + ${(props) => props.theme.scrollbar} `; -interface GridContainerProps { - isGalleryOpen: boolean; -} -const GridContainer = styled.div((props) => ({ - display: 'grid', - columnGap: props.theme.spacing(8), - rowGap: props.theme.spacing(6), - marginTop: props.theme.spacing(14), - gridTemplateColumns: props.isGalleryOpen - ? 'repeat(auto-fill,minmax(300px,1fr))' - : 'repeat(auto-fill,minmax(150px,1fr))', - gridTemplateRows: props.isGalleryOpen ? 'repeat(minmax(300px,1fr))' : 'minmax(150px,220px)', -})); +const PageHeader = styled.div` + padding: ${(props) => props.theme.space.s}; + padding-bottom: ${(props) => props.theme.space.xl}; + border-bottom: 0.5px solid ${(props) => props.theme.colors.background.elevation3}; + max-width: 1224px; + margin-left: auto; + margin-right: auto; + width: 100%; +`; -const ShareDialogeContainer = styled.div({ - position: 'absolute', - top: 0, - right: 0, - zIndex: 2000, -}); +const StyledCollectiblesTabs = styled(CollectiblesTabs)` + margin-top: ${(props) => props.theme.spacing(8)}px; + padding: 0 ${(props) => props.theme.space.s}; + padding-bottom: ${(props) => props.theme.space.xl}; + max-width: 1224px; + margin-left: auto; + margin-right: auto; + width: 100%; +`; + +const StyledWebGalleryButton = styled(WebGalleryButton)` + margin-top: ${(props) => props.theme.space.s}; +`; const ReceiveNftContainer = styled.div((props) => ({ position: 'absolute', @@ -65,7 +69,6 @@ const ReceiveNftContainer = styled.div((props) => ({ })); const CollectibleContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(12), marginBottom: props.theme.spacing(12), })); @@ -83,76 +86,23 @@ const ButtonContainer = styled.div({ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - maxWidth: 400, + maxWidth: 360, }); -// const ShareButtonContainer = styled.div((props) => ({ -// marginLeft: props.theme.spacing(3), -// width: '100%', -// })); - -const ReceiveButtonContainer = styled.div((props) => ({ - marginRight: props.theme.spacing(3), +const ReceiveButtonContainer = styled.div(() => ({ width: '100%', })); -const WebGalleryButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-start', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - width: '100%', - marginTop: props.theme.spacing(8), - opacity: 0.8, - ':hover': { - opacity: 1, - }, -})); - -const WebGalleryButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 700, - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', -})); - const BottomBarContainer = styled.div({ marginTop: '5%', }); -const CollectiblesHeadingText = styled.h1((props) => ({ - ...props.theme.headline_category_s, - color: props.theme.colors.white['200'], - textTransform: 'uppercase', - letterSpacing: '0.02em', - opacity: 0.7, -})); - -const GalleryCollectiblesHeadingText = styled.h1((props) => ({ - ...props.theme.headline_category_m, - color: props.theme.colors.white['200'], - textTransform: 'uppercase', - letterSpacing: '0.02em', - opacity: 0.7, -})); - -const CollectiblesValueText = styled.h1((props) => ({ - ...props.theme.headline_xl, -})); - const LoadMoreButtonContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', alignItems: 'center', marginBottom: props.theme.spacing(30), + marginTop: props.theme.space.xl, })); const LoadMoreButton = styled.button((props) => ({ @@ -176,24 +126,68 @@ const LoadMoreButton = styled.button((props) => ({ const NoCollectiblesText = styled.h1((props) => ({ ...props.theme.body_bold_m, color: props.theme.colors.white['200'], - marginTop: 'auto', + marginTop: props.theme.spacing(16), marginBottom: 'auto', textAlign: 'center', })); -const BarLoaderContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(5), - maxWidth: 300, +const ErrorContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(20), display: 'flex', + flexDirection: 'column', + alignItems: 'center', })); -function NftDashboard() { +const ErrorTextContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(8), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +})); + +const ErrorText = styled.div((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white['200'], +})); + +export type NftDashboardState = { + openReceiveModal: boolean; + showNewFeatureAlert: boolean; + isOrdinalReceiveAlertVisible: boolean; + isLoading: boolean; + isLoadingOrdinals: boolean; + openInGalleryView: () => void; + onReceiveModalOpen: () => void; + onReceiveModalClose: () => void; + onOrdinalReceiveAlertOpen: () => void; + onOrdinalReceiveAlertClose: () => void; + NftListView: () => JSX.Element; + onActivateRareSatsAlertCrossPress: () => void; + onActivateRareSatsAlertDenyPress: () => void; + onActivateRareSatsAlertEnablePress: () => void; + onDismissRareSatsNotice: () => void; + isGalleryOpen: boolean; + hasActivatedOrdinalsKey?: boolean; + hasActivatedRareSatsKey?: boolean; + showNoticeAlert?: boolean; + rareSatsQuery: ReturnType; + totalNfts: number; + onLoadMoreRareSatsButtonClick: () => void; +}; + +const useNftDashboard = (): NftDashboardState => { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); const dispatch = useDispatch(); - const { stxAddress, ordinalsAddress, hasActivatedOrdinalsKey } = useWalletSelector(); - const [showShareNftOptions, setShowNftOptions] = useState(false); + const { + stxAddress, + ordinalsAddress, + hasActivatedOrdinalsKey, + hasActivatedRareSatsKey, + rareSatsNoticeDismissed, + } = useWalletSelector(); const [openReceiveModal, setOpenReceiveModal] = useState(false); - const [showActivateOrdinalsAlert, setShowActivateOrdinalsAlert] = useState(false); + const [showNewFeatureAlert, setShowNewFeatureAlert] = useState(false); + const [showNoticeAlert, setShowNoticeAlert] = useState(false); const [isOrdinalReceiveAlertVisible, setIsOrdinalReceiveAlertVisible] = useState(false); const { data: nftsList, @@ -214,10 +208,12 @@ function NftDashboard() { refetch: refetchOrdinals, } = useAddressInscriptions(); + const rareSatsQuery = useAddressRareSats(); + const refetchCollectibles = useCallback(async () => { await refetch(); await refetchOrdinals(); - }, [refetch]); + }, [refetch, refetchOrdinals]); useEffect(() => { refetchCollectibles(); @@ -238,10 +234,17 @@ function NftDashboard() { const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); useEffect(() => { - if (hasActivatedOrdinalsKey === undefined && ordinalsLength) { - setShowActivateOrdinalsAlert(true); + if ( + (hasActivatedOrdinalsKey === undefined && ordinalsLength) || + hasActivatedRareSatsKey === undefined + ) { + setShowNewFeatureAlert(true); } - }, [hasActivatedOrdinalsKey, ordinalsLength]); + }, [hasActivatedOrdinalsKey, hasActivatedRareSatsKey, ordinalsLength]); + + useEffect(() => { + setShowNoticeAlert(rareSatsNoticeDismissed === undefined); + }, [rareSatsNoticeDismissed]); const onLoadMoreButtonClick = () => { if (hasNextPageOrdinals) { @@ -282,124 +285,183 @@ function NftDashboard() { setIsOrdinalReceiveAlertVisible(false); }; - const NftListView = useCallback( - () => - totalNfts === 0 && ordinalsLength === 0 ? ( - {t('NO_COLLECTIBLES')} - ) : ( - <> - - {hasActivatedOrdinalsKey && !ordinalsError && ordinals?.pages?.map(renderOrdinalsList)} - {!stacksError && - nfts?.map((nft) => ( - - ))} - - {(hasNextPage || hasNextPageOrdinals) && ( - - {isFetchingNextPage || isFetchingNextPageOrdinals ? ( - - ) : ( - {t('LOAD_MORE')} - )} - - )} - - ), - [ordinals, nfts, hasActivatedOrdinalsKey], - ); + const NftListView = useCallback(() => { + if (stacksError || ordinalsError) { + return ( + + + + {t('ERROR_RETRIEVING')} + {t('TRY_AGAIN')} + + + ); + } - // const onSharePress = () => { - // setShowNftOptions(true); - // }; + if (totalNfts === 0 && ordinalsLength === 0) { + return {t('NO_COLLECTIBLES')}; + } - const onCrossPress = () => { - setShowNftOptions(false); - }; + return ( + <> + + {hasActivatedOrdinalsKey && !ordinalsError && ordinals?.pages?.map(renderOrdinalsList)} + {!stacksError && + nfts?.map((nft) => ( + + ))} + + {(hasNextPage || hasNextPageOrdinals) && ( + + {isFetchingNextPage || isFetchingNextPageOrdinals ? ( + + ) : ( + {t('LOAD_MORE')} + )} + + )} + + ); + }, [ordinals, nfts, hasActivatedOrdinalsKey, stacksError, ordinalsError]); - const onActivateOrdinalsAlertCrossPress = () => { - setShowActivateOrdinalsAlert(false); + const onActivateRareSatsAlertCrossPress = () => { + setShowNewFeatureAlert(false); }; - const onActivateOrdinalsAlertDenyPress = () => { - setShowActivateOrdinalsAlert(false); - dispatch(ChangeActivateOrdinalsAction(false)); + const onActivateRareSatsAlertDenyPress = () => { + setShowNewFeatureAlert(false); + dispatch(ChangeActivateOrdinalsAction(true)); + dispatch(ChangeActivateRareSatsAction(false)); }; - const onActivateOrdinalsAlertActivatePress = () => { - setShowActivateOrdinalsAlert(false); + const onActivateRareSatsAlertEnablePress = () => { + setShowNewFeatureAlert(false); dispatch(ChangeActivateOrdinalsAction(true)); + dispatch(ChangeActivateRareSatsAction(true)); + }; + + const onDismissRareSatsNotice = () => { + setShowNoticeAlert(false); + dispatch(SetRareSatsNoticeDismissedAction(true)); }; + const onLoadMoreRareSatsButtonClick = () => { + if (rareSatsQuery?.hasNextPage) { + rareSatsQuery.fetchNextPage(); + } + }; + + return { + openReceiveModal, + showNewFeatureAlert, + isOrdinalReceiveAlertVisible, + isLoading, + isLoadingOrdinals, + openInGalleryView, + onReceiveModalOpen, + onReceiveModalClose, + onOrdinalReceiveAlertOpen, + onOrdinalReceiveAlertClose, + NftListView, + onActivateRareSatsAlertCrossPress, + onActivateRareSatsAlertDenyPress, + onActivateRareSatsAlertEnablePress, + onDismissRareSatsNotice, + isGalleryOpen, + hasActivatedOrdinalsKey, + hasActivatedRareSatsKey, + showNoticeAlert, + rareSatsQuery, + totalNfts, + onLoadMoreRareSatsButtonClick, + }; +}; + +function NftDashboard() { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + const nftDashboard = useNftDashboard(); + const { + openReceiveModal, + showNewFeatureAlert, + hasActivatedOrdinalsKey, + isOrdinalReceiveAlertVisible, + isLoading, + isLoadingOrdinals, + openInGalleryView, + onReceiveModalOpen, + onReceiveModalClose, + onOrdinalReceiveAlertOpen, + onOrdinalReceiveAlertClose, + NftListView, + onActivateRareSatsAlertCrossPress, + onActivateRareSatsAlertDenyPress, + onActivateRareSatsAlertEnablePress, + isGalleryOpen, + } = nftDashboard; + return ( <> {isOrdinalReceiveAlertVisible && ( )} - {showActivateOrdinalsAlert && ( - } /> )} - + + - - {isGalleryOpen ? ( - {t('COLLECTIBLES')} - ) : ( - {t('COLLECTIBLES')} - )} - {ordinalsAddress && isLoadingOrdinals ? ( - - - - ) : ( - {`${totalNfts} ${t('ITEMS')}`} - )} - {!isGalleryOpen && ( - - <> - - {t('WEB_GALLERY')} - - - )} - - - - - - {openReceiveModal && ( - - + + + {t('COLLECTIBLES')} + + {!isGalleryOpen && } + + + + } + text={t('RECEIVE')} + onPress={onReceiveModalOpen} /> - - )} - {/* - - */} - - {showShareNftOptions && ( - + + {openReceiveModal && ( + + + )} - - + + {isLoading || isLoadingOrdinals ? ( ) : ( - + } nftDashboard={nftDashboard} /> )} diff --git a/src/app/screens/nftDashboard/nft.tsx b/src/app/screens/nftDashboard/nft.tsx index 08e9cf042..fc879fe8c 100644 --- a/src/app/screens/nftDashboard/nft.tsx +++ b/src/app/screens/nftDashboard/nft.tsx @@ -16,7 +16,7 @@ const NftNameText = styled.h1((props) => ({ textAlign: 'left', })); -const NftNameTextContainer = styled.h1((props) => ({ +const NftNameTextContainer = styled.div((props) => ({ width: '100%', display: 'flex', justifyContent: 'flex-start', @@ -35,35 +35,27 @@ const GradientContainer = styled.div((props) => ({ justifyContent: 'center', alignItems: 'center', borderRadius: 8, - background: 'linear-gradient(to bottom,#E5A78E, #EA603E, #4D52EF)', + background: props.theme.colors.elevation1, })); -const NftImageContainer = styled.div({ - flex: 1, +const NftImageContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', - alignItems: 'center', + alignItems: 'flex-start', width: '100%', overflow: 'hidden', -}); - -interface GridContainerProps { - showBorder: boolean; -} + borderRadius: 8, + background: props.theme.colors.elevation1, + flexGrow: props.isGalleryView ? 1 : 'initial', +})); -const GridItemContainer = styled.button((props) => ({ +const GridItemContainer = styled.button((props) => ({ display: 'flex', flexDirection: 'column', color: props.theme.colors.white['0'], - padding: props.showBorder ? props.theme.spacing(7) : 0, - marginBottom: props.theme.spacing(16), + padding: 0, borderRadius: props.theme.radius(3), - background: props.showBorder - ? 'linear-gradient(27.88deg, #1D2032 0%, rgba(29, 32, 50, 0) 100%)' - : 'transparent', - border: props.showBorder - ? ` 1px solid ${props.theme.colors.background.elevation2}` - : 'transparent', + background: 'transparent', })); function Nft({ asset, isGalleryOpen }: Props) { @@ -89,22 +81,19 @@ function Nft({ asset, isGalleryOpen }: Props) { navigate(`nft-detail/${url}`); } }; - const showNftImg = isGalleryOpen ? ( - - - - ) : ( - - ); return ( - + {asset.asset_identifier === BNS_CONTRACT ? ( - user + + user + ) : ( - showNftImg + + + )} {getName()} diff --git a/src/app/screens/nftDashboard/nftImage.tsx b/src/app/screens/nftDashboard/nftImage.tsx index 3283b2168..4016b6f26 100644 --- a/src/app/screens/nftDashboard/nftImage.tsx +++ b/src/app/screens/nftDashboard/nftImage.tsx @@ -13,12 +13,13 @@ interface ContainerProps { const ImageContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', - alignItems: props.isGalleryOpen ? 'center' : 'flex-start', + alignItems: 'center', width: '100%', height: props.isGalleryOpen ? '100%' : 150, overflow: 'hidden', position: 'relative', borderRadius: 8, + aspectRatio: '1', })); const LoaderContainer = styled.div((props) => ({ diff --git a/src/app/screens/nftDashboard/notice.tsx b/src/app/screens/nftDashboard/notice.tsx new file mode 100644 index 000000000..5c995910e --- /dev/null +++ b/src/app/screens/nftDashboard/notice.tsx @@ -0,0 +1,89 @@ +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; +import { XCircle, ArrowRight } from '@phosphor-icons/react'; +import { StyledHeading } from '@ui-library/common.styled'; +import Theme from 'theme'; + +const Container = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + borderRadius: 12, + background: props.theme.colors.elevation6_600, + padding: 16, + marginTop: 24, + width: '100%', +})); + +const Heading = styled(StyledHeading)` + flex: 1; +`; + +const Description = styled(StyledHeading)` + margin-top: ${(props) => props.theme.spacing(4)}px; + padding-right: ${(props) => props.theme.spacing(12)}px; +`; + +const RowContainer = styled.div({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', +}); + +const ButtonImage = styled.button({ + backgroundColor: 'transparent', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', +}); + +const BundleLinkContainer = styled.button((props) => ({ + display: 'inline-flex', + flexDirection: 'row', + alignItems: 'center', + marginTop: props.theme.spacing(4), + backgroundColor: 'transparent', + color: props.theme.colors.white_0, + transition: 'background-color 0.2s ease, opacity 0.2s ease', + ':hover': { + color: props.theme.colors.white_200 + }, +})); +const BundleLinkText = styled.div((props) => ({ + ...props.theme.body_medium_m, + marginRight: props.theme.spacing(1), +})); + +interface Props { + title: string; + description: string; + onClose?: () => void; + seeRarities?: () => void; +} + +function Notice({ title, description, onClose, seeRarities }: Props) { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + return ( + + + + {title} + + {onClose && ( + + + + )} + + + {description} + + + + {t('SEE_SUPPORTED')} + + + + ); +} +export default Notice; diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx new file mode 100644 index 000000000..eb8228b36 --- /dev/null +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -0,0 +1,70 @@ +import BundleAsset from '@components/bundleAsset/bundleAsset'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import { StyledP } from '@ui-library/common.styled'; +import { Bundle, getBundleId, getBundleSubText } from '@utils/rareSats'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; + +const InfoContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; +`; + +const StyledBundleId = styled(StyledP)` + text-align: left; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const StyledBundleSub = styled(StyledP)` + text-align: left; + text-overflow: ellipsis; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const GridItemContainer = styled.button` + display: flex; + flex-direction: column; + background: transparent; + gap: ${(props) => props.theme.space.s}; + width: 100%; +`; + +function RareSatsTabGridItem({ bundle }: { bundle: Bundle }) { + const navigate = useNavigate(); + const { setSelectedSatBundleDetails, setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); + const isMoreThanOneItem = bundle.items?.length > 1; + + const handleOnClick = () => { + setSelectedSatBundleDetails(bundle); + if (isMoreThanOneItem) { + return navigate('/nft-dashboard/rare-sats-bundle'); + } + + setSelectedSatBundleItemIndex(0); + navigate('/nft-dashboard/rare-sats-detail'); + }; + + const bundleId = getBundleId(bundle); + const bundleSubText = getBundleSubText(bundle); + + return ( + + + + + {bundleId} + + + {bundleSubText} + + + + ); +} +export default RareSatsTabGridItem; diff --git a/src/app/screens/nftDashboard/supportedRarities/index.tsx b/src/app/screens/nftDashboard/supportedRarities/index.tsx new file mode 100644 index 000000000..43cd55e69 --- /dev/null +++ b/src/app/screens/nftDashboard/supportedRarities/index.tsx @@ -0,0 +1,96 @@ +import { useTranslation } from 'react-i18next'; +import { ArrowUpRight } from '@phosphor-icons/react'; +import styled from 'styled-components'; +import TopRow from '@components/topRow'; +import { useNavigate } from 'react-router-dom'; +import { StyledP } from '@ui-library/common.styled'; +import { RareSats } from '@utils/rareSats'; +import { useMemo } from 'react'; +import { BLOG_LINK } from '@utils/constants'; +import Theme from 'theme'; +import RarityTile from './rarityTile'; + +interface ContainerProps { + isGallery?: boolean; +} + +const ContentContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + paddingRight: props.theme.spacing(8), + paddingLeft: props.theme.spacing(8), + paddingTop: props.theme.spacing(8), + overflowY: 'auto', + paddingBottom: props.theme.spacing(12), + flex: 1, +})); +const TopText = styled.h1((props) => ({ + ...props.theme.typography.body_m, + color: props.theme.colors.white_200, + marginTop: props.theme.spacing(8), +})); + +const TypesContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(6), +})); + +const ButtonImage = styled.button((props) => ({ + backgroundColor: 'transparent', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + marginTop: props.theme.spacing(6), +})); + +const Container = styled.div((props) => ({ + width: props.isGallery ? 580 : '100%', +})); + +const MainContainer = styled.div({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', + height: '100%', +}); + +const rarityTypes = RareSats.filter((rareSat) => rareSat !== 'common'); + +function SupportedRarities() { + const navigate = useNavigate(); + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + + const openLearnMoreLink = () => + window.open(`${BLOG_LINK}/rare-satoshis`, '_blank', 'noopener,noreferrer'); + + return ( + + + { + navigate(-1); + }} + /> + + {t('RARITY_DETAIL.RARITY_INFO')} + + + {t('RARITY_DETAIL.LEARN_MORE')} + + + + + + {rarityTypes.map((type) => ( + + ))} + + + + + ); +} +export default SupportedRarities; diff --git a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx new file mode 100644 index 000000000..dd5acb1a2 --- /dev/null +++ b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx @@ -0,0 +1,78 @@ +import { useTranslation } from 'react-i18next'; +import { ArrowUpRight } from '@phosphor-icons/react'; +import styled from 'styled-components'; +import { RareSatsType } from '@utils/rareSats'; +import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { MAGISAT_IO_RARITY_SCAN_URL } from '@utils/constants'; +import Theme from 'theme'; + +const Container = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + borderRadius: 12, + background: props.theme.colors.elevation1, + padding: props.theme.spacing(8), + marginTop: props.theme.spacing(6), +})); + +const TextsColumn = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + marginLeft: props.theme.spacing(6), +})); + +const RarityText = styled.p((props) => ({ + ...props.theme.typography.body_bold_m, + color: props.theme.colors.white[0], + textTransform: 'capitalize', +})); + +const RarityDetailText = styled.p((props) => ({ + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white[200], +})); + +const ButtonText = styled.p((props) => ({ + ...props.theme.typography.body_medium_m, + color: props.theme.colors.orange_main, + marginRight: props.theme.spacing(2), +})); + +const ButtonImage = styled.button((props) => ({ + backgroundColor: 'transparent', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + marginTop: props.theme.spacing(2), +})); + +interface Props { + type: RareSatsType; +} + +function RarityTile({ type }: Props) { + const { ordinalsAddress } = useWalletSelector(); + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + + const openScanLink = () => + window.open(`${MAGISAT_IO_RARITY_SCAN_URL}${ordinalsAddress}`, '_blank', 'noopener,noreferrer'); + + return ( + + + + {type} + {t(`RARITY_DETAIL.${type.toUpperCase()}`)} + {type === 'unknown' && ( + + {t('RARITY_DETAIL.SCAN')} + + + )} + + + ); +} +export default RarityTile; diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index bd3f5a4af..74bc1108c 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -7,7 +7,6 @@ import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import AccountHeaderComponent from '@components/accountHeader'; import AlertMessage from '@components/alertMessage'; import ActionButton from '@components/button'; -import InfoContainer from '@components/infoContainer'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; @@ -25,6 +24,9 @@ import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; +import { CubeTransparent, ArrowRight } from '@phosphor-icons/react'; +import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import OrdinalAttributeComponent from './ordinalAttributeComponent'; const Container = styled.div` @@ -258,6 +260,41 @@ const Text = styled.h1((props) => ({ marginLeft: props.theme.spacing(2), })); +const RareSatsBundleContainer = styled.div((props) => ({ + display: 'flex', + flex: 1, + flexDirection: 'row', + padding: props.theme.spacing(8), + marginBottom: props.theme.spacing(8), + border: `1px solid ${props.theme.colors.white_800}`, + borderRadius: '12px', +})); +const CubeTransparentIcon = styled(CubeTransparent)((props) => ({ + color: props.theme.colors.white_200, + marginRight: props.theme.spacing(8), +})); +const RareSatsBundleTextDescription = styled.div((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white_200, +})); +const BundleLinkContainer = styled.button((props) => ({ + display: 'inline-flex', + flexDirection: 'row', + alignItems: 'center', + marginTop: props.theme.spacing(4), + backgroundColor: 'transparent', + color: props.theme.colors.white_0, + transition: 'background-color 0.2s ease, opacity 0.2s ease', + ':hover': { + color: props.theme.colors.action.classicLight, + opacity: 0.6, + }, +})); +const BundleLinkText = styled.div((props) => ({ + ...props.theme.body_medium_m, + marginRight: props.theme.spacing(1), +})); + interface DetailSectionProps { isGallery: boolean; } @@ -277,11 +314,16 @@ function OrdinalDetailScreen() { const { selectedOrdinal } = useNftDataSelector(); const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); const { isPending, pendingTxHash } = usePendingOrdinalTxs(selectedOrdinal?.tx_id); - const [notSupportedOrdinal, setNotSupportedOrdinal] = useState(false); const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); const [isBrc20Ordinal, setIsBrc20Ordinal] = useState(false); const textContent = useTextOrdinalContent(selectedOrdinal!); const theme = useTheme(); + const { hasActivatedRareSatsKey } = useWalletSelector(); + const { bundle, isPartOfABundle } = useGetUtxoOrdinalBundle( + selectedOrdinal?.output, + hasActivatedRareSatsKey, + ); + const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); const isTransferValid = useMemo( @@ -291,18 +333,6 @@ function OrdinalDetailScreen() { useResetUserFlow('/ordinal-detail'); - useEffect(() => { - if (selectedOrdinal) { - if ( - selectedOrdinal?.content_type.includes('image') || - selectedOrdinal?.content_type.includes('text') || - textContent?.includes('brc-721e') - ) { - setNotSupportedOrdinal(false); - } else setNotSupportedOrdinal(true); - } - }, [selectedOrdinal?.content_type]); - useEffect(() => { if (textContent?.includes('brc-20')) { setIsBrc20Ordinal(true); @@ -404,7 +434,7 @@ function OrdinalDetailScreen() { const showBrc20OrdinalDetail = (isGallery: boolean) => { try { const regex = /”/g; - const validBrcContentValue = textContent.replace(regex, '"'); + const validBrcContentValue = (textContent ?? '').replace(regex, '"'); const content = JSON.parse(validBrcContentValue); switch (content.op) { @@ -484,6 +514,29 @@ function OrdinalDetailScreen() { } }; + const handleNavigationToRareSatsBundle = () => { + if (!bundle) { + return; + } + setSelectedSatBundleDetails(bundle); + navigate('/nft-dashboard/rare-sats-bundle'); + }; + + const rareSats = isPartOfABundle && ( + + +
+ + {t('RARE_SATS_BUNDLE_DESCRIPTION')} + + + {t('RARE_SATS_BUNDLE_LINK')} + + +
+
+ ); + const extensionView = ( @@ -507,13 +560,13 @@ function OrdinalDetailScreen() { - {notSupportedOrdinal && } arrow

{t('SEND')}

+ {rareSats} {isBrc20Ordinal ? showBrc20OrdinalDetail(false) : ownedByView}
); @@ -551,7 +604,7 @@ function OrdinalDetailScreen() { {t('DESCRIPTION')} - {notSupportedOrdinal && } + {rareSats} {isBrc20Ordinal ? showBrc20OrdinalDetail(true) : ordinalDescriptionData}
diff --git a/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx b/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx index e209b6b7b..38fcfa6fc 100644 --- a/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx +++ b/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx @@ -8,12 +8,14 @@ const Container = styled.div((props) => ({ flexDirection: 'column', alignItems: 'flex-start', marginTop: props.theme.spacing(8), + width: '100%', })); const RowContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', alignItems: 'flex-start', + width: '100%', })); const TitleText = styled.h1((props) => ({ @@ -24,12 +26,17 @@ const TitleText = styled.h1((props) => ({ interface ValueTextProps { color?: string; + fullWidth?: boolean; } -const ValueText = styled.h1((props) => ({ +const ValueText = styled.p((props) => ({ ...props.theme.body_medium_m, - textAlign: 'center', + textAlign: 'left', color: props.color || props.theme.colors.white[0], + width: props.fullWidth ? '100%' : 'auto', + overflowWrap: 'break-word', + wordWrap: 'break-word', + wordBreak: 'break-word', })); const OrdinalsTag = styled.div({ @@ -59,36 +66,51 @@ const Text = styled.h1((props) => ({ interface Props { title: string; - value: string; + value?: string; isAddress?: boolean; showOridnalTag?: boolean; valueColor?: string; + customValue?: React.ReactNode; + suffix?: string; } -function OrdinalAttributeComponent({ title, value, showOridnalTag, isAddress, valueColor }: Props) { +function OrdinalAttributeComponent({ + title, + value, + showOridnalTag, + isAddress, + valueColor, + customValue, + suffix, +}: Props) { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); return ( {title} - - {isAddress ? ( - {value} - ) : ( - {text}} - /> - )} - {showOridnalTag && ( - - - {t('ORDINALS')} - - )} - + {customValue ?? ( + + {isAddress ? ( + + {value} + + ) : ( + {text}} + suffix={suffix} + /> + )} + {showOridnalTag && ( + + + {t('ORDINALS')} + + )} + + )} ); } diff --git a/src/app/screens/ordinals/brc20Tile.tsx b/src/app/screens/ordinals/brc20Tile.tsx index 611ba82c1..6ff4a22cb 100644 --- a/src/app/screens/ordinals/brc20Tile.tsx +++ b/src/app/screens/ordinals/brc20Tile.tsx @@ -11,14 +11,17 @@ interface ContainerProps { isSmallImage?: boolean; } -const ImageContainer = styled.div(() => ({ +const ImageContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', width: '100%', height: '100%', - backgroundColor: '#1b1e2b', + backgroundColor: props.theme.colors.elevation1, borderRadius: 8, flexDirection: 'column', + '> img': { + width: '100%', + }, })); const BRC20Container = styled.div({ @@ -71,12 +74,12 @@ const TickerIconText = styled.h1((props) => ({ fontSize: 10, })); -const OrdinalsTag = styled.div({ +const OrdinalsTag = styled.div((props) => ({ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', - background: 'rgba(39, 42, 68, 0.6)', + background: props.theme.colors.elevation1, borderRadius: 40, width: 79, height: 22, @@ -85,7 +88,7 @@ const OrdinalsTag = styled.div({ zIndex: 1000, position: 'absolute', padding: '3px 6px', -}); +})); const ButtonIcon = styled.img({ width: 12, height: 12, diff --git a/src/app/screens/ordinals/index.tsx b/src/app/screens/ordinals/index.tsx index 97194a31a..223b4c765 100644 --- a/src/app/screens/ordinals/index.tsx +++ b/src/app/screens/ordinals/index.tsx @@ -15,14 +15,14 @@ const NftNameText = styled.h1((props) => ({ textAlign: 'left', })); -const NftNameTextContainer = styled.h1((props) => ({ +const NftNameTextContainer = styled.div((props) => ({ width: '100%', display: 'flex', justifyContent: 'flex-start', marginTop: props.theme.spacing(6), })); -const NftImageContainer = styled.div({ +const NftImageContainer = styled.div((props) => ({ flex: 1, display: 'flex', justifyContent: 'center', @@ -30,25 +30,17 @@ const NftImageContainer = styled.div({ width: '100%', aspectRatio: '1', overflow: 'hidden', -}); - -interface GridContainerProps { - showBorder: boolean; -} + borderRadius: props.theme.radius(3), + background: props.theme.colors.elevation1, +})); -const GridItemContainer = styled.button((props) => ({ +const GridItemContainer = styled.button((props) => ({ display: 'flex', flexDirection: 'column', color: props.theme.colors.white['0'], - padding: props.showBorder ? props.theme.spacing(7) : 0, - marginBottom: props.theme.spacing(16), + padding: 0, borderRadius: props.theme.radius(3), - background: props.showBorder - ? 'linear-gradient(27.88deg, #1D2032 0%, rgba(29, 32, 50, 0) 100%)' - : 'transparent', - border: props.showBorder - ? ` 1px solid ${props.theme.colors.background.elevation2}` - : 'transparent', + background: 'transparent', })); function Ordinal({ asset, isGalleryOpen }: Props) { @@ -58,11 +50,11 @@ function Ordinal({ asset, isGalleryOpen }: Props) { const handleOnClick = () => { setSelectedOrdinalDetails(asset); - navigate('ordinal-detail'); + navigate('/nft-dashboard/ordinal-detail'); }; return ( - + {isGalleryOpen ? ( diff --git a/src/app/screens/ordinals/ordinalImage.tsx b/src/app/screens/ordinals/ordinalImage.tsx index 0162a4f4c..f7cc4dae1 100644 --- a/src/app/screens/ordinals/ordinalImage.tsx +++ b/src/app/screens/ordinals/ordinalImage.tsx @@ -27,8 +27,11 @@ const ImageContainer = styled.div((props) => ({ position: 'relative', fontSize: '3em', wordWrap: 'break-word', - backgroundColor: '#1b1e2b', + backgroundColor: props.theme.colors.elevation1, borderRadius: 8, + '> img': { + width: '100%', + }, })); const FillImg = styled.img(() => ({ @@ -41,12 +44,12 @@ const ButtonIcon = styled.img({ height: 12, }); -const OrdinalsTag = styled.div({ +const OrdinalsTag = styled.div((props) => ({ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', - background: 'rgba(39, 42, 68, 0.6)', + background: props.theme.colors.elevation1, borderRadius: 40, width: 79, height: 22, @@ -55,7 +58,7 @@ const OrdinalsTag = styled.div({ zIndex: 1000, position: 'absolute', padding: '3px 6px', -}); +})); const LoaderContainer = styled.div((props) => ({ display: 'flex', @@ -85,20 +88,30 @@ interface TextProps { isSmall?: boolean; blur?: boolean; withoutSizeIncrease?: boolean; + isGalleryOpen?: boolean; } -const OrdinalContentText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white[0], - fontSize: props.inNftSend || props.withoutSizeIncrease ? 15 : 'calc(0.8vw + 2vh)', - overflow: 'hidden', - textAlign: 'center', - filter: `blur(${props.blur ? '3px' : 0})`, - textOverflow: 'ellipsis', - display: '-webkit-box', - '-webkit-line-clamp': '4', - '-webkit-box-orient': 'vertical', -})); +const OrdinalContentText = styled.p((props) => { + let fontSize = 'calc(0.8vw + 2vh)'; + if (props.isSmall) { + fontSize = 'calc(2vw)'; + } else if (props.inNftSend || props.withoutSizeIncrease) { + fontSize = '15px'; + } + return { + ...props.theme.body_medium_m, + color: props.theme.colors.white[0], + fontSize, + overflow: 'hidden', + textAlign: 'center', + filter: `blur(${props.blur ? '3px' : 0})`, + textOverflow: 'ellipsis', + display: '-webkit-box', + '-webkit-line-clamp': '4', + '-webkit-box-orient': 'vertical', + margin: props.isGalleryOpen ? props.theme.space.xxl : props.theme.space.xs, + }; +}); const StyledImage = styled(Image)` border-radius: 8px; @@ -237,6 +250,7 @@ function OrdinalImage({ inNftSend={inNftSend} isSmall={isSmallImage} withoutSizeIncrease={withoutSizeIncrease} + isGalleryOpen={isGalleryOpen} > {textContent} diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx new file mode 100644 index 000000000..20d0298fa --- /dev/null +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -0,0 +1,284 @@ +import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; +import AccountHeaderComponent from '@components/accountHeader'; +import AlertMessage from '@components/alertMessage'; +import ActionButton from '@components/button'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; +import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; +import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import WebGalleryButton from '@components/webGalleryButton'; +import { BundleItem } from '@utils/rareSats'; +import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; +import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; +import { RareSatsBundleGridItem } from './rareSatsBundleGridItem'; + +interface DetailSectionProps { + isGalleryOpen?: boolean; +} + +/* layout */ +const Container = styled.div` + overflow-y: auto; +`; + +const PageHeader = styled.div` + padding: ${(props) => props.theme.space.m}; + padding-top: 0; + max-width: 1224px; + margin-top: ${(props) => (props.isGalleryOpen ? props.theme.space.xxl : props.theme.space.l)}; + margin-left: auto; + margin-right: auto; + width: 100%; +`; + +// TODO tim: use media queries for this once we get responsive layouts with breakpoints +const PageHeaderContent = styled.div` + display: flex; + flex-direction: ${(props) => (props.isGalleryOpen ? 'row' : 'column')}; + justify-content: ${(props) => (props.isGalleryOpen ? 'space-between' : 'initial')}; + row-gap: ${(props) => props.theme.space.xl}; +`; + +const AttributesContainer = styled.div` + max-width: 285px; +`; + +const StyledSeparator = styled.hr` + margin-top: ${(props) => props.theme.space.m}; + margin-bottom: ${(props) => props.theme.space.xxl}; + border: none; + border-top: 1px solid ${(props) => props.theme.colors.elevation3}; +`; + +const StyledGridContainer = styled(GridContainer)` + margin-top: ${(props) => props.theme.spacing(8)}px; + padding: 0 ${(props) => props.theme.space.m}; + padding-bottom: ${(props) => props.theme.space.xl}; + max-width: 1224px; + margin-left: auto; + margin-right: auto; + width: 100%; +`; + +/* components */ + +const StyledWebGalleryButton = styled(WebGalleryButton)` + color: ${(props) => props.theme.colors.white_200}; + margin-top: ${(props) => props.theme.space.xs}; +`; + +const SendButtonContainer = styled.div` + margin-top: ${(props) => props.theme.space.l}; + width: ${(props) => (props.isGalleryOpen ? '222px' : '155px')}; +`; + +const BundleRarityLinkContainer = styled.button` + margin-top: ${(props) => props.theme.space.l}; + display: flex; + justify-content: flex-start; + align-items: center; + gap: ${(props) => props.theme.space.xxs}; + background-color: transparent; + color: ${(props) => props.theme.colors.white_200}; + :hover:enabled { + color: ${(props) => props.theme.colors.white_200}; + } + :active ; + :disabled { + color: ${(props) => props.theme.colors.white_400}; + } + svg { + flex-grow: 0; + flex-shrink: 0; + } +`; + +const BackButtonContainer = styled.div` + display: flex; + flex-direction: row; + margin-bottom: ${(props) => props.theme.space.xxl}; +`; + +const ButtonImage = styled.img((props) => ({ + marginRight: props.theme.spacing(3), + alignSelf: 'center', + transform: 'all', +})); + +const Button = styled.button((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center', + background: 'transparent', + marginBottom: props.theme.spacing(12), +})); + +const AssetDetailButtonText = styled.div((props) => ({ + ...props.theme.body_xs, + fontWeight: 400, + fontSize: 14, + color: props.theme.colors.white['0'], + textAlign: 'center', +})); + +const NoCollectiblesText = styled.p((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white_200, + marginTop: props.theme.spacing(16), + marginBottom: 'auto', + textAlign: 'center', +})); + +function RareSatsBundle() { + const { t } = useTranslation('translation'); + const navigate = useNavigate(); + const { network, selectedAccount } = useWalletSelector(); + const { selectedSatBundle: bundle } = useNftDataSelector(); + const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle?.txid); + const [showSendOrdinalsAlert, setShowSendOrdinalsAlert] = useState(false); + const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); + + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + + useResetUserFlow('/rare-sats-bundle'); + + const handleBackButtonClick = () => { + navigate('/nft-dashboard?tab=rareSats'); + setSelectedSatBundleDetails(null); + }; + + const openInGalleryView = async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL('options.html#/nft-dashboard/rare-sats-bundle'), + }); + }; + + const onCloseAlert = () => { + setShowSendOrdinalsAlert(false); + }; + + const handleSendOrdinal = async () => { + if (isPending) { + return setShowSendOrdinalsAlert(true); + } + + if (isLedgerAccount(selectedAccount)) { + await chrome.tabs.create({ + url: chrome.runtime.getURL('options.html#/nft-dashboard/send-rare-sat'), + }); + return; + } + + navigate('/nft-dashboard/send-rare-sat'); + }; + + const handleRedirectToTx = () => { + if (pendingTxHash) { + window.open(getBtcTxStatusUrl(pendingTxHash, network), '_blank', 'noopener,noreferrer'); + } + }; + + const handleRarityScale = () => { + navigate('/nft-dashboard/supported-rarity-scale'); + }; + + const isEmpty = !bundle?.items?.length; + + return ( + <> + {isGalleryOpen ? ( + + ) : ( + + )} + + + {isGalleryOpen && ( + + + + )} + +
+ + {t('RARE_SATS.RARE_SATS_BUNDLE')} + + + {t('NFT_DASHBOARD_SCREEN.TOTAL_ITEMS', { total: bundle?.items?.length })} + + {!isGalleryOpen && } + + } + text={t('COMMON.SEND')} + onPress={handleSendOrdinal} + /> + + + + {t('RARE_SATS.RARITY_LINK_TEXT')} + + + +
+ + + + +
+
+ {isGalleryOpen && } + {isEmpty && ( + {t('NFT_DASHBOARD_SCREEN.NO_COLLECTIBLES')} + )} + + {bundle?.items?.map((item: BundleItem, index) => ( + + ))} + + {showSendOrdinalsAlert && ( + + )} +
+ {!isGalleryOpen && } + + ); +} + +export default RareSatsBundle; diff --git a/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx new file mode 100644 index 000000000..966e850b2 --- /dev/null +++ b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx @@ -0,0 +1,87 @@ +import { StyledP } from '@ui-library/common.styled'; +import { BundleItem, getBundleItemId, getBundleItemSubText } from '@utils/rareSats'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; + +const InfoContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; +`; + +const StyledItemId = styled(StyledP)` + text-align: left; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const StyledItemSub = styled(StyledP)` + text-align: left; + text-overflow: ellipsis; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const ImageContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + aspect-ratio: 1; + overflow: hidden; + border-radius: ${(props) => props.theme.radius(3)}px; + background: ${(props) => props.theme.colors.elevation1}; +`; + +const GridItemContainer = styled.button` + display: flex; + flex-direction: column; + background: transparent; + gap: ${(props) => props.theme.space.s}; +`; + +export function RareSatsBundleGridItem({ + item, + itemIndex, +}: { + item: BundleItem; + itemIndex: number; +}) { + const navigate = useNavigate(); + const { setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); + const { selectedSatBundle } = useNftDataSelector(); + + const handleOnClick = () => { + setSelectedSatBundleItemIndex(itemIndex); + navigate('/nft-dashboard/rare-sats-detail'); + }; + + const itemId = getBundleItemId(selectedSatBundle!, itemIndex); + const itemSubText = getBundleItemSubText({ + satType: item.type, + rareSatsType: item.rarity_ranking, + }); + + return ( + + + + + + + {itemId} + + + {itemSubText} + + + + ); +} +export default RareSatsBundleGridItem; diff --git a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx new file mode 100644 index 000000000..f9c3bfdad --- /dev/null +++ b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx @@ -0,0 +1,489 @@ +import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; +import AccountHeaderComponent from '@components/accountHeader'; +import AlertMessage from '@components/alertMessage'; +import ActionButton from '@components/button'; +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import WebGalleryButton from '@components/webGalleryButton'; +import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { Circle, ArrowRight, ArrowUp } from '@phosphor-icons/react'; +import Callout from '@ui-library/callout'; +import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; +import { getBtcTxStatusUrl, getTruncatedAddress, isLedgerAccount } from '@utils/helper'; +import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useLocation } from 'react-router-dom'; +import styled from 'styled-components'; +import { + getBundleItemId, + getRareSatsColorsByRareSatsType, + getRareSatsLabelByType, + getRarityLabelByRareSatsType, + getBundleItemSubText, + BundleItem, +} from '@utils/rareSats'; +import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; + +interface DetailSectionProps { + isGalleryOpen?: boolean; +} + +const Container = styled.div` + display: flex; + flex-direction: column; + flex: 1; + overflow-y: auto; + margin-left: 5%; + margin-right: 5%; + &::-webkit-scrollbar { + display: none; + } +`; + +const SendButtonContainer = styled.div` + width: ${(props) => (props.isGalleryOpen ? '222px' : '155px')}; +`; + +const BackButtonContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + marginTop: props.theme.spacing(40), +})); + +const ExtensionContainer = styled.div({ + display: 'flex', + flexDirection: 'column', + marginTop: 8, + marginBottom: 40, + alignItems: 'center', + flex: 1, +}); + +const RareSatsContainer = styled.div((props) => ({ + maxWidth: 450, + width: '60%', + display: 'flex', + aspectRatio: '1', + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'flex-start', + borderRadius: 8, + marginBottom: props.theme.spacing(12), +})); + +const ExtensionRareSatsContainer = styled.div<{ isInscription?: boolean }>((props) => ({ + maxHeight: props.isInscription ? 148 : 64, + width: props.isInscription ? 148 : 64, + display: 'flex', + aspectRatio: '1', + justifyContent: 'center', + alignItems: 'center', + borderRadius: 8, + marginBottom: props.theme.spacing(12), + marginTop: props.theme.spacing(12), +})); + +const RareSatsTitleText = styled.h1((props) => ({ + ...props.theme.headline_m, + color: props.theme.colors.white['0'], + textAlign: 'center', +})); + +const RareSatsGalleryTitleText = styled.p((props) => ({ + ...props.theme.headline_l, + color: props.theme.colors.white['0'], + marginBottom: props.theme.spacing(12), +})); + +const DescriptionText = styled.p((props) => ({ + ...props.theme.headline_l, + color: props.theme.colors.white['0'], + fontSize: 24, + marginBottom: props.theme.spacing(16), +})); + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const RowContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'flex-start', + marginTop: props.theme.spacing(6), + flexDirection: 'row', +})); + +const ColumnContainer = styled.div({ + display: 'flex', + alignItems: 'flex-start', + flexDirection: 'column', + width: '100%', +}); + +const DescriptionContainer = styled.div((props) => ({ + display: 'flex', + flex: 1, + marginLeft: props.theme.spacing(20), + flexDirection: 'column', + marginBottom: props.theme.spacing(30), +})); + +const StyledWebGalleryButton = styled(WebGalleryButton)` + color: ${(props) => props.theme.colors.white_200}; + margin-top: ${(props) => props.theme.space.xs}; +`; + +const ButtonImage = styled.img((props) => ({ + marginRight: props.theme.spacing(3), + alignSelf: 'center', + transform: 'all', +})); + +const Button = styled.button((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center', + background: 'transparent', + marginBottom: props.theme.spacing(12), +})); + +const AssetDetailButtonText = styled.div((props) => ({ + ...props.theme.body_xs, + fontWeight: 400, + fontSize: 14, + color: props.theme.colors.white['0'], + textAlign: 'center', +})); + +const SatTypeText = styled.p((props) => ({ + ...props.theme[props.isGalleryOpen ? 'body_bold_l' : 'body_bold_m'], + color: props.theme.colors.white['400'], + textAlign: props.isGalleryOpen ? 'left' : 'center', + textTransform: 'capitalize', +})); + +const DetailSection = styled.div((props) => ({ + display: 'flex', + flexDirection: !props.isGalleryOpen ? 'row' : 'column', + justifyContent: 'space-between', + width: '100%', +})); + +const RareSatRankingBadge = styled.div<{ bgColor: string }>((props) => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + borderRadius: '30px', + backgroundColor: props.bgColor, + marginTop: props.theme.spacing(1), + padding: '5px 10px', +})); + +const RareSatRankingBadgeText = styled.div((props) => ({ + ...props.theme.body_medium_s, + marginLeft: props.theme.spacing(4), +})); + +const StyledCallout = styled(Callout)((props) => ({ + marginBottom: props.theme.space.l, +})); + +const BundleRarityLinkContainer = styled.button((props) => ({ + marginTop: props.isGalleryOpen ? props.theme.space.l : props.theme.space.m, + display: 'inline-flex', + alignSelf: props.isGalleryOpen ? 'flex-start' : 'center', + flexDirection: 'row', + marginBottom: props.isGalleryOpen ? props.theme.spacing(14) : 0, + alignItems: 'center', + backgroundColor: 'transparent', + color: props.theme.colors.white_0, + transition: 'background-color 0.2s ease, opacity 0.2s ease', + ':hover': { + color: props.theme.colors.action.classicLight, + opacity: 0.6, + }, +})); +const BundleRarityTextLink = styled.p((props) => ({ + ...props.theme.body_medium_m, + color: props.theme.colors.white_200, + marginRight: props.theme.spacing(1), +})); +const ArrowRightIcon = styled(ArrowRight)((props) => ({ + color: props.theme.colors.white_200, +})); +const Divider = styled.div((props) => ({ + width: '100%', + height: '1px', + backgroundColor: props.theme.colors.white_900, + marginTop: props.theme.spacing(20), + marginBottom: props.theme.spacing(4), +})); +const Flex1 = styled.div(() => ({ + flex: 1, + width: '100%', +})); +const ViewInExplorerButton = styled.button((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'transparent', + marginTop: props.theme.space.xxl, + width: '100%', +})); + +function RareSatsDetailScreen() { + const { t } = useTranslation('translation'); + const navigate = useNavigate(); + const location = useLocation(); + const { ordinalsAddress, network, selectedAccount } = useWalletSelector(); + const { selectedSatBundle, selectedSatBundleItemIndex } = useNftDataSelector(); + const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); + const { setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); + useResetUserFlow('/rare-sats-detail'); + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + + const bundle = selectedSatBundle!; + const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle.txid); + + const itemIndex = selectedSatBundleItemIndex!; + const item = bundle.items[itemIndex] as BundleItem | undefined; + // when going back, selectedSatBundleItemIndex is set tu null and we don't want to render anything + if (!item) { + return null; + } + + const isBundle = bundle.items.length < 2; + const isUnknown = item?.type === 'unknown'; + const isInscription = item?.type === 'inscription' || item?.type === 'inscribed-sat'; + + const handleBackButtonClick = () => { + // only go back if there is history + if (location.key !== 'default') { + navigate(-1); + } else { + navigate('/nft-dashboard?tab=rareSats'); + } + setSelectedSatBundleItemIndex(null); + }; + + const openInGalleryView = async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL('options.html#/nft-dashboard/rare-sats-detail'), + }); + }; + + const showAlert = () => { + setshowSendOridnalsAlert(true); + }; + + const onCloseAlert = () => { + setshowSendOridnalsAlert(false); + }; + + const handleSendRareSats = async () => { + if (isPending) { + return showAlert(); + } + + if (isLedgerAccount(selectedAccount)) { + await chrome.tabs.create({ + url: chrome.runtime.getURL('options.html#/nft-dashboard/send-rare-sat'), + }); + return; + } + + navigate('/nft-dashboard/send-rare-sat'); + }; + + const handleRedirectToTx = () => { + if (pendingTxHash) { + window.open(getBtcTxStatusUrl(pendingTxHash, network), '_blank', 'noopener,noreferrer'); + } + }; + + const handleRarityScale = () => { + navigate('/nft-dashboard/supported-rarity-scale'); + }; + + const openInOrdinalsExplorer = () => { + if (!isInscription) { + return; + } + window.open(`${XVERSE_ORDIVIEW_URL}/inscription/${item.inscription.id}`); + }; + + const { color, backgroundColor } = getRareSatsColorsByRareSatsType(item.rarity_ranking); + + const satsRanking = ( + + + + {getRareSatsLabelByType(item.rarity_ranking)} + + + } + /> + ); + const satsValue = ( + + ); + const satsRarity = ( + + ); + const ownedBy = ( + + ); + const id = ( + + ); + const title = getBundleItemId(bundle, itemIndex); + const sendActionSection = isBundle ? ( + <> + + } + text={t('COMMON.SEND')} + onPress={handleSendRareSats} + /> + + + {t('RARE_SATS.RARITY_LINK_TEXT')} + + + + ) : ( + + ); + + const extensionView = ( + + + {getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking })} + + {title} + + + + + {sendActionSection} + + + + {!isUnknown && {satsRanking}} + {isBundle ? satsValue : satsRarity} + + + {!isUnknown && isBundle && {satsRarity}} + {isUnknown ? id : ownedBy} + + + {isInscription && ( + + + + )} + + ); + + const galleryView = ( + + + + + + {getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking })} + + {title} + {sendActionSection} + + + + + + {t('NFT_DETAIL_SCREEN.DESCRIPTION')} + + + {!isUnknown && {satsRanking}} + {isBundle ? satsValue : satsRarity} + + + {!isUnknown && isBundle && {satsRarity}} + {isUnknown ? id : ownedBy} + + + {isInscription && ( + + + + )} + + + + ); + + return ( + <> + {isGalleryOpen ? ( + + ) : ( + + )} + + {showSendOridnalsAlert && ( + + )} + {isGalleryOpen && selectedSatBundle !== null ? galleryView : extensionView} + + {!isGalleryOpen && ( + + + + )} + + ); +} + +export default RareSatsDetailScreen; diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index 022825b53..f2059638c 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -123,7 +123,7 @@ function SendOrdinal() { data, error: txError, mutate, - } = useMutation({ + } = useMutation({ mutationFn: async (recipient) => { const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); const ordUtxo = addressUtxos.find( diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx new file mode 100644 index 000000000..d2988aac4 --- /dev/null +++ b/src/app/screens/sendRareSat/index.tsx @@ -0,0 +1,258 @@ +import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; +import AccountHeaderComponent from '@components/accountHeader'; +import SendForm from '@components/sendForm'; +import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useBtcClient from '@hooks/useBtcClient'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; +import { + SignedBtcTx, + signOrdinalSendTransaction, +} from '@secretkeylabs/xverse-core/transactions/btc'; +import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; +import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; +import { useMutation } from '@tanstack/react-query'; +import { isLedgerAccount } from '@utils/helper'; +import { getBundleSubText, getBundleId } from '@utils/rareSats'; +import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import styled from 'styled-components'; +import BundleAsset from '@components/bundleAsset/bundleAsset'; + +const ScrollContainer = styled.div` + display: flex; + flex: 1; + flex-direction: column; + overflow-y: auto; + &::-webkit-scrollbar { + display: none; + } + width: 360px; + margin: auto; +`; + +const Container = styled.div({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + flex: 1, +}); + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const ButtonContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + marginLeft: '15%', + marginTop: props.theme.spacing(40), +})); + +const Button = styled.button((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-end', + alignItems: 'center', + borderRadius: props.theme.radius(1), + backgroundColor: 'transparent', + opacity: 0.8, + marginTop: props.theme.spacing(5), +})); + +const ButtonText = styled.div((props) => ({ + ...props.theme.body_xs, + fontWeight: 400, + fontSize: 14, + color: props.theme.colors.white['0'], + textAlign: 'center', +})); + +const ButtonImage = styled.img((props) => ({ + marginRight: props.theme.spacing(3), + alignSelf: 'center', + transform: 'all', +})); + +const BundleAssetContainer = styled.div((props) => ({ + maxHeight: 148, + width: 148, + display: 'flex', + aspectRatio: 1, + justifyContent: 'center', + alignItems: 'center', + borderRadius: 8, + marginTop: props.theme.spacing(8), + marginBottom: props.theme.spacing(6), +})); + +function SendOrdinal() { + const { t } = useTranslation('translation'); + const navigate = useNavigate(); + const { selectedSatBundle } = useNftDataSelector(); + const btcClient = useBtcClient(); + const location = useLocation(); + const { network, ordinalsAddress, btcAddress, selectedAccount, seedPhrase, btcFiatRate } = + useWalletSelector(); + const [ordinalUtxo, setOrdinalUtxo] = useState(undefined); + const [error, setError] = useState(''); + const [recipientAddress, setRecipientAddress] = useState(''); + const [warning, setWarning] = useState(''); + useResetUserFlow('/send-rare-sat'); + + const address: string | undefined = useMemo( + () => (location.state ? location.state.recipientAddress : undefined), + [location.state], + ); + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + + const signTransaction = async (recipient: string) => { + const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); + const ordUtxo = addressUtxos.find( + (utxo) => + `${utxo.txid}:${utxo.vout}` === `${selectedSatBundle?.txid}:${selectedSatBundle?.vout}`, + ); + setOrdinalUtxo(ordUtxo); + if (ordUtxo) { + const signedTx = await signOrdinalSendTransaction( + recipient, + ordUtxo, + btcAddress, + Number(selectedAccount?.id), + seedPhrase, + network.type, + [ordUtxo], + ); + + return signedTx; + } + }; + + const { + isLoading, + data, + error: txError, + mutate, + } = useMutation({ + mutationFn: signTransaction, + }); + + useEffect(() => { + if (data) { + navigate(`/confirm-ordinal-tx/${selectedSatBundle?.txid}`, { + state: { + signedTxHex: data.signedTx, + recipientAddress, + fee: data.fee, + feePerVByte: data.feePerVByte, + fiatFee: getBtcFiatEquivalent(data.fee, btcFiatRate), + total: data.total, + fiatTotal: getBtcFiatEquivalent(data.total, btcFiatRate), + ordinalUtxo, + isRareSat: true, + }, + }); + } + }, [data]); // eslint-disable-line react-hooks/exhaustive-deps + + useEffect(() => { + if (txError) { + if (Number(txError) === ErrorCodes.InSufficientBalance) { + setError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); + } else if (Number(txError) === ErrorCodes.InSufficientBalanceWithTxFee) { + setError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); + } else setError(txError.toString()); + } + }, [txError]); // eslint-disable-line react-hooks/exhaustive-deps + + const handleBackButtonClick = () => { + navigate(-1); + }; + + function validateFields(associatedAddress: string): boolean { + if (!associatedAddress) { + setError(t('SEND.ERRORS.ADDRESS_REQUIRED')); + return false; + } + + if (!validateBtcAddress({ btcAddress: associatedAddress, network: network.type })) { + setError(t('SEND.ERRORS.ADDRESS_INVALID')); + return false; + } + + return true; + } + + const onPressNext = async (associatedAddress: string) => { + setRecipientAddress(associatedAddress); + if (validateFields(associatedAddress)) { + mutate(associatedAddress); + } + }; + + const handleInputChange = (inputAddress: string) => { + if (inputAddress === ordinalsAddress) { + return setWarning(t('SEND.YOU_ARE_TRANSFERRING_TO_YOURSELF')); + } + setWarning(''); + }; + + const heading = selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; + const subText = selectedSatBundle ? getBundleId(selectedSatBundle) : ''; + + return ( + <> + {isGalleryOpen && ( + <> + + {!isLedgerAccount(selectedAccount) && ( + + + + )} + + )} + + {!isGalleryOpen && } + + + + + + + {heading} + + + {subText} + + + + {!isGalleryOpen && } + + + ); +} + +export default SendOrdinal; diff --git a/src/app/screens/settings/index.tsx b/src/app/screens/settings/index.tsx index 5752e2627..c9f375768 100644 --- a/src/app/screens/settings/index.tsx +++ b/src/app/screens/settings/index.tsx @@ -11,7 +11,10 @@ import { useState } from 'react'; import PasswordInput from '@components/passwordInput'; import useWalletReducer from '@hooks/useWalletReducer'; import { useDispatch } from 'react-redux'; -import { ChangeActivateOrdinalsAction } from '@stores/wallet/actions/actionCreators'; +import { + ChangeActivateOrdinalsAction, + ChangeActivateRareSatsAction, +} from '@stores/wallet/actions/actionCreators'; import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; import { isLedgerAccount } from '@utils/helper'; import ResetWalletPrompt from '../../components/resetWallet'; @@ -57,7 +60,13 @@ function Setting() { const [password, setPassword] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); - const { fiatCurrency, network, hasActivatedOrdinalsKey, selectedAccount } = useWalletSelector(); + const { + fiatCurrency, + network, + hasActivatedOrdinalsKey, + hasActivatedRareSatsKey, + selectedAccount, + } = useWalletSelector(); const navigate = useNavigate(); const dispatch = useDispatch(); const { unlockWallet, resetWallet } = useWalletReducer(); @@ -93,6 +102,12 @@ function Setting() { const switchActivateOrdinalState = () => { dispatch(ChangeActivateOrdinalsAction(!hasActivatedOrdinalsKey)); + // disable rare sats if ordinal is disabled + dispatch(ChangeActivateRareSatsAction(false)); + }; + + const switchActivateRareSatsState = () => { + dispatch(ChangeActivateRareSatsAction(!hasActivatedRareSatsKey)); }; const openUpdatePasswordScreen = () => { @@ -216,7 +231,7 @@ function Setting() { showWarningTitle /> + + ({ color: props.theme.colors.white['0'], })); +const DescriptionText = styled.p((props) => ({ + ...props.theme.body_m, + marginTop: props.theme.spacing(2), + color: props.theme.colors.white_400, + textAlign: 'left', + paddingRight: props.theme.spacing(8), +})); + +const Column = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + flex: 1, +})); + +const DisabledOverlay = styled.div((props) => ({ + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, + zIndex: 10, + backgroundColor: props.theme.colors.elevation0, + opacity: 0.5, +})); + +const Wrapper = styled.div({ + position: 'relative', + display: 'inline-block', // This makes sure the wrapper size fits the content +}); + interface SettingComponentProps { title?: string; text: string; @@ -65,6 +95,8 @@ interface SettingComponentProps { showWarningTitle?: boolean; toggle?: boolean; toggleValue?: boolean; + description?: string; + disabled?: boolean; toggleFunction?: () => void; } @@ -78,36 +110,45 @@ function SettingComponent({ showWarningTitle, toggle, toggleValue, + description, + disabled, toggleFunction, }: SettingComponentProps) { const theme = useTheme(); return ( - - {title && {title}} - - + + + {text} + + {description && {description}} + + {textDetail && {textDetail}} + {icon && arrow icon} + {toggle && toggleFunction && ( + + )} + + + {disabled && } + ); } diff --git a/src/app/stores/nftData/actions/actionCreator.ts b/src/app/stores/nftData/actions/actionCreator.ts index b01c6bf07..6c98635e9 100644 --- a/src/app/stores/nftData/actions/actionCreator.ts +++ b/src/app/stores/nftData/actions/actionCreator.ts @@ -18,3 +18,21 @@ export function setSelectedOrdinalAction( selectedOrdinal, }; } + +export function setSelectedSatBundleAction( + selectedSatBundle: actions.NftDataState['selectedSatBundle'], +): actions.SetSelectedSatBundle { + return { + type: actions.SetSelectedSatBundleKey, + selectedSatBundle, + }; +} + +export function setSelectedSatBundleItemIndexAction( + selectedSatBundleItemIndex: actions.NftDataState['selectedSatBundleItemIndex'], +): actions.SetSelectedSatBundleItemIndex { + return { + type: actions.SetSelectedSatBundleItemIndexKey, + selectedSatBundleItemIndex, + }; +} diff --git a/src/app/stores/nftData/actions/types.ts b/src/app/stores/nftData/actions/types.ts index 8c4ba15ac..7c76f3b7f 100644 --- a/src/app/stores/nftData/actions/types.ts +++ b/src/app/stores/nftData/actions/types.ts @@ -1,15 +1,21 @@ import { Inscription } from '@secretkeylabs/xverse-core/types/api/ordinals'; import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; +import { Bundle } from '@utils/rareSats'; export interface NftDataState { nftData: NftData[]; selectedOrdinal: Inscription | null; + selectedSatBundle: Bundle | null; + selectedSatBundleItemIndex: number | null; } export const SetNftDataKey = 'SetNftData'; export const SetSelectedOrdinalKey = 'SetSelectedOrdinal'; +export const SetSelectedSatBundleKey = 'SetSelectedSatBundle'; +export const SetSelectedSatBundleItemIndexKey = 'SetSelectedSatBundleItemIndex'; + export interface SetNftData { type: typeof SetNftDataKey; nftData: NftData[]; @@ -20,4 +26,17 @@ export interface SetSelectedOrdinal { selectedOrdinal: Inscription | null; } -export type NftDataAction = SetNftData | SetSelectedOrdinal; +export interface SetSelectedSatBundle { + type: typeof SetSelectedSatBundleKey; + selectedSatBundle: NftDataState['selectedSatBundle']; +} +export interface SetSelectedSatBundleItemIndex { + type: typeof SetSelectedSatBundleItemIndexKey; + selectedSatBundleItemIndex: NftDataState['selectedSatBundleItemIndex']; +} + +export type NftDataAction = + | SetNftData + | SetSelectedOrdinal + | SetSelectedSatBundle + | SetSelectedSatBundleItemIndex; diff --git a/src/app/stores/nftData/reducer.ts b/src/app/stores/nftData/reducer.ts index 0b4624a44..8d4c4701c 100644 --- a/src/app/stores/nftData/reducer.ts +++ b/src/app/stores/nftData/reducer.ts @@ -1,8 +1,17 @@ -import { NftDataAction, NftDataState, SetNftDataKey, SetSelectedOrdinalKey } from './actions/types'; +import { + NftDataAction, + NftDataState, + SetNftDataKey, + SetSelectedOrdinalKey, + SetSelectedSatBundleItemIndexKey, + SetSelectedSatBundleKey, +} from './actions/types'; const initialNftDataState: NftDataState = { nftData: [], selectedOrdinal: null, + selectedSatBundle: null, + selectedSatBundleItemIndex: null, }; const NftDataStateReducer = ( @@ -21,6 +30,16 @@ const NftDataStateReducer = ( ...state, selectedOrdinal: action.selectedOrdinal, }; + case SetSelectedSatBundleKey: + return { + ...state, + selectedSatBundle: action.selectedSatBundle, + }; + case SetSelectedSatBundleItemIndexKey: + return { + ...state, + selectedSatBundleItemIndex: action.selectedSatBundleItemIndex, + }; default: return state; } diff --git a/src/app/stores/wallet/actions/actionCreators.ts b/src/app/stores/wallet/actions/actionCreators.ts index 84dfed15d..26bd7d912 100644 --- a/src/app/stores/wallet/actions/actionCreators.ts +++ b/src/app/stores/wallet/actions/actionCreators.ts @@ -217,6 +217,24 @@ export function ChangeActivateOrdinalsAction( }; } +export function ChangeActivateRareSatsAction( + hasActivatedRareSatsKey: boolean, +): actions.ChangeActivateRareSats { + return { + type: actions.ChangeHasActivatedRareSatsKey, + hasActivatedRareSatsKey, + }; +} + +export function SetRareSatsNoticeDismissedAction( + rareSatsNoticeDismissed: boolean, +): actions.SetRareSatsNoticeDismissed { + return { + type: actions.RareSatsNoticeDismissedKey, + rareSatsNoticeDismissed, + }; +} + export function ChangeShowBtcReceiveAlertAction( showBtcReceiveAlert: boolean | null, ): actions.ChangeShowBtcReceiveAlert { diff --git a/src/app/stores/wallet/actions/types.ts b/src/app/stores/wallet/actions/types.ts index 77e775835..2115dfaf9 100644 --- a/src/app/stores/wallet/actions/types.ts +++ b/src/app/stores/wallet/actions/types.ts @@ -37,6 +37,8 @@ export const SetCoinRatesKey = 'SetCoinRatesKey'; export const SetCoinDataKey = 'SetCoinDataKey'; export const ChangeHasActivatedOrdinalsKey = 'ChangeHasActivatedOrdinalsKey'; +export const RareSatsNoticeDismissedKey = 'RareSatsNoticeDismissedKey'; +export const ChangeHasActivatedRareSatsKey = 'ChangeHasActivatedRareSatsKey'; export const ChangeShowBtcReceiveAlertKey = 'ChangeShowBtcReceiveAlertKey'; export const ChangeShowOrdinalReceiveAlertKey = 'ChangeShowOrdinalReceiveAlertKey'; @@ -81,6 +83,8 @@ export interface WalletState { feeMultipliers: AppInfo | null; networkAddress: string | undefined; hasActivatedOrdinalsKey: boolean | undefined; + hasActivatedRareSatsKey: boolean | undefined; + rareSatsNoticeDismissed: boolean | undefined; showBtcReceiveAlert: boolean | null; showOrdinalReceiveAlert: boolean | null; showDataCollectionAlert: boolean | null; @@ -202,6 +206,16 @@ export interface ChangeActivateOrdinals { hasActivatedOrdinalsKey: boolean; } +export interface ChangeActivateRareSats { + type: typeof ChangeHasActivatedRareSatsKey; + hasActivatedRareSatsKey: boolean; +} + +export interface SetRareSatsNoticeDismissed { + type: typeof RareSatsNoticeDismissedKey; + rareSatsNoticeDismissed: boolean; +} + export interface ChangeShowBtcReceiveAlert { type: typeof ChangeShowBtcReceiveAlertKey; showBtcReceiveAlert: boolean | null; diff --git a/src/app/stores/wallet/reducer.ts b/src/app/stores/wallet/reducer.ts index 1c8c6bb1b..2c29a307e 100644 --- a/src/app/stores/wallet/reducer.ts +++ b/src/app/stores/wallet/reducer.ts @@ -29,6 +29,8 @@ import { WalletSessionPeriods, WalletState, ChangeShowDataCollectionAlertKey, + RareSatsNoticeDismissedKey, + ChangeHasActivatedRareSatsKey, } from './actions/types'; const initialWalletState: WalletState = { @@ -60,6 +62,8 @@ const initialWalletState: WalletState = { networkAddress: undefined, btcApiUrl: '', hasActivatedOrdinalsKey: undefined, + hasActivatedRareSatsKey: undefined, + rareSatsNoticeDismissed: undefined, showBtcReceiveAlert: true, showOrdinalReceiveAlert: true, showDataCollectionAlert: true, @@ -191,6 +195,16 @@ const walletReducer = ( ...state, hasActivatedOrdinalsKey: action.hasActivatedOrdinalsKey, }; + case ChangeHasActivatedRareSatsKey: + return { + ...state, + hasActivatedRareSatsKey: action.hasActivatedRareSatsKey, + }; + case RareSatsNoticeDismissedKey: + return { + ...state, + rareSatsNoticeDismissed: action.rareSatsNoticeDismissed, + }; case ChangeShowBtcReceiveAlertKey: return { ...state, diff --git a/src/app/ui-library/common.styled.ts b/src/app/ui-library/common.styled.ts index 59520e822..6bb1cff20 100644 --- a/src/app/ui-library/common.styled.ts +++ b/src/app/ui-library/common.styled.ts @@ -1,9 +1,8 @@ import styled from 'styled-components'; +import { TabList, Tab } from 'react-tabs'; import Theme from 'theme'; -type Typography = keyof typeof Theme.typography; -type Color = keyof typeof Theme.colors; -type TypographyProps = { typography: Typography; color?: Color }; +type Color = keyof typeof Theme.colors | 'currentColor'; /** * Typography @@ -14,6 +13,9 @@ type TypographyProps = { typography: Typography; color?: Color }; * * ref: https://zeroheight.com/0683c9fa7/p/789eec-typography */ +type Typography = keyof typeof Theme.typography; +type TypographyProps = { typography: Typography; color?: Color }; + export const StyledP = styled.p` ${(props) => props.theme[props.typography]} color: ${(props) => (props.color ? props.theme.colors[props.color] : 'inherit')} @@ -34,3 +36,36 @@ export const VerticalStackButtonContainer = styled.div` flex-direction: column; gap: ${(props) => props.theme.spacing(6)}px; `; + +/* + * Tabulations (styled react-tabs) + * + * ref: https://zeroheight.com/0683c9fa7/p/99c19e-tabulations/b/647c03 + */ +export const StyledTabList = styled(TabList)` + display: flex; + gap: ${(props) => props.theme.spacing(2)}px; + list-style: none; +`; + +export const StyledTab = styled(Tab)` + ${(props) => props.theme.typography.body_bold_s} + padding: ${(props) => props.theme.spacing(4)}px ${(props) => props.theme.spacing(6)}px; + border-radius: ${(props) => props.theme.radius(2)}px; + text-transform: uppercase; + cursor: pointer; + color: ${(props) => props.theme.colors.white_0}; + background-color: ${(props) => props.theme.colors.elevation0}; + + :hover { + background-color: ${(props) => props.theme.colors.elevation1}; + } + + &.react-tabs__tab--selected { + background-color: ${(props) => props.theme.colors.elevation3}; + } + + :active { + background-color: ${(props) => props.theme.colors.elevation5}; + } +`; diff --git a/src/app/ui-library/dialog.tsx b/src/app/ui-library/dialog.tsx new file mode 100644 index 000000000..e91cee627 --- /dev/null +++ b/src/app/ui-library/dialog.tsx @@ -0,0 +1,149 @@ +import styled, { useTheme } from 'styled-components'; +import ActionButton from '@components/button'; +import { XCircle } from '@phosphor-icons/react'; + +type DialogType = 'default' | 'feedback'; + +const Container = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + position: 'absolute', + left: '50%', + top: '50%', + transform: 'translate(-50%, -50%)', + width: 312, + borderRadius: 12, + zIndex: 16000, + padding: '16px 16px 32px 16px', + background: props.theme.colors.elevation3, + filter: 'drop-shadow(0px 16px 36px rgba(0, 0, 0, 0.5))', +})); + +const HeaderText = styled.h1((props) => ({ + ...props.theme.body_bold_m, + flex: 1, +})); + +const CenteredTitle = styled.h1((props) => ({ + ...props.theme.body_bold_m, + textAlign: 'center', + marginTop: props.theme.spacing(6), +})); + +const DescriptionText = styled.h1((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[200], + marginTop: props.theme.spacing(8), +})); + +const DescriptionTextCenter = styled.h1((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white[200], + marginTop: props.theme.spacing(2), + textAlign: 'center', +})); + +const RowContainer = styled.div({ + display: 'flex', + flexDirection: 'row', + alignItems: 'space-between', +}); + +const TransparentButtonContainer = styled.div((props) => ({ + marginRight: props.theme.spacing(6), + width: '100%', +})); + +const ButtonImage = styled.button({ + backgroundColor: 'transparent', +}); + +const ButtonContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + marginTop: props.theme.spacing(16), +})); + +const OuterContainer = styled.div((props) => ({ + top: 0, + left: 0, + bottom: 0, + right: 0, + position: 'fixed', + backgroundColor: props.theme.colors.elevation0, + zIndex: 1000, + opacity: 0.6, +})); + +const Column = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + marginTop: props.theme.spacing(8), + alignItems: 'center', +})); + +interface Props { + onClose: () => void; + title: string; + description: string; + leftButtonText?: string; + rightButtonText?: string; + type?: DialogType; + icon?: JSX.Element; + onLeftButtonClick?: () => void; + onRightButtonClick?: () => void; +} + +// TODO: handle horizontal and vertical bottons view + +function Dialog({ + onClose, + title, + description, + leftButtonText, + rightButtonText, + type = 'default', + icon, + onLeftButtonClick, + onRightButtonClick, +}: Props) { + const theme = useTheme(); + return ( + <> + + + + {type === 'default' ? title : ''} + + + + + {type === 'default' ? ( + {description} + ) : ( + + {icon} + {title} + {description} + + )} + {onRightButtonClick && onLeftButtonClick && ( + + + + + + + )} + {!onRightButtonClick && onLeftButtonClick && ( + + + + )} + + + ); +} + +export default Dialog; diff --git a/src/app/utils/constants.ts b/src/app/utils/constants.ts index 8a55be965..e30046dae 100644 --- a/src/app/utils/constants.ts +++ b/src/app/utils/constants.ts @@ -12,12 +12,14 @@ export const GAMMA_URL = 'https://gamma.io/'; export const TERMS_LINK = 'https://xverse.app/terms'; export const PRIVACY_POLICY_LINK = 'https://xverse.app/privacy'; export const SUPPORT_LINK = 'https://support.xverse.app/hc/en-us'; +export const BLOG_LINK = 'https:/xverse.app/blog'; export const SUPPORT_EMAIL = 'support@xverse.app'; export const BTC_TRANSACTION_STATUS_URL = 'https://mempool.space/tx/'; export const BTC_TRANSACTION_TESTNET_STATUS_URL = 'https://mempool.space/testnet/tx/'; export const TRANSACTION_STATUS_URL = 'https://explorer.stacks.co/txid/'; export const XVERSE_WEB_POOL_URL = 'https://pool.xverse.app'; export const XVERSE_ORDIVIEW_URL = 'https://ord.xverse.app'; +export const MAGISAT_IO_RARITY_SCAN_URL = 'https://magisat.io/wallet?walletAddress='; export const TRANSAC_URL = 'https://global.transak.com'; export const TRANSAC_API_KEY = process.env.TRANSAC_API_KEY; @@ -25,7 +27,15 @@ export const MOON_PAY_URL = 'https://buy.moonpay.com'; export const MOON_PAY_API_KEY = process.env.MOON_PAY_API_KEY; export const MIX_PANEL_TOKEN = process.env.MIX_PANEL_TOKEN; -export type CurrencyTypes = 'STX' | 'BTC' | 'FT' | 'NFT' | 'Ordinal' | 'brc20' | 'brc20-Ordinal'; +export type CurrencyTypes = + | 'STX' + | 'BTC' + | 'FT' + | 'NFT' + | 'Ordinal' + | 'brc20' + | 'brc20-Ordinal' + | 'RareSat'; export enum LoaderSize { SMALLEST, SMALL, diff --git a/src/app/utils/helper.ts b/src/app/utils/helper.ts index 6d227216e..2503ec611 100644 --- a/src/app/utils/helper.ts +++ b/src/app/utils/helper.ts @@ -5,7 +5,7 @@ import { NetworkType, } from '@secretkeylabs/xverse-core/types'; import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; -import { getStacksInfo } from '@secretkeylabs/xverse-core/api'; +import { getStacksInfo } from '@secretkeylabs/xverse-core'; import BitcoinEsploraApiProvider from '@secretkeylabs/xverse-core/api/esplora/esploraAPiProvider'; import BigNumber from 'bignumber.js'; import { ChainID } from '@stacks/transactions'; @@ -61,12 +61,10 @@ export function getTicker(name: string) { } export function getTruncatedAddress(address: string, lengthToShow = 4) { - if (address) { - return `${address.substring(0, lengthToShow)}...${address.substring( - address.length - lengthToShow, - address.length, - )}`; - } + return `${address.substring(0, lengthToShow)}...${address.substring( + address.length - lengthToShow, + address.length, + )}`; } export function getShortTruncatedAddress(address: string) { diff --git a/src/app/utils/rareSats.test.ts b/src/app/utils/rareSats.test.ts new file mode 100644 index 000000000..d42203c7a --- /dev/null +++ b/src/app/utils/rareSats.test.ts @@ -0,0 +1,186 @@ +import { ApiBundle, Bundle, mapRareSatsAPIResponseToRareSats } from './rareSats'; + +describe('rareSats', () => { + describe('mapRareSatsAPIResponseToRareSats', () => { + const testCases: Array<{ name: string; input: ApiBundle; expected: Bundle }> = [ + { + name: 'mixed (sats, inscriptions)', + input: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + sats: [ + { + number: '32234503563456', + offset: 0, + rarity_ranking: 'epic', + }, + { + number: '0', + offset: 100, + rarity_ranking: 'mythic', + }, + ], + inscriptions: [ + { + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', + offset: 0, + content_type: 'image/jpeg', + }, + { + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', + offset: 500, + content_type: 'text/html', + }, + ], + }, + expected: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + items: [ + { + inscription: { + content_type: 'text/html', + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', + }, + rarity_ranking: 'common', + type: 'inscription', + }, + { + inscription: { + content_type: 'image/jpeg', + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', + }, + rarity_ranking: 'epic', + type: 'inscribed-sat', + number: '32234503563456', + }, + { + number: '0', + rarity_ranking: 'mythic', + type: 'rare-sat', + }, + ], + }, + }, + { + name: 'only rare sats', + input: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + sats: [ + { + number: '32234503563456', + offset: 0, + rarity_ranking: 'epic', + }, + { + number: '0', + offset: 100, + rarity_ranking: 'mythic', + }, + ], + inscriptions: [], + }, + expected: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + items: [ + { + number: '32234503563456', + rarity_ranking: 'epic', + type: 'rare-sat', + }, + { + number: '0', + rarity_ranking: 'mythic', + type: 'rare-sat', + }, + ], + }, + }, + { + name: 'only inscriptions', + input: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + sats: [], + inscriptions: [ + { + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', + offset: 0, + content_type: 'image/jpeg', + }, + { + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', + offset: 500, + content_type: 'text/html', + }, + ], + }, + expected: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + items: [ + { + inscription: { + content_type: 'image/jpeg', + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', + }, + rarity_ranking: 'common', + type: 'inscription', + }, + { + inscription: { + content_type: 'text/html', + id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', + }, + rarity_ranking: 'common', + type: 'inscription', + }, + ], + }, + }, + { + name: 'unknown', + input: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + sats: [], + inscriptions: [], + }, + expected: { + txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', + vout: 0, + block_height: 803440, + value: 600, + items: [ + { + type: 'unknown', + rarity_ranking: 'unknown', + }, + ], + }, + }, + ]; + + testCases.forEach(({ name, input, expected }) => { + test(name, () => { + expect(mapRareSatsAPIResponseToRareSats(input)).toEqual(expected); + }); + }); + }); +}); diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts new file mode 100644 index 000000000..a474fa046 --- /dev/null +++ b/src/app/utils/rareSats.ts @@ -0,0 +1,232 @@ +import { t } from 'i18next'; +import type { Account } from '@secretkeylabs/xverse-core/types'; +import { getTruncatedAddress } from './helper'; + +const RoadArmorRareSats = ['uncommon', 'rare', 'epic', 'legendary', 'mythic', 'common'] as const; +export type RoadArmorRareSatsType = (typeof RoadArmorRareSats)[number]; + +export const RareSats = ['unknown', ...RoadArmorRareSats] as const; +export type RareSatsType = (typeof RareSats)[number]; + +export const getRareSatsLabelByType = (type: RareSatsType) => + t(`RARE_SATS.RARE_TYPES.${type.toUpperCase()}`); + +export type SatType = 'inscription' | 'rare-sat' | 'inscribed-sat' | 'unknown'; + +export const getBundleItemSubText = ({ + satType, + rareSatsType, +}: { + satType: SatType; + rareSatsType?: RareSatsType; +}) => + ({ + inscription: t('COMMON.INSCRIPTION'), + 'rare-sat': t('RARE_SATS.SAT_TYPES.RARE_SAT', { + type: getRareSatsLabelByType(rareSatsType ?? 'unknown'), + }), + 'inscribed-sat': t('RARE_SATS.SAT_TYPES.INSCRIBED_RARE_SAT', { + type: getRareSatsLabelByType(rareSatsType ?? 'unknown'), + }), + unknown: t('RARE_SATS.SAT_TYPES.UNKNOWN_RARE_SAT'), + }[satType]); + +// TODO: make number separator dynamic by locale, extension only supports en-US for now so this is not a priority +export const getRarityLabelByRareSatsType = (rareSatsType: RareSatsType) => + ({ + mythic: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '1 / 2.1' }), + legendary: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '5 / 2.1' }), + epic: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '32 / 2.1' }), + rare: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '3,437 / 2.1' }), + uncommon: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '6,929,999 / 2.1' }), + common: '--', + }[rareSatsType]); + +export const getRareSatsColorsByRareSatsType = (rareSatsType: RareSatsType) => + ({ + unknown: { + color: 'rgb(175,186,189)', + backgroundColor: 'rgba(175,186,189,0.15)', + }, + uncommon: { + color: 'rgb(0,218,182)', + backgroundColor: 'rgba(0,218,182,0.15)', + }, + rare: { + color: 'rgb(100,196,246)', + backgroundColor: 'rgba(100,196,246,0.15)', + }, + epic: { + color: 'rgb(182,105,254)', + backgroundColor: 'rgba(182,105,254,0.15)', + }, + legendary: { + color: 'rgb(255,205,120)', + backgroundColor: 'rgba(255,205,120,0.15)', + }, + mythic: { + color: 'rgb(255,244,203)', + backgroundColor: 'rgba(255,244,203, 0.15)', + }, + common: { + color: 'rgb(216,216,216)', + backgroundColor: 'rgba(216,216,216,0.15)', + }, + }[rareSatsType ?? 'common']); + +type SatInscription = { + id: string; + offset: number; + content_type: string; +}; + +type Sat = { number: string; offset: number; rarity_ranking: RoadArmorRareSatsType }; + +export type ApiBundle = { + txid: string; + vout: number; + block_height: number; + value: number; + sats: Array; + inscriptions: Array; +}; + +export type BundleItem = + | { + type: 'rare-sat'; + rarity_ranking: RoadArmorRareSatsType; + number: string; + } + | { + type: 'inscribed-sat'; + rarity_ranking: RoadArmorRareSatsType; + number: string; + inscription: { + id: string; + content_type: string; + }; + } + | { + type: 'inscription'; + rarity_ranking: RoadArmorRareSatsType; + inscription: { + id: string; + content_type: string; + }; + } + | { + type: 'unknown'; + rarity_ranking: 'unknown'; + }; + +export type Bundle = Omit & { + items: Array; +}; + +export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle => { + const generalBundleInfo = { + txid: apiBundles.txid, + vout: apiBundles.vout, + block_height: apiBundles.block_height, + value: apiBundles.value, + }; + + // unknown + if (!apiBundles.sats.length && !apiBundles.inscriptions.length) { + return { ...generalBundleInfo, items: [{ type: 'unknown', rarity_ranking: 'unknown' }] }; + } + + // only rare sats + if (!apiBundles.inscriptions.length) { + return { + ...generalBundleInfo, + items: apiBundles.sats.map((sat) => ({ + type: 'rare-sat', + rarity_ranking: sat.rarity_ranking, + number: sat.number, + })), + }; + } + + // can be mixed + const satsObject = apiBundles.sats.reduce((acc, sat) => { + acc[sat.offset] = sat; + return acc; + }, {} as Record); + + const inscriptionsObject: Record = {}; + const items: Array = []; + + apiBundles.inscriptions.forEach((inscription) => { + inscriptionsObject[inscription.offset] = inscription; + + if (satsObject[inscription.offset]) { + return; + } + items.push({ + type: 'inscription', + rarity_ranking: 'common', + inscription: { + id: inscription.id, + content_type: inscription.content_type, + }, + }); + }); + + apiBundles.sats.forEach((sat) => { + const inscription = inscriptionsObject[sat.offset]; + if (!inscription) { + return items.push({ + type: 'rare-sat', + rarity_ranking: sat.rarity_ranking, + number: sat.number, + }); + } + items.push({ + type: 'inscribed-sat', + rarity_ranking: sat.rarity_ranking, + number: sat.number, + inscription: { + id: inscription.id, + content_type: inscription.content_type, + }, + }); + }); + + return { + ...generalBundleInfo, + items, + }; +}; + +export const getBundleId = (bundle: Bundle): string => { + if ( + bundle.items.length === 1 && + bundle.items[0].type !== 'unknown' && + bundle.items[0].type !== 'inscription' + ) { + return bundle.items[0].number; + } + + return getTruncatedAddress(bundle.txid, 6); +}; + +export const getBundleSubText = (bundle: Bundle): string => { + if (bundle.items.length > 1) { + return t('RARE_SATS.RARE_SATS_BUNDLE'); + } + + const item = bundle.items[0]; + return getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking }); +}; + +export const getBundleItemId = (bundle: Bundle, index: number): string => { + const item = bundle.items[index]; + if (item.type === 'unknown') { + return getTruncatedAddress(bundle.txid, 6); + } + if (item.type === 'inscription' || item.type === 'inscribed-sat') { + return getTruncatedAddress(item.inscription.id, 6); + } + return item.number; +}; diff --git a/src/assets/img/nftDashboard/nft_fallback.svg b/src/assets/img/nftDashboard/nft_fallback.svg index 264fb093f..dae6d71bc 100644 --- a/src/assets/img/nftDashboard/nft_fallback.svg +++ b/src/assets/img/nftDashboard/nft_fallback.svg @@ -1,8 +1,8 @@ - - - + + + diff --git a/src/assets/img/nftDashboard/rareSats/NewFeature.svg b/src/assets/img/nftDashboard/rareSats/NewFeature.svg new file mode 100644 index 000000000..a789e5e27 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/NewFeature.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/epic.svg b/src/assets/img/nftDashboard/rareSats/epic.svg new file mode 100644 index 000000000..5efdf652e --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/epic.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/legendary.svg b/src/assets/img/nftDashboard/rareSats/legendary.svg new file mode 100644 index 000000000..7aadb307b --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/legendary.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/mythic.svg b/src/assets/img/nftDashboard/rareSats/mythic.svg new file mode 100644 index 000000000..4865d4930 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/mythic.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/rare.svg b/src/assets/img/nftDashboard/rareSats/rare.svg new file mode 100644 index 000000000..452b9a55c --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/rare.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/uncommon.svg b/src/assets/img/nftDashboard/rareSats/uncommon.svg new file mode 100644 index 000000000..257ee10ba --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/uncommon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 72592d7db..3d2e0052f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,4 +1,8 @@ { + "COMMON": { + "INSCRIPTION": "Inscription", + "SEND": "Send" + }, "LANDING_SCREEN": { "SCREEN_TITLE": "Wallet for Stacks & Bitcoin", "CREATE_WALLET_BUTTON": "Create Wallet", @@ -271,7 +275,8 @@ "SEND_BRC20_ORDINAL_WALLET_WARNING": "Transferring this Ordinal inscription will initiate the transfer of your BRC-20 tokens.", "SEND_ORDINAL_TO_SELF_WARNING": "You are about to transfer an Ordinal to yourself", "SEND_BRC20_ORDINAL_TO_SELF_WARNING": "You are about to transfer BRC-20 tokens to yourself", - "SEND_BTC_TO_SELF_WARNING": "You are about to transfer BTC to yourself" + "SEND_BTC_TO_SELF_WARNING": "You are about to transfer BTC to yourself", + "YOU_ARE_TRANSFERRING_TO_YOURSELF": "You are transferring to yourself" }, "CONFIRM_TRANSACTION": { "SEND": "Confirm Transaction", @@ -517,10 +522,12 @@ "NO_EARN_OPTION": "No Earn options currently available for this wallet type." }, "NFT_DASHBOARD_SCREEN": { - "COLLECTIBLES": "Number of collectibles", - "NO_COLLECTIBLES": "No collectibles yet", + "COLLECTIBLES": "Collectibles", + "NO_COLLECTIBLES": "There's nothing here yet.", + "ERROR_RETRIEVING": "We are having trouble retrieving data.", + "TRY_AGAIN": "Please try again later.", "LOAD_MORE": "Load more", - "ITEMS": "items", + "TOTAL_ITEMS": "{{total}} items", "WEB_GALLERY": "Open gallery", "RECEIVE": "Receive", "SEND": "Send", @@ -545,7 +552,31 @@ "DEPLOY": "Deploy", "VERIFY_ADDRESS_ON_LEDGER": "Verify address on Ledger", "VIEW_ADDRESS": "View address", - "ADD_STACKS_ADDRESS": "Add a Stacks address" + "ADD_STACKS_ADDRESS": "Add a Stacks address", + "RARITY_DETAIL": { + "TOP_TEXT": "Currently, only the default rarity scale is supported. Your sats could have other attributes.", + "LEARN_MORE": "Learn more", + "UNKNOWN": "A sat of unknown rarity.", + "UNCOMMON": "The first sat of each block.", + "RARE": "The first sat of each difficulty adjustment period.", + "EPIC": "The first sat of each halving epoch.", + "LEGENDARY": "The first sat of each cycle.", + "MYTHIC": "The first sat of the genesis block.", + "SCAN": "Scan for custom attributes", + "SUPPORTED_RARITIES": "Supported rarities", + "RARITY_INFO": "Currently, only the default rarity scale is supported. Your sats could have other attributes." + }, + "NFTS": "INSCRIPTIONS & NFTs", + "RARE_SATS": "Rare Sats", + "NEW_FEATURE": "New Feature, Rare Sats", + "NEW_FEAT_RARE_SATS_DESCRIPTION": "Enable rare sats to display rare, interesting and unique sats in your wallet. You can change this setting at any time.", + "NEW_FEAT_RARE_SATS_ORDINALS_ENABLE": "Enable rare sats to display rare, interesting and unique sats in your wallet. Note than enabling rare sats will also enable Ordinals. You can change this setting at any time.", + "MAYBE_LATER": "Maybe Later", + "ENABLE": "Enable", + "RARE_SATS_NOTICE_TITLE": "Don't see your rare sat?", + "RARE_SATS_NOTICE_DETAIL": "Currently, Xverse only supports the Rodarmor rarity index. Your sats may have other attributes.", + "SEE_SUPPORTED": "See supported rarity scale", + "FROM_RARE_SAT_BUNDLE": "This inscription belongs to the same bundle as other assets. Transferring it will involve transferring the full bundle." }, "RESTORE_FUND_SCREEN": { "TITLE": "Restore assets", @@ -597,7 +628,7 @@ "ORDINAL_PENDING_SEND_DESCRIPTION": "This Ordinal is already in a pending transfer.", "ORDINAL_PENDING_SEND_BUTTON": "View in Explorer", "INSCRIPTION": "Inscription", - "ID": "Id", + "ID": "ID", "CONTENT_LENGTH": "Content length", "ADDRESS": "Address", "CONTENT_TYPE": "Content type", @@ -613,7 +644,9 @@ "BRC20_TRANSFER_STATUS": "Status", "TOTAL_SUPPLY": "Total supply", "MINT_LIMIT": "Mint limit", - "VIEW_IN_ORDINALS_EXPLORER": "Open in Ordinal Viewer" + "VIEW_IN_ORDINALS_EXPLORER": "Open in Ordinal Viewer", + "RARE_SATS_BUNDLE_DESCRIPTION": "This inscription belongs to the same bundle as other assets.", + "RARE_SATS_BUNDLE_LINK": "See bundle" }, "RESET_WALLET_SCREEN": { "ENTER_PASSWORD": "Enter your password to reset your wallet", @@ -662,7 +695,10 @@ "LOCK_COUNTDOWN_TITLE": "Select the time duration before the wallet locks automatically.", "ENTER_YOUR_NEW_PASSWORD": "Enter your new password", "CONFIRM_YOUR_NEW_PASSWORD": "Confirm your new password", - "TEXT_INPUT_NEW_PASSWORD_LABEL": "New Password" + "TEXT_INPUT_NEW_PASSWORD_LABEL": "New Password", + "ENABLE_RARE_SATS": "Enable Rare Sats (experimental)", + "ENABLE_RARE_SATS_DETAIL": "Display Rare Sats in the collectibles and allow to scan the wallet for Rare Sats. This feature can impact performance.", + "ADVANCED": "Advanced" }, "OPTIONS_DIALOG": { "SWITCH_ACCOUNT": "Switch Account", @@ -1018,5 +1054,30 @@ "THIS_IS_A_SPONSORED_TRANSACTION": "This is a sponsored transaction, no transaction fees will be deducted from your account.", "SWAP_TRANSACTION_CANNOT_BE_SPONSORED": "Swap transaction cannot be sponsored while you have a pending transaction.", "LEARN_MORE": "Learn more" + }, + "RARE_SATS": { + "RARE_TYPES": { + "UNKNOWN": "Unknown", + "UNCOMMON": "Uncommon", + "COMMON": "Common", + "RARE": "Rare", + "EPIC": "Epic", + "LEGENDARY": "Legendary", + "MYTHIC": "Mythic" + }, + "SAT_TYPES": { + "RARE_SAT": "{{type}} Sat", + "INSCRIBED_RARE_SAT": "Inscribed {{type}} Sat", + "UNKNOWN_RARE_SAT": "Unknown Rarity Sat" + }, + "RARITY_RANKING_POSITION": "{{position}} quadrillion", + "RARE_SATS_RANKING": "Rare Sat ranking", + "RARITY": "Rarity", + "SEND_INDIVIDUAL_SAT_INFO": "Rare Sats and inscriptions in the same bundle cannot be sent separately.", + "RARITY_LINK_TEXT": "See supported rarity scale", + "SATS_VALUE": "Sats value", + "SATS_BUNDLE": "Sats Bundle", + "RARE_SATS_BUNDLE": "Rare Sats Bundle", + "BUNDLE_PENDING_SEND_DESCRIPTION": "This Bundle is already in a pending transfer." } } diff --git a/src/theme/index.ts b/src/theme/index.ts index b40793654..eea920b66 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -6,6 +6,18 @@ const Theme = { xlg: '1536px', }, spacing: (multiple: number) => multiple * 2, + space: { + xxxs: '2px', + xxs: '4px', + xs: '8px', + s: '12px', + m: '16px', + l: '24px', + xl: '32px', + xxl: '40px', + xxxl: '64px', + xxxxl: '80px', + } as const, radius: (multiple: number) => multiple * 4 + 4, /* @@ -16,8 +28,8 @@ const Theme = { white_0: '#FFFFFF', white_200: 'rgba(255, 255, 255, 0.8)', white_400: 'rgba(255, 255, 255, 0.6)', - white_600: 'rgba(255, 255, 255, 0.2)', - white_800: 'rgba(255, 255, 255, 0.20)', + white_600: 'rgba(255, 255, 255, 0.4)', + white_800: 'rgba(255, 255, 255, 0.2)', white_850: 'rgba(255, 255, 255, 0.15)', white_900: 'rgba(255, 255, 255, 0.1)', elevation_n1: '#0C0C0C', @@ -58,8 +70,8 @@ const Theme = { 0: '#FFFFFF', 200: 'rgba(255, 255, 255, 0.8)', 400: 'rgba(255, 255, 255, 0.6)', - 600: 'rgba(255, 255, 255, 0.2)', - 800: 'rgba(255, 255, 255, 0.20)', + 600: 'rgba(255, 255, 255, 0.4)', + 800: 'rgba(255, 255, 255, 0.2)', 850: 'rgba(255, 255, 255, 0.15)', 900: 'rgba(255, 255, 255, 0.1)', }, @@ -93,7 +105,7 @@ const Theme = { }, grey: '#24252C', purple_main: '#5E41C5', - orange_main: ' #EE7A30', + orange_main: '#EE7A30', /* above: deprecated */ }, From 1ce9f0472cf5f50b6508a0cee686cd0181ff11bb Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Fri, 6 Oct 2023 12:26:34 +0800 Subject: [PATCH 04/28] release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes --- package-lock.json | 22 +++--- package.json | 4 +- .../components/rareSatIcon/rareSatIcon.tsx | 23 ++---- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 42 +++++----- .../confirmOrdinalTransaction/index.tsx | 11 ++- src/app/screens/nftDashboard/index.tsx | 6 +- ...Component.tsx => bundleItemsComponent.tsx} | 76 +++++++++++++------ src/app/screens/signPsbtRequest/index.tsx | 23 +++--- src/app/utils/query.ts | 7 +- .../img/nftDashboard/rareSats/unknown.svg | 7 ++ src/locales/en.json | 4 +- 11 files changed, 128 insertions(+), 97 deletions(-) rename src/app/screens/signPsbtRequest/{ordinalDetailComponent.tsx => bundleItemsComponent.tsx} (65%) create mode 100644 src/assets/img/nftDashboard/rareSats/unknown.svg diff --git a/package-lock.json b/package-lock.json index a4b80a5e3..ba1c9ab17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "xverse-web-extension", - "version": "0.19.0", + "version": "0.20.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xverse-web-extension", - "version": "0.19.0", + "version": "0.20.0", "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.1", + "@secretkeylabs/xverse-core": "1.8.2", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -2209,15 +2209,15 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "1.8.1", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.1/e8656470eb2f1c662353883a03e675330303791b", - "integrity": "sha512-8rzgQLSHEHLLrEsBs6BE7p6W55/zSU4ySKw5v/q9n55p1HVnt3WfZoEzJcQ4fd6Hrxaz2gSlnf2ut9EuEDegUQ==", + "version": "1.8.2", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.2/da050d0fa956e39c47f4547596214ce301fec05b", + "integrity": "sha512-M0KlJ6qAl8WAh3kSqsBjnGgl9TKkZ02mBc/CPdOtnKZQc+92xtVxlv6dV44sn4k6BCKxGHNkhlPDXVt2rtGxUQ==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", "@scure/base": "^1.1.1", - "@scure/btc-signer": "^1.0.0", + "@scure/btc-signer": "1.1.0", "@stacks/auth": "^6.5.1", "@stacks/encryption": "6.1.1", "@stacks/network": "4.3.5", @@ -20408,14 +20408,14 @@ } }, "@secretkeylabs/xverse-core": { - "version": "1.8.1", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.1/e8656470eb2f1c662353883a03e675330303791b", - "integrity": "sha512-8rzgQLSHEHLLrEsBs6BE7p6W55/zSU4ySKw5v/q9n55p1HVnt3WfZoEzJcQ4fd6Hrxaz2gSlnf2ut9EuEDegUQ==", + "version": "1.8.2", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.2/da050d0fa956e39c47f4547596214ce301fec05b", + "integrity": "sha512-M0KlJ6qAl8WAh3kSqsBjnGgl9TKkZ02mBc/CPdOtnKZQc+92xtVxlv6dV44sn4k6BCKxGHNkhlPDXVt2rtGxUQ==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", "@scure/base": "^1.1.1", - "@scure/btc-signer": "^1.0.0", + "@scure/btc-signer": "1.1.0", "@stacks/auth": "^6.5.1", "@stacks/encryption": "6.1.1", "@stacks/network": "4.3.5", diff --git a/package.json b/package.json index 00ad41b2b..21e54fe26 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "xverse-web-extension", "description": "A Bitcoin wallet for Web3", - "version": "0.19.0", + "version": "0.20.0", "private": true, "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.1", + "@secretkeylabs/xverse-core": "1.8.2", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", diff --git a/src/app/components/rareSatIcon/rareSatIcon.tsx b/src/app/components/rareSatIcon/rareSatIcon.tsx index 94a7bb8e1..163a230cd 100644 --- a/src/app/components/rareSatIcon/rareSatIcon.tsx +++ b/src/app/components/rareSatIcon/rareSatIcon.tsx @@ -3,9 +3,9 @@ import Legendary from '@assets/img/nftDashboard/rareSats/legendary.svg'; import Mythic from '@assets/img/nftDashboard/rareSats/mythic.svg'; import Rare from '@assets/img/nftDashboard/rareSats/rare.svg'; import Uncommon from '@assets/img/nftDashboard/rareSats/uncommon.svg'; +import Unknown from '@assets/img/nftDashboard/rareSats/unknown.svg'; import { RareSatsType, getRareSatsColorsByRareSatsType } from '@utils/rareSats'; import styled from 'styled-components'; -import { Question } from '@phosphor-icons/react'; import Theme from '../../../theme'; @@ -27,9 +27,6 @@ const Image = styled.img` height: 100%; zindex: 2; `; -const QuestionIcon = styled(Question)((props) => ({ - color: props.theme.colors.white_0, -})); type GlowProps = { color: string; outerColor: string; @@ -79,27 +76,17 @@ function RareSatIcon({ mythic: Mythic, rare: Rare, uncommon: Uncommon, + unknown: Unknown, }[type]; const backgroundColor = bgColor ? Theme.colors.background[bgColor] : 'transparent'; const { color, backgroundColor: outerColor } = getRareSatsColorsByRareSatsType(type); return ( - {type === 'unknown' ? ( - - ) : ( - <> - {glow && ( - - )} - - + {glow && type !== 'unknown' && ( + )} + ); diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index 98779e567..db6b4261c 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -1,42 +1,34 @@ -import { getOrdinalIdFromUtxo, Inscription, ParsedPSBT, UTXO } from '@secretkeylabs/xverse-core'; +import { getUtxoOrdinalBundle, ParsedPSBT } from '@secretkeylabs/xverse-core'; import { useEffect, useState } from 'react'; -import useOrdinalsApi from './useOrdinalsApi'; +import { BundleItem, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; import useWalletSelector from './useWalletSelector'; const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { const [loading, setLoading] = useState(false); const [userReceivesOrdinal, setUserReceivesOrdinal] = useState(false); - const [ordinalInfoData, setOrdinalInfoData] = useState>([]); + const [bundleItemsData, setBundleItemsData] = useState([]); const { ordinalsAddress } = useWalletSelector(); - const OrdinalsApi = useOrdinalsApi(); - - const getOrdinalId = async (utxoHash: string, index: number) => { - const utxo: UTXO = { - txid: utxoHash, - vout: index, - status: { - confirmed: false, - }, - value: 0, - }; - const data = await getOrdinalIdFromUtxo(utxo); - return data; - }; async function handleOrdinalAndOrdinalInfo() { - const ordinals: Inscription[] = []; + const bundleItems: BundleItem[] = []; if (parsedPsbt) { setLoading(true); await Promise.all( parsedPsbt.inputs.map(async (input) => { - const data = await getOrdinalId(input.txid, input.index); - if (data) { - const response = await OrdinalsApi.getInscription(data); - ordinals.push(response); - } + const data = await getUtxoOrdinalBundle(input.txid, input.index); + console.log({ data }); + + const bundle = mapRareSatsAPIResponseToRareSats(data); + bundle.items.forEach((item) => { + // we don't show unknown items for now + if (item.type === 'unknown') { + return; + } + bundleItems.push(item); + }); }), ); - setOrdinalInfoData(ordinals); + setBundleItemsData(bundleItems); setLoading(false); parsedPsbt.outputs.forEach(async (output) => { if (output.address === ordinalsAddress) { @@ -52,7 +44,7 @@ const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { return { loading, - ordinalInfoData, + bundleItemsData, userReceivesOrdinal, }; }; diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index c2065a12f..2819190ff 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -63,7 +63,16 @@ function ConfirmOrdinalTransaction() { const btcClient = useBtcClient(); const [recipientAddress, setRecipientAddress] = useState(''); const location = useLocation(); - const { fee, feePerVByte, signedTxHex, ordinalUtxo, isRareSat } = location.state; + + // TODO tim: refactor to not use location.state. + const { feePerVByte, signedTxHex, ordinalUtxo, isRareSat } = location.state; + // this hack is necessary because the browser back/forward buttons + // serialize BigNumber objects into plain objects + let { fee } = location.state; + if (!BigNumber.isBigNumber(fee)) { + fee = BigNumber(fee); + } + const { selectedOrdinal, selectedSatBundle } = useNftDataSelector(); const { refetch } = useBtcWalletData(); const [currentFee, setCurrentFee] = useState(fee); diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index 4938d5cc0..a5b8dc046 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -19,6 +19,7 @@ import { import { useDispatch } from 'react-redux'; import { StyledHeading } from '@ui-library/common.styled'; import Dialog from '@ui-library/dialog'; +import { InvalidParamsError } from '@utils/query'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { MoonLoader } from 'react-spinners'; @@ -286,7 +287,10 @@ const useNftDashboard = (): NftDashboardState => { }; const NftListView = useCallback(() => { - if (stacksError || ordinalsError) { + if ( + (stacksError && !(stacksError instanceof InvalidParamsError)) || + (ordinalsError && !(ordinalsError instanceof InvalidParamsError)) + ) { return ( diff --git a/src/app/screens/signPsbtRequest/ordinalDetailComponent.tsx b/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx similarity index 65% rename from src/app/screens/signPsbtRequest/ordinalDetailComponent.tsx rename to src/app/screens/signPsbtRequest/bundleItemsComponent.tsx index 603036687..6f69fcb1d 100644 --- a/src/app/screens/signPsbtRequest/ordinalDetailComponent.tsx +++ b/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx @@ -3,8 +3,11 @@ import { useState } from 'react'; import { animated, useSpring } from '@react-spring/web'; import Cross from '@assets/img/dashboard/X.svg'; import styled from 'styled-components'; -import { Inscription } from '@secretkeylabs/xverse-core'; -import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { BundleItem, getBundleItemSubText } from '@utils/rareSats'; +import { useTranslation } from 'react-i18next'; +import IconOrdinal from '@assets/img/transactions/ordinal.svg'; +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import { getTruncatedAddress } from '@utils/helper'; const Container = styled.div((props) => ({ display: 'flex', @@ -64,6 +67,9 @@ const InscriptionText = styled.h1((props) => ({ marginTop: 24, textAlign: 'center', color: props.theme.colors.white[0], + overflowWrap: 'break-word', + wordWrap: 'break-word', + wordBreak: 'break-word', })); const ColumnContainer = styled.div({ @@ -117,21 +123,11 @@ const EyeIcon = styled.img({ }); interface Props { - ordinalInscription: string; - ordinalDetail?: string; - icon: string; - title: string; - heading?: string; - ordinal?: Inscription; + item: BundleItem; + userReceivesOrdinal: boolean; } -function OrdinalDetailComponent({ - ordinalInscription, - ordinalDetail, - icon, - title, - heading, - ordinal, -}: Props) { +function BundleItemsComponent({ item, userReceivesOrdinal }: Props) { + const { t } = useTranslation('translation'); const [showOrdinal, setShowOrdinal] = useState(false); const styles = useSpring({ from: { @@ -151,6 +147,34 @@ function OrdinalDetailComponent({ const onCrossClick = () => { setShowOrdinal(false); }; + const getItemId = () => { + if (item.type === 'inscription') { + return item.inscription.id; + } + if (item.type === 'inscribed-sat' || item.type === 'rare-sat') { + return item.number; + } + return ''; + }; + const itemSubText = getBundleItemSubText({ + satType: item.type, + rareSatsType: item.rarity_ranking, + }); + const getDetail = () => { + if (item.type === 'inscription' || item.type === 'inscribed-sat') { + return item.inscription.content_type; + } + return itemSubText; + }; + const getTitle = () => { + if (item.type === 'inscription') { + return t('COMMON.INSCRIPTION'); + } + if (item.type === 'inscribed-sat') { + return t('RARE_SATS.INSCRIBED_SAT'); + } + return t('RARE_SATS.RARE_SAT'); + }; return ( <> {showOrdinal && ( @@ -162,25 +186,29 @@ function OrdinalDetailComponent({ - + - {`Inscription ${ordinal?.number} `} + {`${getTitle()} ${getItemId()} `} )} - {heading && {heading}} + + {userReceivesOrdinal + ? t('CONFIRM_TRANSACTION.YOU_WILL_RECEIVE') + : t('CONFIRM_TRANSACTION.YOU_WILL_TRANSFER')} + - - {title} + + {getTitle()} - {ordinalInscription} + {getTruncatedAddress(String(getItemId()))} - {ordinalDetail && {ordinalDetail}} + {getDetail()} @@ -188,4 +216,4 @@ function OrdinalDetailComponent({ ); } -export default OrdinalDetailComponent; +export default BundleItemsComponent; diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index f3fc59703..6efb0d39e 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -1,6 +1,5 @@ import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg'; import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.svg'; -import IconOrdinal from '@assets/img/transactions/ordinal.svg'; import { ExternalSatsMethods, MESSAGE_SOURCE } from '@common/types/message-types'; import { ledgerDelay } from '@common/utils/ledger'; import AccountHeaderComponent from '@components/accountHeader'; @@ -33,7 +32,7 @@ import { useLocation, useNavigate } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; import { SignTransactionOptions } from 'sats-connect'; import styled from 'styled-components'; -import OrdinalDetailComponent from './ordinalDetailComponent'; +import BundleItemsComponent from './bundleItemsComponent'; const OuterContainer = styled.div` display: flex; @@ -130,7 +129,7 @@ function SignPsbtRequest() { }, [selectedAccount, payload.psbtBase64]); const parsedPsbt = useMemo(() => handlePsbtParsing(), [handlePsbtParsing]); - const { loading, ordinalInfoData, userReceivesOrdinal } = useDetectOrdinalInSignPsbt(parsedPsbt); + const { loading, bundleItemsData, userReceivesOrdinal } = useDetectOrdinalInSignPsbt(parsedPsbt); const signingAddresses = useMemo( () => getSigningAddresses(payload.inputsToSign), [payload.inputsToSign], @@ -339,7 +338,7 @@ function SignPsbtRequest() { return ( <> - + {loading ? ( @@ -357,15 +356,13 @@ function SignPsbtRequest() { {!payload.broadcast && ( )} - {ordinalInfoData && - ordinalInfoData.map((ordinalData) => ( - ( + ))} + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 3d2e0052f..3b6941066 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1078,6 +1078,8 @@ "SATS_VALUE": "Sats value", "SATS_BUNDLE": "Sats Bundle", "RARE_SATS_BUNDLE": "Rare Sats Bundle", - "BUNDLE_PENDING_SEND_DESCRIPTION": "This Bundle is already in a pending transfer." + "BUNDLE_PENDING_SEND_DESCRIPTION": "This bundle is already in a pending transfer.", + "RARE_SAT": "Rare Sat", + "INSCRIBED_SAT": "Inscribed Sat" } } From a110adb79860475ab631ad0b9c9656d64eb81ca4 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Tue, 10 Oct 2023 18:05:52 +0800 Subject: [PATCH 05/28] chore: tidy up zips of each build run and the release uploads (#31) --- .github/workflows/build.yml | 6 ++---- .github/workflows/release.yml | 7 +------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3560149b8..23a9ffad3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,14 +33,12 @@ jobs: run: | BRANCH_NAME=$(echo ${{ github.head_ref }} | sed 's/\//-/') GIT_SHA_SHORT=$(git rev-parse --short ${{ github.sha }}) - echo "FILENAME=xverse-extension.$BRANCH_NAME.$GIT_SHA_SHORT.zip" >> $GITHUB_ENV - - name: Create Archive - run: zip -r build.zip ./build + echo "FILENAME=xverse-extension.$BRANCH_NAME.$GIT_SHA_SHORT" >> $GITHUB_ENV - name: Upload Archive uses: actions/upload-artifact@v3 with: name: ${{ env.FILENAME }} - path: build.zip + path: ./build retention-days: 30 if-no-files-found: error comment-on-pr: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 038b6fe40..ff22ad986 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,12 +35,7 @@ jobs: echo "FILENAME=xverse-extension.$(echo ${{github.ref_name}}| sed 's/\//-/').zip" >> $GITHUB_OUTPUT - name: Create Archive run: | - zip -r build.zip ./build - - name: Upload Archive - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.save-filename.outputs.FILENAME }} - path: build.zip + zip -rj build.zip ./build - name: Upload Release Asset if: ${{ github.event.release.upload_url }} uses: actions/upload-release-asset@v1 From 0595589426e45e45bdf0e1995b16babeff1d8f63 Mon Sep 17 00:00:00 2001 From: Den <36603049+dhriaznov@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:19:28 +0300 Subject: [PATCH 06/28] feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and code typo (#43) * unstaged package-lock.json * fix: update all custom switch colors --------- Co-authored-by: Tim Man * fix: inscriptions grid fixes (#44) * chore: bump core version to 1.9.1 * Update function to recognise and parse brc20 tokens (#46) * Update skeleton loader logic for Collectibles UI (#45) * Update skeleton loader logic for Collectibles UI * Add a separate `TilesSkeletonLoader` component, add skeleton loader on the Collection page * Add ordinal detail page skeleton loader for the extension view * Add skeleton loader for the ordinal image component * fix: collectibles fixes from review (#47) * Fix minor ui bugs in collectible screen (#48) --------- Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> --- .prettierrc.json | 2 + package-lock.json | 81 ++- package.json | 4 +- src/app/components/barLoader/index.tsx | 13 +- src/app/components/bottomModal/index.tsx | 4 +- src/app/components/button/index.tsx | 20 +- .../collectibleDetailTile/index.tsx | 89 +++ .../components/rareSatAsset/rareSatAsset.tsx | 2 +- .../components/rareSatIcon/rareSatIcon.tsx | 2 +- .../components/receiveCardComponent/index.tsx | 25 +- src/app/components/separator/index.tsx | 13 +- src/app/components/squareButton/index.tsx | 72 ++ src/app/components/tabBar/index.tsx | 63 +- .../components/updatedBottomModal/index.tsx | 98 +++ .../components/wrenchErrorMessage/index.tsx | 31 + .../useAddressInscriptionCollections.ts | 49 ++ .../ordinals/useAddressInscriptions.ts | 66 +- .../ordinals/useCollectionMarketData.ts | 24 + .../hooks/queries/ordinals/useInscription.ts | 27 + src/app/hooks/queries/useBtcCoinsBalance.ts | 10 +- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 2 +- src/app/hooks/useResetUserFlow.ts | 1 + src/app/hooks/useTextOrdinalContent.ts | 4 +- src/app/routes/index.tsx | 29 +- .../confirmOrdinalTransaction/index.tsx | 8 +- .../createInscription/ContentLabel/index.tsx | 3 +- .../createInscription/ContentLabel/utils.ts | 90 +-- src/app/screens/home/index.tsx | 80 +-- src/app/screens/home/squareButton/index.tsx | 53 -- .../importLedgerAccount/steps/index.styled.ts | 18 +- .../importLedgerAccount/steps/index.tsx | 22 +- src/app/screens/legalLinks/index.tsx | 8 +- .../screens/manageTokens/coinItem/index.tsx | 10 +- .../screens/nftDashboard/collectiblesTabs.tsx | 124 ++-- src/app/screens/nftDashboard/index.tsx | 193 +++--- .../nftDashboard/inscriptionsTabGridItem.tsx | 100 +++ .../screens/nftDashboard/receiveNft/index.tsx | 95 ++- .../nftDashboard/tilesSkeletonLoader.tsx | 41 ++ src/app/screens/nftDetail/descriptionTile.tsx | 36 - src/app/screens/nftDetail/index.tsx | 42 +- src/app/screens/ordinalDetail/index.tsx | 627 +++++++++++------- .../screens/ordinalDetail/useOrdinalDetail.ts | 133 ++++ src/app/screens/ordinals/brc20Tile.tsx | 127 ++-- src/app/screens/ordinals/index.tsx | 2 +- src/app/screens/ordinals/ordinalImage.tsx | 66 +- src/app/screens/ordinalsCollection/index.tsx | 254 +++++++ .../ordinalsCollectionGridItem.tsx | 83 +++ src/app/screens/rareSatsBundle/index.tsx | 18 +- src/app/screens/receive/index.tsx | 23 +- src/app/screens/receive/qrCode.tsx | 71 ++ .../screens/receive/updatedReceiveScreen.tsx | 177 +++++ src/app/screens/sendOrdinal/index.tsx | 303 +++++---- .../settings/privacyPreferences/index.tsx | 16 +- .../signPsbtRequest/bundleItemsComponent.tsx | 10 +- src/app/screens/swap/index.tsx | 21 +- src/app/screens/swap/swapInfoBlock/index.tsx | 14 +- src/app/ui-library/common.styled.ts | 7 +- src/app/utils/brc20.ts | 87 ++- src/app/utils/inscriptions.ts | 55 ++ src/app/utils/query.ts | 2 +- src/app/utils/rareSats.ts | 1 - src/assets/img/receive_ordinals_image.svg | 8 + src/locales/en.json | 39 +- src/pages/Options/index.css | 6 + src/pages/Popup/index.css | 7 + src/theme/index.ts | 35 +- 66 files changed, 2788 insertions(+), 1058 deletions(-) create mode 100644 src/app/components/collectibleDetailTile/index.tsx create mode 100644 src/app/components/squareButton/index.tsx create mode 100644 src/app/components/updatedBottomModal/index.tsx create mode 100644 src/app/components/wrenchErrorMessage/index.tsx create mode 100644 src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts create mode 100644 src/app/hooks/queries/ordinals/useCollectionMarketData.ts create mode 100644 src/app/hooks/queries/ordinals/useInscription.ts delete mode 100644 src/app/screens/home/squareButton/index.tsx create mode 100644 src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx create mode 100644 src/app/screens/nftDashboard/tilesSkeletonLoader.tsx delete mode 100644 src/app/screens/nftDetail/descriptionTile.tsx create mode 100644 src/app/screens/ordinalDetail/useOrdinalDetail.ts create mode 100644 src/app/screens/ordinalsCollection/index.tsx create mode 100644 src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx create mode 100644 src/app/screens/receive/qrCode.tsx create mode 100644 src/app/screens/receive/updatedReceiveScreen.tsx create mode 100644 src/app/utils/inscriptions.ts create mode 100644 src/assets/img/receive_ordinals_image.svg diff --git a/.prettierrc.json b/.prettierrc.json index bb4b238d4..063d35498 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,6 @@ { + "plugins": ["prettier-plugin-organize-imports"], + "organizeImportsSkipDestructiveCodeActions": true, "arrowParens": "always", "bracketSpacing": true, "jsxBracketSameLine": false, diff --git a/package-lock.json b/package-lock.json index ba1c9ab17..b34b45a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.2", + "@secretkeylabs/xverse-core": "1.9.1", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -40,6 +40,7 @@ "nanoid": "^4.0.0", "p-queue": "^7.3.4", "process": "^0.11.10", + "qr-code-styling": "^1.5.0", "rc-image": "^5.14.0", "react": "^18.2.0", "react-content-loader": "^6.2.0", @@ -112,6 +113,7 @@ "lint-staged": "^13.2.3", "path": "^0.12.7", "prettier": "^2.7.1", + "prettier-plugin-organize-imports": "^3.2.3", "react-refresh": "^0.14.0", "react-refresh-typescript": "^2.0.7", "rimraf": "^3.0.2 ", @@ -2209,9 +2211,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "1.8.2", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.2/da050d0fa956e39c47f4547596214ce301fec05b", - "integrity": "sha512-M0KlJ6qAl8WAh3kSqsBjnGgl9TKkZ02mBc/CPdOtnKZQc+92xtVxlv6dV44sn4k6BCKxGHNkhlPDXVt2rtGxUQ==", + "version": "1.9.1", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.9.1/ea80ed9482e6a537cf26af36718dbcd56d55010c", + "integrity": "sha512-zAyst55gv5CrY9cWfMQYRIjDJn91Se89CgMPPOGjThoCQVOI7h/oX9JvVAZMVNEPZJwJvVpIdwpJ6kuPhc7U9Q==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -14858,9 +14860,9 @@ } }, "node_modules/postcss": { - "version": "8.4.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", - "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -15015,6 +15017,26 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-organize-imports": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", + "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", + "dev": true, + "peerDependencies": { + "@volar/vue-language-plugin-pug": "^1.0.4", + "@volar/vue-typescript": "^1.0.4", + "prettier": ">=2.0", + "typescript": ">=2.9" + }, + "peerDependenciesMeta": { + "@volar/vue-language-plugin-pug": { + "optional": true + }, + "@volar/vue-typescript": { + "optional": true + } + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -15187,11 +15209,24 @@ "bitcoin-ops": "^1.3.0" } }, + "node_modules/qr-code-styling": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.5.0.tgz", + "integrity": "sha512-7C+1cZGsZWH0BIRtv24faKZJwkxdYlynXktP9dDxKNSik2bqaUZck3B3MpQod/wqm9i3l4q7QsPGkRGKvcuqZw==", + "dependencies": { + "qrcode-generator": "^1.4.3" + } + }, "node_modules/qr.js": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" }, + "node_modules/qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", @@ -20408,9 +20443,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "1.8.2", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.8.2/da050d0fa956e39c47f4547596214ce301fec05b", - "integrity": "sha512-M0KlJ6qAl8WAh3kSqsBjnGgl9TKkZ02mBc/CPdOtnKZQc+92xtVxlv6dV44sn4k6BCKxGHNkhlPDXVt2rtGxUQ==", + "version": "1.9.1", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.9.1/ea80ed9482e6a537cf26af36718dbcd56d55010c", + "integrity": "sha512-zAyst55gv5CrY9cWfMQYRIjDJn91Se89CgMPPOGjThoCQVOI7h/oX9JvVAZMVNEPZJwJvVpIdwpJ6kuPhc7U9Q==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -30353,9 +30388,9 @@ } }, "postcss": { - "version": "8.4.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", - "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "requires": { "nanoid": "^3.3.6", @@ -30442,6 +30477,13 @@ "fast-diff": "^1.1.2" } }, + "prettier-plugin-organize-imports": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", + "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", + "dev": true, + "requires": {} + }, "pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -30592,11 +30634,24 @@ "bitcoin-ops": "^1.3.0" } }, + "qr-code-styling": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.5.0.tgz", + "integrity": "sha512-7C+1cZGsZWH0BIRtv24faKZJwkxdYlynXktP9dDxKNSik2bqaUZck3B3MpQod/wqm9i3l4q7QsPGkRGKvcuqZw==", + "requires": { + "qrcode-generator": "^1.4.3" + } + }, "qr.js": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" }, + "qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", diff --git a/package.json b/package.json index 21e54fe26..4be7b10bd 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.8.2", + "@secretkeylabs/xverse-core": "1.9.1", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "^6.1.1", @@ -36,6 +36,7 @@ "nanoid": "^4.0.0", "p-queue": "^7.3.4", "process": "^0.11.10", + "qr-code-styling": "^1.5.0", "rc-image": "^5.14.0", "react": "^18.2.0", "react-content-loader": "^6.2.0", @@ -135,6 +136,7 @@ "lint-staged": "^13.2.3", "path": "^0.12.7", "prettier": "^2.7.1", + "prettier-plugin-organize-imports": "^3.2.3", "react-refresh": "^0.14.0", "react-refresh-typescript": "^2.0.7", "rimraf": "^3.0.2 ", diff --git a/src/app/components/barLoader/index.tsx b/src/app/components/barLoader/index.tsx index 9aa4ecc24..5c53d37da 100644 --- a/src/app/components/barLoader/index.tsx +++ b/src/app/components/barLoader/index.tsx @@ -1,5 +1,5 @@ -import ContentLoader from 'react-content-loader'; import { LoaderSize } from '@utils/constants'; +import ContentLoader from 'react-content-loader'; import styled from 'styled-components'; import Theme from 'theme'; @@ -72,7 +72,15 @@ export default BarLoader; const StyledContentLoader = styled(ContentLoader)` padding: ${(props) => props.theme.spacing(1)}px; `; -export function BetterBarLoader({ width, height }: { width: number; height: number }) { +export function BetterBarLoader({ + width, + height, + className, +}: { + width: number; + height: number; + className?: string; +}) { return ( diff --git a/src/app/components/bottomModal/index.tsx b/src/app/components/bottomModal/index.tsx index 7ebb7e832..720e1d974 100644 --- a/src/app/components/bottomModal/index.tsx +++ b/src/app/components/bottomModal/index.tsx @@ -1,7 +1,7 @@ -import Modal from 'react-modal'; -import styled, { useTheme } from 'styled-components'; import Cross from '@assets/img/dashboard/X.svg'; import Separator from '@components/separator'; +import Modal from 'react-modal'; +import styled, { useTheme } from 'styled-components'; const BottomModalHeaderText = styled.h1((props) => ({ ...props.theme.body_bold_m, diff --git a/src/app/components/button/index.tsx b/src/app/components/button/index.tsx index b933a4595..a5d656900 100644 --- a/src/app/components/button/index.tsx +++ b/src/app/components/button/index.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import { MoonLoader } from 'react-spinners'; +import styled from 'styled-components'; interface ButtonProps { disabled?: boolean; @@ -79,6 +79,7 @@ const ButtonIconContainer = styled.div((props) => ({ })); interface Props { + className?: string; src?: string; icon?: JSX.Element; text: string; @@ -87,9 +88,11 @@ interface Props { disabled?: boolean; transparent?: boolean; warning?: boolean; + hoverDialogId?: string; } function ActionButton({ + className, src, icon, text, @@ -98,6 +101,7 @@ function ActionButton({ disabled = false, transparent, warning, + hoverDialogId, }: Props) { const handleOnPress = () => { if (!disabled) { @@ -107,7 +111,12 @@ function ActionButton({ if (transparent) { return ( - + {processing ? ( ) : ( @@ -122,7 +131,12 @@ function ActionButton({ } return ( - + {text} +
+ ); +} + +export default SquareButton; diff --git a/src/app/components/tabBar/index.tsx b/src/app/components/tabBar/index.tsx index 428a1422c..1c3cff69a 100644 --- a/src/app/components/tabBar/index.tsx +++ b/src/app/components/tabBar/index.tsx @@ -1,14 +1,8 @@ -import styled from 'styled-components'; -import { useNavigate } from 'react-router-dom'; -import NftTab from '@assets/img/bottomTabBar/nft_tab.svg'; -import SettingsTab from '@assets/img/bottomTabBar/setting_tab.svg'; -import StackingTab from '@assets/img/bottomTabBar/stacking_tab.svg'; -import WalletTab from '@assets/img/bottomTabBar/wallet_tab.svg'; -import UnselectedNftTab from '@assets/img/bottomTabBar/unselected_nft_tab.svg'; -import UnselectedSettingsTab from '@assets/img/bottomTabBar/unselected_setting_tab.svg'; -import UnselectedStackingTab from '@assets/img/bottomTabBar/unselected_stacking_tab.svg'; -import UnselectedWalletTab from '@assets/img/bottomTabBar/unselected_wallet_tab.svg'; +import { ChartLineUp, Gear, SketchLogo, Wallet } from '@phosphor-icons/react'; +import { animated, easings, useSpring } from '@react-spring/web'; import { isInOptions } from '@utils/helper'; +import { useNavigate } from 'react-router-dom'; +import styled, { useTheme } from 'styled-components'; const RowContainer = styled.div((props) => ({ display: 'flex', @@ -22,8 +16,19 @@ const RowContainer = styled.div((props) => ({ borderTop: `1px solid ${props.theme.colors.background.elevation3}`, })); +const MovingDiv = styled(animated.div)((props) => ({ + width: 56, + height: 32, + backgroundColor: props.theme.colors.white_900, + position: 'absolute', + bottom: 18, + left: 20, + borderRadius: 16, +})); + const Button = styled.button({ backgroundColor: 'transparent', + zIndex: 2, }); type Tab = 'dashboard' | 'nft' | 'stacking' | 'settings'; @@ -33,6 +38,23 @@ interface Props { } function BottomTabBar({ tab }: Props) { const navigate = useNavigate(); + const theme = useTheme(); + + const getPosition = () => { + if (tab === 'nft') return 96; + if (tab === 'stacking') return 168; + if (tab === 'settings') return 240; + return 24; + }; + + const styles = useSpring({ + from: { x: getPosition() }, // TODO: enable slide animation + to: { x: getPosition() }, + config: { + duration: 200, + easing: easings.easeOutCirc, + }, + }); const handleDashboardButtonClick = () => { if (tab !== 'dashboard') { @@ -62,17 +84,30 @@ function BottomTabBar({ tab }: Props) { return showBottomBar ? ( + ) : null; diff --git a/src/app/components/updatedBottomModal/index.tsx b/src/app/components/updatedBottomModal/index.tsx new file mode 100644 index 000000000..5d7c0b6ba --- /dev/null +++ b/src/app/components/updatedBottomModal/index.tsx @@ -0,0 +1,98 @@ +import { XCircle } from '@phosphor-icons/react'; +import Modal from 'react-modal'; +import styled, { useTheme } from 'styled-components'; + +const BottomModalHeaderText = styled.h1((props) => ({ + ...props.theme.body_bold_l, + flex: 1, +})); + +const RowContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + padding: props.theme.space.m, +})); + +const ButtonImage = styled.button((props) => ({ + display: 'flex', + alignItems: 'center', + color: props.theme.colors.white_400, + background: 'transparent', +})); + +interface Props { + header: string; + visible: boolean; + children: React.ReactNode; + onClose: () => void; + overlayStylesOverriding?: {}; + contentStylesOverriding?: {}; +} + +const CustomisedModal = styled(Modal)` + overflow-y: auto; + &::-webkit-scrollbar { + display: none; + } + position: absolute; +`; + +function UpdatedBottomModal({ + header, + children, + visible, + onClose, + overlayStylesOverriding, + contentStylesOverriding, +}: Props) { + const theme = useTheme(); + const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; + const customStyles = { + overlay: { + backgroundColor: isGalleryOpen ? 'transparent' : theme.colors.background.modalBackdrop, + height: '100%', + width: 360, + margin: 'auto', + zIndex: 4, + ...overlayStylesOverriding, + }, + content: { + inset: 'auto auto 0px auto', + width: '100%', + maxWidth: 360, + maxHeight: '90%', + border: 'transparent', + background: theme.colors.background.elevation6_600, + backdropFilter: 'blur(10px)', + margin: 0, + padding: 0, + borderTopLeftRadius: isGalleryOpen ? 12 : 16, + borderTopRightRadius: isGalleryOpen ? 12 : 16, + borderBottomRightRadius: isGalleryOpen ? 12 : 0, + borderBottomLeftRadius: isGalleryOpen ? 12 : 0, + ...contentStylesOverriding, + }, + }; + + return ( + document.getElementById('app') as HTMLElement} + ariaHideApp={false} + style={customStyles} + contentLabel="Example Modal" + > + + {header} + + + + + {children} + + ); +} + +export default UpdatedBottomModal; diff --git a/src/app/components/wrenchErrorMessage/index.tsx b/src/app/components/wrenchErrorMessage/index.tsx new file mode 100644 index 000000000..f340adb4b --- /dev/null +++ b/src/app/components/wrenchErrorMessage/index.tsx @@ -0,0 +1,31 @@ +import { Wrench } from '@phosphor-icons/react'; +import { StyledP } from '@ui-library/common.styled'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; + +const ErrorContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + color: ${(props) => props.theme.colors.white_200}; +`; + +const ErrorTextContainer = styled.div` + margin-top: ${(props) => props.theme.space.m}; + display: flex; + flex-direction: column; + align-items: center; +`; + +export default function WrenchErrorMesa({ className }: { className?: string }) { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + return ( + + + + {t('ERROR_RETRIEVING')} + {t('TRY_AGAIN')} + + + ); +} diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts new file mode 100644 index 000000000..45967e8bc --- /dev/null +++ b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts @@ -0,0 +1,49 @@ +import useWalletSelector from '@hooks/useWalletSelector'; +import { getCollections } from '@secretkeylabs/xverse-core'; +import { useInfiniteQuery } from '@tanstack/react-query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; + +const PAGE_SIZE = 30; + +/** + * Get collections belonging to an address + */ +const useAddressInscriptionCollections = () => { + const { ordinalsAddress } = useWalletSelector(); + + const getCollectionsByAddress = async ({ pageParam = 0 }) => { + if (!ordinalsAddress) { + throw new InvalidParamsError('ordinalsAddress is required'); + } + + // TODO cui: remove mock data after QA + const testAddress = localStorage.getItem('testAddress'); + if (testAddress) { + return getCollections( + testAddress, + pageParam || 0, // offset, + PAGE_SIZE, // limit + ); + } + return getCollections(ordinalsAddress, pageParam || 0, PAGE_SIZE); + }; + + return useInfiniteQuery(['inscription-collections', ordinalsAddress], getCollectionsByAddress, { + enabled: !!ordinalsAddress, + retry: handleRetries, + getNextPageParam: (lastpage, pages) => { + const currentLength = pages + .map((page) => page.results) + .filter(Boolean) + .flat().length; + if (currentLength < lastpage.total) { + return currentLength; + } + return false; + }, + refetchOnMount: false, + refetchOnWindowFocus: false, + }); +}; + +export default useAddressInscriptionCollections; diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts index 98ddaf6bf..ed3eeaaa3 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts @@ -1,45 +1,59 @@ -import useOrdinalsApi from '@hooks/useOrdinalsApi'; import useWalletSelector from '@hooks/useWalletSelector'; +import { getCollectionSpecificInscriptions } from '@secretkeylabs/xverse-core'; import { useInfiniteQuery } from '@tanstack/react-query'; -import { InvalidParamsError, handleRetries } from '@utils/query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; -const useAddressInscriptions = () => { - const { ordinalsAddress } = useWalletSelector(); - const ordinalsApi = useOrdinalsApi(); +const PAGE_SIZE = 30; - const PageSize = 30; +/** + * Get inscriptions belonging to an address, filtered by collection id + */ +const useAddressInscriptions = (collectionId?: string) => { + const { ordinalsAddress } = useWalletSelector(); const getInscriptionsByAddress = async ({ pageParam = 0 }) => { - if (!ordinalsAddress) { - throw new InvalidParamsError('ordinalsAddress is required'); + if (!ordinalsAddress || !collectionId) { + throw new InvalidParamsError('ordinalsAddress and collectionId are required'); } - const response = await ordinalsApi.getInscriptions(ordinalsAddress, pageParam || 0, PageSize); - return response; + + // TODO cui: remove mock data after QA + const testAddress = localStorage.getItem('testAddress'); + if (testAddress) { + return getCollectionSpecificInscriptions( + testAddress, + collectionId, + pageParam || 0, // offset, + PAGE_SIZE, // limit + ); + } + return getCollectionSpecificInscriptions( + ordinalsAddress, + collectionId, + pageParam || 0, // offset, + PAGE_SIZE, // limit + ); }; - const { isLoading, data, isFetchingNextPage, hasNextPage, error, refetch, fetchNextPage } = - useInfiniteQuery([`inscriptions-${ordinalsAddress}`], getInscriptionsByAddress, { - refetchOnMount: false, - refetchOnWindowFocus: false, + return useInfiniteQuery( + ['inscriptions', ordinalsAddress, collectionId], // cache key + getInscriptionsByAddress, + { + enabled: !!(collectionId && ordinalsAddress), retry: handleRetries, getNextPageParam: (lastpage, pages) => { - const currentLength = pages.map((page) => page.results).flat().length; + const currentLength = pages + .map((page) => page.data) + .filter(Boolean) + .flat().length; if (currentLength < lastpage.total) { return currentLength; } return false; }, - }); - - return { - isLoading, - data, - error, - fetchNextPage, - isFetchingNextPage, - hasNextPage, - refetch, - }; + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + ); }; export default useAddressInscriptions; diff --git a/src/app/hooks/queries/ordinals/useCollectionMarketData.ts b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts new file mode 100644 index 000000000..1f2ecc811 --- /dev/null +++ b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts @@ -0,0 +1,24 @@ +import { CollectionMarketDataResponse, getCollectionMarketData } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; + +/** + * Get inscription collection market data + */ +const useInscriptionCollectionMarketData = (collectionId?: string | null) => { + const collectionMarketData = async (): Promise => { + if (!collectionId) { + throw new InvalidParamsError('collectionId is required'); + } + return getCollectionMarketData(collectionId); + }; + + return useQuery({ + enabled: !!collectionId, + retry: handleRetries, + queryKey: ['collection-market-data', collectionId], + queryFn: collectionMarketData, + }); +}; + +export default useInscriptionCollectionMarketData; diff --git a/src/app/hooks/queries/ordinals/useInscription.ts b/src/app/hooks/queries/ordinals/useInscription.ts new file mode 100644 index 000000000..f675395b1 --- /dev/null +++ b/src/app/hooks/queries/ordinals/useInscription.ts @@ -0,0 +1,27 @@ +import useWalletSelector from '@hooks/useWalletSelector'; +import { getInscription, Inscription } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; + +/** + * Get inscriptions details by collection id + */ +const useAddressInscription = (ordinalId: string, ordinal: Inscription | null) => { + const { ordinalsAddress } = useWalletSelector(); + const fetchOrdinals = async (): Promise => { + if (ordinal) return ordinal; + if (!ordinalsAddress || !ordinalId) { + throw new InvalidParamsError('ordinalsAddress and ordinalId are required'); + } + return getInscription(ordinalsAddress, ordinalId); + }; + + return useQuery({ + enabled: !!(ordinal || (ordinalsAddress && ordinalId)), + retry: handleRetries, + queryKey: ['ordinal-details', ordinalsAddress, ordinalId], + queryFn: fetchOrdinals, + }); +}; + +export default useAddressInscription; diff --git a/src/app/hooks/queries/useBtcCoinsBalance.ts b/src/app/hooks/queries/useBtcCoinsBalance.ts index 13c9f87ea..4a52709c1 100644 --- a/src/app/hooks/queries/useBtcCoinsBalance.ts +++ b/src/app/hooks/queries/useBtcCoinsBalance.ts @@ -1,9 +1,9 @@ import useWalletSelector from '@hooks/useWalletSelector'; -import { useQuery } from '@tanstack/react-query'; import {} from '@secretkeylabs/xverse-core/'; -import { useDispatch } from 'react-redux'; import { getOrdinalsFtBalance } from '@secretkeylabs/xverse-core/api'; import { setBrcCoinsDataAction } from '@stores/wallet/actions/actionCreators'; +import { useQuery } from '@tanstack/react-query'; +import { useDispatch } from 'react-redux'; const useBtcCoinBalance = () => { const dispatch = useDispatch(); @@ -12,7 +12,11 @@ const useBtcCoinBalance = () => { const fetchBrcCoinsBalances = async () => { try { const list = await getOrdinalsFtBalance(ordinalsAddress); - dispatch(setBrcCoinsDataAction(list)); + dispatch( + setBrcCoinsDataAction( + list.map((brcToken) => ({ ...brcToken, ticker: brcToken.ticker?.toUpperCase() })), + ), + ); return list; } catch (e: any) { return Promise.reject(e); diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index db6b4261c..84ffb4bef 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -1,6 +1,6 @@ import { getUtxoOrdinalBundle, ParsedPSBT } from '@secretkeylabs/xverse-core'; -import { useEffect, useState } from 'react'; import { BundleItem, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { useEffect, useState } from 'react'; import useWalletSelector from './useWalletSelector'; const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { diff --git a/src/app/hooks/useResetUserFlow.ts b/src/app/hooks/useResetUserFlow.ts index d13a3e73b..932f416f3 100644 --- a/src/app/hooks/useResetUserFlow.ts +++ b/src/app/hooks/useResetUserFlow.ts @@ -25,6 +25,7 @@ const userFlowConfig: Record = { '/rare-sats-detail': { resetTo: '/nft-dashboard?tab=rareSats' }, '/rare-sats-bundle': { resetTo: '/nft-dashboard?tab=rareSats' }, '/send-rare-sat': { resetTo: '/nft-dashboard?tab=rareSats' }, + '/ordinals-collection': { resetTo: '/nft-dashboard?tab=inscriptions' }, }; type UserFlowConfigKey = keyof typeof userFlowConfig; diff --git a/src/app/hooks/useTextOrdinalContent.ts b/src/app/hooks/useTextOrdinalContent.ts index 2cad59d8f..000d49a3d 100644 --- a/src/app/hooks/useTextOrdinalContent.ts +++ b/src/app/hooks/useTextOrdinalContent.ts @@ -1,11 +1,11 @@ -import { Inscription } from '@secretkeylabs/xverse-core/types'; import { getTextOrdinalContent } from '@secretkeylabs/xverse-core/api/index'; +import type { CondensedInscription, Inscription } from '@secretkeylabs/xverse-core/types'; import { useQuery } from '@tanstack/react-query'; import PQueue from 'p-queue'; const queue = new PQueue({ concurrency: 1 }); -const useTextOrdinalContent = (ordinal: Inscription) => { +const useTextOrdinalContent = (ordinal: Inscription | CondensedInscription) => { const { data: textContent } = useQuery({ queryKey: [`ordinal-text-${ordinal?.id}`], queryFn: async () => queue.add(() => getTextOrdinalContent(ordinal?.id)), diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index dacdfe0bf..81775dac5 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -11,13 +11,13 @@ import BtcSelectAddressScreen from '@screens/btcSelectAddressScreen'; import BtcSendScreen from '@screens/btcSendScreen'; import Buy from '@screens/buy'; import CoinDashboard from '@screens/coinDashboard'; +import ConfirmBrc20Transaction from '@screens/confirmBrc20Transaction'; import ConfirmBtcTransaction from '@screens/confirmBtcTransaction'; import ConfirmFtTransaction from '@screens/confirmFtTransaction'; import ConfirmInscriptionRequest from '@screens/confirmInscriptionRequest'; import ConfirmNftTransaction from '@screens/confirmNftTransaction'; import ConfirmOrdinalTransaction from '@screens/confirmOrdinalTransaction'; import ConfirmStxTransaction from '@screens/confirmStxTransaction'; -import ConfirmBrc20Transaction from '@screens/confirmBrc20Transaction'; import CreateInscription from '@screens/createInscription'; import CreatePassword from '@screens/createPassword'; import CreateWalletSuccess from '@screens/createWalletSuccess'; @@ -26,17 +26,21 @@ import ExecuteBrc20Transaction from '@screens/executeBrc20Transaction'; import ForgotPassword from '@screens/forgotPassword'; import Home from '@screens/home'; import Landing from '@screens/landing'; +import LedgerAddStxAddress from '@screens/ledger/addStxAddress'; import ConfirmLedgerTransaction from '@screens/ledger/confirmLedgerTransaction'; import ImportLedger from '@screens/ledger/importLedgerAccount'; import VerifyLedger from '@screens/ledger/verifyLedgerAccountAddress'; -import LedgerAddStxAddress from '@screens/ledger/addStxAddress'; import LegalLinks from '@screens/legalLinks'; import Login from '@screens/login'; import ManageTokens from '@screens/manageTokens'; import NftDashboard from '@screens/nftDashboard'; +import SupportedRarities from '@screens/nftDashboard/supportedRarities'; import NftDetailScreen from '@screens/nftDetail'; import Onboarding from '@screens/onboarding'; import OrdinalDetailScreen from '@screens/ordinalDetail'; +import OrdinalsCollection from '@screens/ordinalsCollection'; +import RareSatsBundle from '@screens/rareSatsBundle'; +import RareSatsDetailScreen from '@screens/rareSatsDetail/rareSatsDetail'; import Receive from '@screens/receive'; import RestoreFunds from '@screens/restoreFunds'; import RestoreBtc from '@screens/restoreFunds/restoreBtc'; @@ -48,16 +52,17 @@ import SendBtcScreen from '@screens/sendBtc'; import SendFtScreen from '@screens/sendFt'; import SendNft from '@screens/sendNft'; import SendOrdinal from '@screens/sendOrdinal'; -import SendStxScreen from '@screens/sendStx'; import SendRareSat from '@screens/sendRareSat'; +import SendStxScreen from '@screens/sendStx'; import Setting from '@screens/settings'; import BackupWalletScreen from '@screens/settings/backupWallet'; import ChangeNetworkScreen from '@screens/settings/changeNetwork'; import ChangePasswordScreen from '@screens/settings/changePassword'; import FiatCurrencyScreen from '@screens/settings/fiatCurrency'; import LockCountdown from '@screens/settings/lockCountdown'; -import SignPsbtRequest from '@screens/signPsbtRequest'; +import PrivacyPreferencesScreen from '@screens/settings/privacyPreferences'; import SignatureRequest from '@screens/signatureRequest'; +import SignPsbtRequest from '@screens/signPsbtRequest'; import Stacking from '@screens/stacking'; import SwapScreen from '@screens/swap'; import SwapConfirmScreen from '@screens/swap/swapConfirmation'; @@ -65,10 +70,6 @@ import TransactionRequest from '@screens/transactionRequest'; import TransactionStatus from '@screens/transactionStatus'; import WalletExists from '@screens/walletExists'; import { createHashRouter } from 'react-router-dom'; -import PrivacyPreferencesScreen from '@screens/settings/privacyPreferences'; -import SupportedRarities from '@screens/nftDashboard/supportedRarities'; -import RareSatsDetailScreen from '@screens/rareSatsDetail/rareSatsDetail'; -import RareSatsBundle from '@screens/rareSatsBundle'; const router = createHashRouter([ { @@ -428,12 +429,20 @@ const router = createHashRouter([ ), }, + { + path: 'nft-dashboard/ordinals-collection/:id', + element: ( + + + + ), + }, { path: 'nft-dashboard/nft-detail/:id', element: , }, { - path: 'nft-dashboard/ordinal-detail', + path: 'nft-dashboard/ordinal-detail/:id', element: , }, { @@ -445,7 +454,7 @@ const router = createHashRouter([ element: , }, { - path: 'nft-dashboard/ordinal-detail/send-ordinal', + path: 'nft-dashboard/ordinal-detail/:id/send-ordinal', element: ( diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 2819190ff..bcb83443c 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -1,23 +1,23 @@ +import { ConfirmOrdinalsTransactionState, LedgerTransactionType } from '@common/types/ledger'; import AccountHeaderComponent from '@components/accountHeader'; +import BundleAsset from '@components/bundleAsset/bundleAsset'; import ConfirmBtcTransactionComponent from '@components/confirmBtcTransactionComponent'; import BottomBar from '@components/tabBar'; +import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; -import { ConfirmOrdinalsTransactionState, LedgerTransactionType } from '@common/types/ledger'; import OrdinalImage from '@screens/ordinals/ordinalImage'; import { BtcTransactionBroadcastResponse } from '@secretkeylabs/xverse-core/types'; import { useMutation } from '@tanstack/react-query'; import { isLedgerAccount } from '@utils/helper'; +import { getBundleId, getBundleSubText } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import { getBundleId, getBundleSubText } from '@utils/rareSats'; -import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; -import BundleAsset from '@components/bundleAsset/bundleAsset'; const ScrollContainer = styled.div` display: flex; diff --git a/src/app/screens/createInscription/ContentLabel/index.tsx b/src/app/screens/createInscription/ContentLabel/index.tsx index 71f2100bc..cc5aee1ee 100644 --- a/src/app/screens/createInscription/ContentLabel/index.tsx +++ b/src/app/screens/createInscription/ContentLabel/index.tsx @@ -6,9 +6,10 @@ import styled from 'styled-components'; import { DotsThreeVertical, Eye, Share } from '@phosphor-icons/react'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; +import { getBrc20Details } from '@utils/brc20'; import { ContentType } from './common'; import Preview from './preview'; -import { getBrc20Details, getSatsDetails } from './utils'; +import getSatsDetails from './utils'; const previewableContentTypes = new Set([ ContentType.IMAGE, diff --git a/src/app/screens/createInscription/ContentLabel/utils.ts b/src/app/screens/createInscription/ContentLabel/utils.ts index 72adc2555..7aefba1e8 100644 --- a/src/app/screens/createInscription/ContentLabel/utils.ts +++ b/src/app/screens/createInscription/ContentLabel/utils.ts @@ -1,25 +1,11 @@ -const isValidContentType = (contentType: string) => - contentType.startsWith('text/plain') || contentType.startsWith('application/json'); - -const isValidFields = ( - parsedFields: string[], - requiredFields: Set, - optionalFields?: Set, -) => - parsedFields.every((f) => requiredFields.has(f) || optionalFields?.has(f)) && - [...requiredFields].every((f) => parsedFields.includes(f)); - -const isNumber = (value: string) => !Number.isNaN(Number(value)); +import { isValidContentType, isValidFields } from '@utils/brc20'; type SatsDefinition = { op: 'ns' | 'reg'; value: string; }; -export const getSatsDetails = ( - content: string, - contentType: string, -): undefined | SatsDefinition => { +const getSatsDetails = (content: string, contentType: string): undefined | SatsDefinition => { if (!isValidContentType(contentType)) { return undefined; } @@ -65,74 +51,4 @@ export const getSatsDetails = ( } }; -type Brc20Definition = { - op: 'deploy' | 'mint' | 'transfer'; - tick: string; - value: string; -}; - -export const getBrc20Details = ( - content: string, - contentType: string, -): undefined | Brc20Definition => { - if (!isValidContentType(contentType)) { - return undefined; - } - - try { - const parsedContent = JSON.parse(content); - - if ( - parsedContent.p !== 'brc-20' || - !['deploy', 'mint', 'transfer'].includes(parsedContent.op) - ) { - return undefined; - } - - const parsedFields = Object.keys(parsedContent); - const parsedValues = Object.values(parsedContent); - - if (parsedValues.some((v) => typeof v !== 'string')) { - return undefined; - } - - const deployRequiredFields = new Set(['p', 'op', 'tick', 'max']); - const deployOptionalFields = new Set(['lim', 'desc']); - - const mintRequiredFields = new Set(['p', 'op', 'tick', 'amt']); - - const transferRequiredFields = new Set(['p', 'op', 'tick', 'amt']); - - const isValidDeploy = - parsedContent.op === 'deploy' && - isValidFields(parsedFields, deployRequiredFields, deployOptionalFields) && - parsedContent.tick.length === 4 && - isNumber(parsedContent.max) && - (!parsedContent.lim || isNumber(parsedContent.lim)) && - (!parsedContent.desc || typeof parsedContent.desc === 'string'); - - const isValidMint = - parsedContent.op === 'mint' && - isValidFields(parsedFields, mintRequiredFields) && - parsedContent.tick.length === 4 && - isNumber(parsedContent.amt); - - const isValidTransfer = - parsedContent.op === 'transfer' && - isValidFields(parsedFields, transferRequiredFields) && - parsedContent.tick.length === 4 && - isNumber(parsedContent.amt); - - if (!isValidDeploy && !isValidMint && !isValidTransfer) { - return undefined; - } - - return { - op: parsedContent.op, - tick: parsedContent.tick, - value: parsedContent.max || parsedContent.amt, - }; - } catch (e) { - return undefined; - } -}; +export default getSatsDetails; diff --git a/src/app/screens/home/index.tsx b/src/app/screens/home/index.tsx index 473ff1e49..cd79d583e 100644 --- a/src/app/screens/home/index.tsx +++ b/src/app/screens/home/index.tsx @@ -1,24 +1,20 @@ -/* eslint-disable no-await-in-loop */ -import SIP10Icon from '@assets/img/dashboard/SIP10.svg'; -import ArrowDownLeft from '@assets/img/dashboard/arrow_down_left.svg'; -import ArrowUpRight from '@assets/img/dashboard/arrow_up_right.svg'; +import dashboardIcon from '@assets/img/dashboard-icon.svg'; import BitcoinIcon from '@assets/img/dashboard/bitcoin_icon.svg'; import BitcoinToken from '@assets/img/dashboard/bitcoin_token.svg'; -import CreditCard from '@assets/img/dashboard/credit_card.svg'; import ListDashes from '@assets/img/dashboard/list_dashes.svg'; import ordinalsIcon from '@assets/img/dashboard/ordinalBRC20.svg'; +import SIP10Icon from '@assets/img/dashboard/SIP10.svg'; import stacksIcon from '@assets/img/dashboard/stack_icon.svg'; import Swap from '@assets/img/dashboard/swap.svg'; import AccountHeaderComponent from '@components/accountHeader'; import BottomModal from '@components/bottomModal'; import ActionButton from '@components/button'; import ReceiveCardComponent from '@components/receiveCardComponent'; -import { isLedgerAccount } from '@utils/helper'; -import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import ShowBtcReceiveAlert from '@components/showBtcReceiveAlert'; import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; import BottomBar from '@components/tabBar'; import TokenTile from '@components/tokenTile'; +import UpdatedBottomModal from '@components/updatedBottomModal'; import useAppConfig from '@hooks/queries/useAppConfig'; import useBtcCoinBalance from '@hooks/queries/useBtcCoinsBalance'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; @@ -27,20 +23,21 @@ import useCoinRates from '@hooks/queries/useCoinRates'; import useFeeMultipliers from '@hooks/queries/useFeeMultipliers'; import useStxWalletData from '@hooks/queries/useStxWalletData'; import useWalletSelector from '@hooks/useWalletSelector'; -import { Plus } from '@phosphor-icons/react'; +import { ArrowDown, ArrowUp, Plus } from '@phosphor-icons/react'; import CoinSelectModal from '@screens/home/coinSelectModal'; import { FungibleToken } from '@secretkeylabs/xverse-core/types'; +import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; import { CurrencyTypes } from '@utils/constants'; +import { isLedgerAccount } from '@utils/helper'; +import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; -import dashboardIcon from '@assets/img/dashboard-icon.svg'; import { useDispatch } from 'react-redux'; -import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; +import { useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; import Theme from 'theme'; +import SquareButton from '../../components/squareButton'; import BalanceCard from './balanceCard'; -import SquareButton from './squareButton'; export const Container = styled.div((props) => ({ ...props.theme.scrollbar, @@ -66,6 +63,7 @@ const ReceiveContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(16), paddingLeft: props.theme.spacing(8), paddingRight: props.theme.spacing(8), + gap: props.theme.space.m, })); const CoinContainer = styled.div({ @@ -135,10 +133,6 @@ const VerifyButtonContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(6), })); -const AddStxButtonContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(6), -})); - const ModalContent = styled.div((props) => ({ padding: props.theme.spacing(8), paddingTop: 0, @@ -153,18 +147,16 @@ const ModalIcon = styled.img((props) => ({ })); const ModalTitle = styled.div((props) => ({ - fontSize: '1rem', - fontWeight: 700, + ...props.theme.typography.body_bold_l, marginBottom: props.theme.spacing(4), textAlign: 'center', })); const ModalDescription = styled.div((props) => ({ - fontSize: '0.875rem', + ...props.theme.typography.body_m, color: props.theme.colors.white['200'], marginBottom: props.theme.spacing(16), textAlign: 'center', - lineHeight: '1.25rem', })); const ModalControlsContainer = styled.div({ @@ -394,18 +386,16 @@ function Home() { )} {isLedgerAccount(selectedAccount) && !stxAddress && ( - - } - text={t('ADD_STACKS_ADDRESS')} - onPress={async () => { - await chrome.tabs.create({ - url: chrome.runtime.getURL(`options.html#/add-stx-address-ledger`), - }); - }} - /> - + } + text={t('ADD_STACKS_ADDRESS')} + onPress={async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/add-stx-address-ledger`), + }); + }} + /> )} ); @@ -466,10 +456,22 @@ function Home() { } /> - - + } + text={t('SEND')} + onPress={onSendModalOpen} + /> + } + text={t('RECEIVE')} + onPress={onReceiveModalOpen} + /> {showSwaps && } - + } + text={t('BUY')} + onPress={onBuyModalOpen} + /> @@ -523,9 +525,13 @@ function Home() { ))} )} - + {areReceivingAddressesVisible ? receiveContent : verifyOrViewAddresses} - + {!!stxAddress && ( diff --git a/src/app/screens/home/squareButton/index.tsx b/src/app/screens/home/squareButton/index.tsx deleted file mode 100644 index 137941662..000000000 --- a/src/app/screens/home/squareButton/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import styled from 'styled-components'; - -const Icon = styled.img` - width: 20px; - height: 20px; -`; - -const Button = styled.button` - display: flex; - width: 48px; - height: 48px; - border-radius: 16px; - justify-content: center; - align-items: center; - transition: background-color 0.2s ease, opacity 0.2s ease; - background-color: ${(props) => props.theme.colors.action.classic}; - :hover { - background-color: ${(props) => props.theme.colors.action.classicLight}; - opacity: 0.6; - } -`; - -const ButtonText = styled.div((props) => ({ - fontFamily: 'Satoshi-Medium', - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const Container = styled.div` - display: flex; - flex-direction: column; - align-items: center; - row-gap: 8px; -`; - -interface Props { - text: string; - src: string; - onPress: () => void; -} - -function SquareButton({ src, text, onPress }: Props) { - return ( - - - {text} - - ); -} - -export default SquareButton; diff --git a/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts b/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts index 2630936d1..316daf68e 100644 --- a/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts +++ b/src/app/screens/ledger/importLedgerAccount/steps/index.styled.ts @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import Switch from 'react-switch'; +import styled from 'styled-components'; export const ImportStartImage = styled.img((props) => ({ marginLeft: props.theme.spacing(0), @@ -189,14 +189,14 @@ interface OptionProps { } export const Option = styled.div((props) => ({ width: '100%', - backgroundColor: '#21253C', + backgroundColor: props.theme.colors.elevation3, padding: props.theme.spacing(8), paddingTop: props.theme.spacing(7), paddingBottom: props.theme.spacing(7), borderRadius: props.theme.radius(2), fontSize: '0.75rem', marginBottom: props.theme.spacing(6), - border: `1px solid ${props.selected ? 'rgba(115, 131, 255, 0.40)' : 'transparent'}`, + border: `1px solid ${props.selected ? props.theme.colors.elevation6 : 'transparent'}`, cursor: 'pointer', userSelect: 'none', display: 'flex', @@ -204,12 +204,13 @@ export const Option = styled.div((props) => ({ transition: 'border 0.2s ease', })); +// TODO create radio button in ui-library export const OptionIcon = styled.div((props) => ({ display: 'flex', justifyContent: 'center', alignItems: 'center', - width: 15, - height: 15, + width: 16, + height: 16, borderRadius: '50%', border: `1px solid ${props.theme.colors.white[0]}`, marginRight: props.theme.spacing(10), @@ -217,10 +218,10 @@ export const OptionIcon = styled.div((props) => ({ '&::after': { content: '""', display: props.selected ? 'block' : 'none', - width: 8, - height: 8, + width: 10, + height: 10, borderRadius: 100, - backgroundColor: props.theme.colors.white[0], + backgroundColor: props.theme.colors.orange_main, }, })); @@ -237,6 +238,7 @@ export const ConfirmationStep = styled.div<{ }, })); +// TODO create custom switch in ui-library export const CustomSwitch = styled(Switch)` .react-switch-handle { background-color: ${({ checked }) => diff --git a/src/app/screens/ledger/importLedgerAccount/steps/index.tsx b/src/app/screens/ledger/importLedgerAccount/steps/index.tsx index 2aca4d4a0..b038dfb4f 100644 --- a/src/app/screens/ledger/importLedgerAccount/steps/index.tsx +++ b/src/app/screens/ledger/importLedgerAccount/steps/index.tsx @@ -1,18 +1,18 @@ -import LedgerAddressComponent from '@components/ledger/ledgerAddressComponent'; -import LedgerInput from '@components/ledger/ledgerInput'; -import warningIcon from '@assets/img/Warning_red.svg'; -import { useTranslation } from 'react-i18next'; -import ledgerImportStartIcon from '@assets/img/ledger/ledger_import_start.svg'; -import btcOrdinalsIcon from '@assets/img/ledger/btc_ordinals_icon.svg'; +import ledgerAccountSwitchIcon from '@assets/img/ledger/account_switch.svg'; import btcIcon from '@assets/img/ledger/btc_icon.svg'; -import ordinalsIcon from '@assets/img/ledger/ordinals_icon.svg'; -import stxIcon from '@assets/img/ledger/stx_icon.svg'; +import btcOrdinalsIcon from '@assets/img/ledger/btc_ordinals_icon.svg'; +import checkCircleIcon from '@assets/img/ledger/check_circle.svg'; import ledgerConnectBtcIcon from '@assets/img/ledger/ledger_import_connect_btc.svg'; import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; -import checkCircleIcon from '@assets/img/ledger/check_circle.svg'; -import ledgerAccountSwitchIcon from '@assets/img/ledger/account_switch.svg'; +import ledgerImportStartIcon from '@assets/img/ledger/ledger_import_start.svg'; +import ordinalsIcon from '@assets/img/ledger/ordinals_icon.svg'; +import stxIcon from '@assets/img/ledger/stx_icon.svg'; +import warningIcon from '@assets/img/Warning_red.svg'; import LedgerFailView from '@components/ledger/failLedgerView'; +import LedgerAddressComponent from '@components/ledger/ledgerAddressComponent'; import LedgerAssetSelectCard from '@components/ledger/ledgerAssetSelectCard'; +import LedgerInput from '@components/ledger/ledgerInput'; +import { useTranslation } from 'react-i18next'; import { useTheme } from 'styled-components'; import LedgerConnectionView from '../../../../components/ledger/connectLedgerView'; import { ImportLedgerSteps, LedgerLiveOptions } from '../types'; @@ -239,7 +239,7 @@ function Steps({ )} setIsTogglerChecked(!isTogglerChecked)} checked={isTogglerChecked} diff --git a/src/app/screens/legalLinks/index.tsx b/src/app/screens/legalLinks/index.tsx index 9e5f8b019..a21455c02 100644 --- a/src/app/screens/legalLinks/index.tsx +++ b/src/app/screens/legalLinks/index.tsx @@ -3,15 +3,15 @@ import ActionButton from '@components/button'; import Separator from '@components/separator'; import useWalletSelector from '@hooks/useWalletSelector'; import { CustomSwitch } from '@screens/ledger/importLedgerAccount/steps/index.styled'; +import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; import { PRIVACY_POLICY_LINK, TERMS_LINK } from '@utils/constants'; -import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import { saveIsTermsAccepted } from '@utils/localStorage'; +import { optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useDispatch } from 'react-redux'; import { useNavigate, useSearchParams } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; -import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; -import { useDispatch } from 'react-redux'; const Container = styled.div((props) => ({ flex: 1, @@ -109,7 +109,7 @@ function LegalLinks() {
{t('AUTHORIZE_DATA_COLLECTION')}
({ @@ -110,7 +110,7 @@ function CoinItem({ coin, disabled, toggled, enabled, showDivider }: Props) { )} ({ alignItems: 'center', })); +const StyledWrenchErrorMessage = styled(WrenchErrorMessage)` + margin-top: ${(props) => props.theme.space.xxl}; +`; + const NoCollectiblesText = styled.div((props) => ({ ...props.theme.body_bold_m, color: props.theme.colors.white['200'], @@ -41,33 +45,6 @@ const NoCollectiblesText = styled.div((props) => ({ textAlign: 'center', })); -const ErrorContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(20), - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -})); - -const ErrorTextContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(8), - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -})); - -const ErrorText = styled.div((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['200'], -})); - -const LoaderContainer = styled.div((props) => ({ - display: 'flex', - flex: 1, - justifyContent: 'center', - alignItems: 'center', - marginTop: props.theme.spacing(12), -})); - const LoadMoreButtonContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', @@ -94,38 +71,58 @@ const LoadMoreButton = styled.button((props) => ({ }, })); -const tabNameToIndex = { - inscriptions: 0, - rareSats: 1, -}; +const tabs: { + key: string; + label: string; +}[] = [ + { + key: 'inscriptions', + label: 'INSCRIPTIONS', + }, + { + key: 'nfts', + label: 'NFTS', + }, + { + key: 'rareSats', + label: 'RARE_SATS', + }, +]; -const tabIndexToName = { - 0: 'inscriptions', - 1: 'rareSats', +const tabKeyToIndex = (key?: string | null) => { + if (!key) return 0; + return tabs.findIndex((tab) => tab.key === key); }; export default function CollectiblesTabs({ className, nftListView, + inscriptionListView, nftDashboard, + loader, }: { className?: string; nftListView: React.ReactNode; + inscriptionListView: React.ReactNode; nftDashboard: NftDashboardState; + loader: React.ReactNode; }) { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); - const [tabIndex, setTabIndex] = useState(tabNameToIndex[searchParams?.get('tab') ?? ''] ?? 0); + const [tabIndex, setTabIndex] = useState(tabKeyToIndex(searchParams?.get('tab'))); const { isGalleryOpen, hasActivatedOrdinalsKey, rareSatsQuery, totalNfts, + totalInscriptions, hasActivatedRareSatsKey, showNoticeAlert, onDismissRareSatsNotice, onLoadMoreRareSatsButtonClick, + isLoading, + isLoadingOrdinalCollections, } = nftDashboard; const handleSelectTab = (index: number) => { @@ -133,7 +130,7 @@ export default function CollectiblesTabs({ }; useEffect(() => { - setSearchParams({ tab: tabIndexToName[tabIndex] }); + setSearchParams({ tab: tabs[tabIndex]?.key }); }, [tabIndex, setSearchParams]); const ordinalBundleCount = rareSatsQuery?.data?.pages?.[0]?.total || 0; @@ -144,17 +141,38 @@ export default function CollectiblesTabs({ {hasActivatedRareSatsKey && ( - {t('NFTS')} - {t('RARE_SATS')} + {tabs.map(({ key, label }) => ( + {t(label)} + ))} )} - {totalNfts > 0 && ( - - {t('TOTAL_ITEMS', { total: totalNfts || 0 })} - + {isLoadingOrdinalCollections ? ( + loader + ) : ( + <> + {totalInscriptions > 0 && ( + + {t('TOTAL_ITEMS', { total: totalInscriptions || 0 })} + + )} + {inscriptionListView} + + )} + + + {isLoading ? ( + loader + ) : ( + <> + {totalNfts > 0 && ( + + {t('TOTAL_ITEMS', { total: totalNfts || 0 })} + + )} + {nftListView} + )} - {nftListView} {ordinalBundleCount > 0 && ( @@ -179,20 +197,8 @@ export default function CollectiblesTabs({ )} {showNoBundlesNotice && {t('NO_COLLECTIBLES')}} - {!!rareSatsQuery.error && ( - - - - {t('ERROR_RETRIEVING')} - {t('TRY_AGAIN')} - - - )} - {rareSatsQuery.isLoading && ( - - - - )} + {!!rareSatsQuery.error && } + {rareSatsQuery.isLoading && loader} {hasActivatedOrdinalsKey && !rareSatsQuery.error && diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index a5b8dc046..3c9a0b0ad 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -4,29 +4,30 @@ import ActionButton from '@components/button'; import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; import BottomTabBar from '@components/tabBar'; import WebGalleryButton from '@components/webGalleryButton'; -import useAddressInscriptions from '@hooks/queries/ordinals/useAddressInscriptions'; +import useAddressInscriptionCollections from '@hooks/queries/ordinals/useAddressInscriptionCollections'; import { useAddressRareSats } from '@hooks/queries/ordinals/useAddressRareSats'; import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowDown, Wrench } from '@phosphor-icons/react'; -import Ordinal from '@screens/ordinals'; -import { InscriptionsList } from '@secretkeylabs/xverse-core/types'; +import type { InscriptionCollectionsData } from '@secretkeylabs/xverse-core/types'; import { ChangeActivateOrdinalsAction, ChangeActivateRareSatsAction, SetRareSatsNoticeDismissedAction, } from '@stores/wallet/actions/actionCreators'; -import { useDispatch } from 'react-redux'; import { StyledHeading } from '@ui-library/common.styled'; import Dialog from '@ui-library/dialog'; +import { getCollectionKey } from '@utils/inscriptions'; import { InvalidParamsError } from '@utils/query'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { MoonLoader } from 'react-spinners'; +import { useDispatch } from 'react-redux'; import styled from 'styled-components'; import CollectiblesTabs, { GridContainer } from './collectiblesTabs'; +import { InscriptionsTabGridItem } from './inscriptionsTabGridItem'; import Nft from './nft'; import ReceiveNftModal from './receiveNft'; +import { StyledBarLoader, TilesSkeletonLoader } from './tilesSkeletonLoader'; const Container = styled.div` display: flex; @@ -73,13 +74,10 @@ const CollectibleContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(12), })); -const LoaderContainer = styled.div((props) => ({ +const LoaderContainer = styled.div({ display: 'flex', - flex: 1, - justifyContent: 'center', - alignItems: 'center', - marginTop: props.theme.spacing(12), -})); + flexDirection: 'column', +}); const ButtonContainer = styled.div({ display: 'flex', @@ -94,18 +92,6 @@ const ReceiveButtonContainer = styled.div(() => ({ width: '100%', })); -const BottomBarContainer = styled.div({ - marginTop: '5%', -}); - -const LoadMoreButtonContainer = styled.div((props) => ({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - marginBottom: props.theme.spacing(30), - marginTop: props.theme.space.xl, -})); - const LoadMoreButton = styled.button((props) => ({ ...props.theme.body_medium_l, fontSize: 13, @@ -151,17 +137,34 @@ const ErrorText = styled.div((props) => ({ color: props.theme.colors.white['200'], })); +const CountLoaderContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(6), + marginBottom: props.theme.spacing(12), +})); + +const LoadMoreButtonContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginBottom: props.theme.spacing(30), + marginTop: props.theme.space.xl, + button: { + width: 156, + }, +})); + export type NftDashboardState = { openReceiveModal: boolean; showNewFeatureAlert: boolean; isOrdinalReceiveAlertVisible: boolean; isLoading: boolean; - isLoadingOrdinals: boolean; + isLoadingOrdinalCollections: boolean; openInGalleryView: () => void; onReceiveModalOpen: () => void; onReceiveModalClose: () => void; onOrdinalReceiveAlertOpen: () => void; onOrdinalReceiveAlertClose: () => void; + InscriptionListView: () => JSX.Element; NftListView: () => JSX.Element; onActivateRareSatsAlertCrossPress: () => void; onActivateRareSatsAlertDenyPress: () => void; @@ -173,6 +176,7 @@ export type NftDashboardState = { showNoticeAlert?: boolean; rareSatsQuery: ReturnType; totalNfts: number; + totalInscriptions: number; onLoadMoreRareSatsButtonClick: () => void; }; @@ -200,37 +204,29 @@ const useNftDashboard = (): NftDashboardState => { fetchNextPage, } = useStacksCollectibles(); const { - data: ordinals, - error: ordinalsError, - hasNextPage: hasNextPageOrdinals, - isFetchingNextPage: isFetchingNextPageOrdinals, - isLoading: isLoadingOrdinals, - fetchNextPage: fetchNextOrdinalsPage, - refetch: refetchOrdinals, - } = useAddressInscriptions(); + data: ordinalCollections, + error: ordinalCollectionsError, + hasNextPage: hasNextPageOrdinalCollections, + isFetchingNextPage: isFetchingNextPageOrdinalCollections, + isLoading: isLoadingOrdinalCollections, + fetchNextPage: fetchNextOrdinalsPageCollections, + refetch: refetchOrdinalCollections, + } = useAddressInscriptionCollections(); const rareSatsQuery = useAddressRareSats(); const refetchCollectibles = useCallback(async () => { await refetch(); - await refetchOrdinals(); - }, [refetch, refetchOrdinals]); + await refetchOrdinalCollections(); + }, [refetch, refetchOrdinalCollections]); useEffect(() => { refetchCollectibles(); }, [stxAddress, ordinalsAddress]); const nfts = nftsList?.pages.map((page) => page.nftsList).flat(); - - const ordinalsLength = ordinals?.pages[0].total; - - const totalNfts = useMemo(() => { - let totalCount = nftsList && nftsList.pages.length > 0 ? nftsList.pages[0].total : 0; - if (hasActivatedOrdinalsKey && ordinalsLength) { - totalCount = ordinalsLength + totalCount; - } - return totalCount; - }, [nftsList, hasActivatedOrdinalsKey, ordinalsLength]); + const ordinalsLength = ordinalCollections?.pages[0].total; + const totalNfts = nftsList && nftsList.pages.length > 0 ? nftsList.pages[0].total : 0; const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); @@ -248,8 +244,8 @@ const useNftDashboard = (): NftDashboardState => { }, [rareSatsNoticeDismissed]); const onLoadMoreButtonClick = () => { - if (hasNextPageOrdinals) { - fetchNextOrdinalsPage(); + if (hasNextPageOrdinalCollections) { + fetchNextOrdinalsPageCollections(); } if (hasNextPage) { fetchNextPage(); @@ -270,14 +266,6 @@ const useNftDashboard = (): NftDashboardState => { setOpenReceiveModal(false); }; - const renderOrdinalsList = useCallback( - (list: InscriptionsList) => - list.results.map((ordinal) => ( - - )), - [], - ); - const onOrdinalReceiveAlertOpen = () => { setIsOrdinalReceiveAlertVisible(true); }; @@ -286,11 +274,56 @@ const useNftDashboard = (): NftDashboardState => { setIsOrdinalReceiveAlertVisible(false); }; + const InscriptionListView = useCallback(() => { + if (ordinalCollectionsError && !(ordinalCollectionsError instanceof InvalidParamsError)) { + return ( + + + + {t('ERROR_RETRIEVING')} + {t('TRY_AGAIN')} + + + ); + } + + if (ordinalsLength === 0) { + return {t('NO_COLLECTIBLES')}; + } + + return ( + <> + + {ordinalCollections?.pages + ?.map((page) => page?.results) + .flat() + .map((collection: InscriptionCollectionsData) => ( + + ))} + + {hasNextPageOrdinalCollections && ( + + + + )} + + ); + }, [ + ordinalCollections, + hasActivatedOrdinalsKey, + ordinalCollectionsError, + hasNextPageOrdinalCollections, + isFetchingNextPageOrdinalCollections, + ]); + const NftListView = useCallback(() => { - if ( - (stacksError && !(stacksError instanceof InvalidParamsError)) || - (ordinalsError && !(ordinalsError instanceof InvalidParamsError)) - ) { + if (stacksError && !(stacksError instanceof InvalidParamsError)) { return ( @@ -302,14 +335,13 @@ const useNftDashboard = (): NftDashboardState => { ); } - if (totalNfts === 0 && ordinalsLength === 0) { + if (totalNfts === 0) { return {t('NO_COLLECTIBLES')}; } return ( <> - {hasActivatedOrdinalsKey && !ordinalsError && ordinals?.pages?.map(renderOrdinalsList)} {!stacksError && nfts?.map((nft) => ( { /> ))} - {(hasNextPage || hasNextPageOrdinals) && ( + {hasNextPage && ( - {isFetchingNextPage || isFetchingNextPageOrdinals ? ( - + {isFetchingNextPage ? ( + ) : ( {t('LOAD_MORE')} )} @@ -330,7 +362,7 @@ const useNftDashboard = (): NftDashboardState => { )} ); - }, [ordinals, nfts, hasActivatedOrdinalsKey, stacksError, ordinalsError]); + }, [nfts, stacksError]); const onActivateRareSatsAlertCrossPress = () => { setShowNewFeatureAlert(false); @@ -364,12 +396,13 @@ const useNftDashboard = (): NftDashboardState => { showNewFeatureAlert, isOrdinalReceiveAlertVisible, isLoading, - isLoadingOrdinals, + isLoadingOrdinalCollections, openInGalleryView, onReceiveModalOpen, onReceiveModalClose, onOrdinalReceiveAlertOpen, onOrdinalReceiveAlertClose, + InscriptionListView, NftListView, onActivateRareSatsAlertCrossPress, onActivateRareSatsAlertDenyPress, @@ -381,6 +414,7 @@ const useNftDashboard = (): NftDashboardState => { showNoticeAlert, rareSatsQuery, totalNfts, + totalInscriptions: ordinalsLength, onLoadMoreRareSatsButtonClick, }; }; @@ -393,13 +427,12 @@ function NftDashboard() { showNewFeatureAlert, hasActivatedOrdinalsKey, isOrdinalReceiveAlertVisible, - isLoading, - isLoadingOrdinals, openInGalleryView, onReceiveModalOpen, onReceiveModalClose, onOrdinalReceiveAlertOpen, onOrdinalReceiveAlertClose, + InscriptionListView, NftListView, onActivateRareSatsAlertCrossPress, onActivateRareSatsAlertDenyPress, @@ -460,20 +493,22 @@ function NftDashboard() { )} - {isLoading || isLoadingOrdinals ? ( - - - - ) : ( - } nftDashboard={nftDashboard} /> - )} + } + inscriptionListView={} + nftDashboard={nftDashboard} + loader={ + + + + + + + } + /> - {!isGalleryOpen && ( - - - - )} + {!isGalleryOpen && } ); } diff --git a/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx b/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx new file mode 100644 index 000000000..91a273407 --- /dev/null +++ b/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx @@ -0,0 +1,100 @@ +import RareSatsCollage from '@components/bundleAsset/rareSatsCollage'; +import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { InscriptionCollectionsData } from '@secretkeylabs/xverse-core/types'; +import { StyledP } from '@ui-library/common.styled'; +import { + getCollectionKey, + getInscriptionsTabGridItemId, + getInscriptionsTabGridItemSubText, + isCollection, + mapCondensedInscriptionToBundleItem, +} from '@utils/inscriptions'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; + +const CollectionContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + gap: props.theme.space.s, +})); + +const ThumbnailContainer = styled.button` + background: transparent; +`; + +const InfoContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; +`; + +const StyledItemId = styled(StyledP)` + text-align: left; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const StyledItemSub = styled(StyledP)` + text-align: left; + text-overflow: ellipsis; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +export function InscriptionsTabGridItem({ + item: collection, +}: { + item: InscriptionCollectionsData; +}) { + const navigate = useNavigate(); + + const handleClickCollectionId = (e: React.MouseEvent) => { + const collectionId = e.currentTarget.value; + navigate(`/nft-dashboard/ordinals-collection/${collectionId}`); + }; + + const handleClickInscriptionId = (e: React.MouseEvent) => { + const inscriptionId = e.currentTarget.value; + navigate(`/nft-dashboard/ordinal-detail/${inscriptionId}`); + }; + + const itemId = getInscriptionsTabGridItemId(collection); + const itemSubText = getInscriptionsTabGridItemSubText(collection); + + return ( + + + {!collection.thumbnail_inscriptions ? ( // eslint-disable-line no-nested-ternary + + ) : !isCollection(collection) || collection.thumbnail_inscriptions.length === 1 ? ( // eslint-disable-line no-nested-ternary + + ) : collection.category === 'brc-20' ? ( + + ) : ( + + )} + + + + {itemId} + + + {itemSubText} + + + + ); +} +export default InscriptionsTabGridItem; diff --git a/src/app/screens/nftDashboard/receiveNft/index.tsx b/src/app/screens/nftDashboard/receiveNft/index.tsx index 06e7c6105..4da8532ba 100644 --- a/src/app/screens/nftDashboard/receiveNft/index.tsx +++ b/src/app/screens/nftDashboard/receiveNft/index.tsx @@ -1,31 +1,56 @@ -import BottomModal from '@components/bottomModal'; -import { useTranslation } from 'react-i18next'; +import plusIcon from '@assets/img/dashboard/plus.svg'; import Cross from '@assets/img/dashboard/X.svg'; -import styled from 'styled-components'; import ordinalsIcon from '@assets/img/nftDashboard/ordinals_icon.svg'; import stacksIcon from '@assets/img/nftDashboard/stacks_icon.svg'; -import plusIcon from '@assets/img/dashboard/plus.svg'; -import { useNavigate } from 'react-router-dom'; -import useWalletSelector from '@hooks/useWalletSelector'; import ActionButton from '@components/button'; -import { useState } from 'react'; +import UpdatedBottomModal from '@components/updatedBottomModal'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { Plus } from '@phosphor-icons/react'; import { isLedgerAccount } from '@utils/helper'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import ReceiveCardComponent from '../../../components/receiveCardComponent'; const ColumnContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - marginTop: props.theme.spacing(12), - marginBottom: props.theme.spacing(16), - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), + marginTop: props.theme.space.l, + marginBottom: props.theme.space.xl, + paddingLeft: props.theme.space.m, + paddingRight: props.theme.space.m, + gap: props.theme.space.m, })); const Icon = styled.img({ width: 24, height: 24, + position: 'absolute', + zIndex: 2, + left: 0, + top: 0, }); +const IconContainer = styled.div((props) => ({ + position: 'relative', + marginBottom: props.theme.spacing(12), +})); + +const IconBackground = styled.div((props) => ({ + width: 24, + height: 24, + position: 'absolute', + zIndex: 1, + left: 20, + top: 0, + backgroundColor: props.theme.colors.white_900, + borderRadius: 30, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', +})); + const RowContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', @@ -54,10 +79,6 @@ const VerifyButtonContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(6), })); -const AddStxButtonContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(6), -})); - interface Props { visible: boolean; onClose: () => void; @@ -118,7 +139,12 @@ function ReceiveNftModal({ visible, onClose, isGalleryOpen, setOrdinalReceiveAle showVerifyButton={choseToVerifyAddresses} currency="ORD" > - + + + + + + )} @@ -130,23 +156,26 @@ function ReceiveNftModal({ visible, onClose, isGalleryOpen, setOrdinalReceiveAle showVerifyButton={choseToVerifyAddresses} currency="STX" > - + + + + + + )} {isLedgerAccount(selectedAccount) && !stxAddress && ( - - { - await chrome.tabs.create({ - url: chrome.runtime.getURL(`options.html#/add-stx-address-ledger`), - }); - }} - /> - + { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/add-stx-address-ledger`), + }); + }} + /> )}
); @@ -182,9 +211,13 @@ function ReceiveNftModal({ visible, onClose, isGalleryOpen, setOrdinalReceiveAle {isReceivingAddressesVisible ? receiveContent : verifyOrViewAddresses} ) : ( - + {isReceivingAddressesVisible ? receiveContent : verifyOrViewAddresses} - + ); } diff --git a/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx b/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx new file mode 100644 index 000000000..e514977cb --- /dev/null +++ b/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx @@ -0,0 +1,41 @@ +import { BetterBarLoader } from '@components/barLoader'; +import styled from 'styled-components'; + +const TilesLoaderContainer = styled.div({ + display: 'flex', + justifyContent: 'space-between', +}); + +const TileLoaderContainer = styled.div({ + display: 'flex', + flexDirection: 'column', +}); + +export const StyledBarLoader = styled(BetterBarLoader)<{ + withMarginBottom?: boolean; +}>((props) => ({ + padding: 0, + borderRadius: 6, + marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, +})); + +export function TilesSkeletonLoader({ + className, + tileSize = 151, +}: { + className?: string; + tileSize?: number; +}) { + return ( + + + + + + + + + + + ); +} diff --git a/src/app/screens/nftDetail/descriptionTile.tsx b/src/app/screens/nftDetail/descriptionTile.tsx deleted file mode 100644 index 8eec545a5..000000000 --- a/src/app/screens/nftDetail/descriptionTile.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import styled from 'styled-components'; - -const DescriptionHeadingText = styled.h1((props) => ({ - ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], - marginBottom: props.theme.spacing(2), - letterSpacing: '0.02em', - textTransform: 'uppercase', -})); - -const DescriptionValueText = styled.h1((props) => ({ - ...props.theme.body_m, - color: props.theme.colors.white['0'], - marginBottom: props.theme.spacing(16), -})); - -const ColumnContainer = styled.h1({ - display: 'flex', - flexDirection: 'column', -}); - -interface Props { - title: string; - value: string; -} - -function DescriptionTile({ title, value }: Props) { - return ( - - {title} - {value} - - ); -} - -export default DescriptionTile; diff --git a/src/app/screens/nftDetail/index.tsx b/src/app/screens/nftDetail/index.tsx index 7b1d7a2eb..0285ca758 100644 --- a/src/app/screens/nftDetail/index.tsx +++ b/src/app/screens/nftDetail/index.tsx @@ -1,32 +1,32 @@ -import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; -import { useNavigate, useParams } from 'react-router-dom'; -import NftImage from '@screens/nftDashboard/nftImage'; import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; -import TopRow from '@components/topRow'; -import BottomTabBar from '@components/tabBar'; import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; import ArrowUp from '@assets/img/dashboard/arrow_up.svg'; import ShareNetwork from '@assets/img/nftDashboard/share.svg'; +import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; +import AccountHeaderComponent from '@components/accountHeader'; import ActionButton from '@components/button'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { useEffect, useState } from 'react'; +import CollectibleDetailTile from '@components/collectibleDetailTile'; import ShareDialog from '@components/shareNft'; -import { GAMMA_URL } from '@utils/constants'; -import { getExplorerUrl, isLedgerAccount } from '@utils/helper'; +import SmallActionButton from '@components/smallActionButton'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useNftDataReducer from '@hooks/stores/useNftReducer'; -import { useMutation } from '@tanstack/react-query'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import NftImage from '@screens/nftDashboard/nftImage'; import { getNftDetail } from '@secretkeylabs/xverse-core/api'; -import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; import { NftDetailResponse } from '@secretkeylabs/xverse-core/types'; +import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; +import { useMutation } from '@tanstack/react-query'; +import { GAMMA_URL } from '@utils/constants'; +import { getExplorerUrl, isLedgerAccount } from '@utils/helper'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; -import AccountHeaderComponent from '@components/accountHeader'; -import SmallActionButton from '@components/smallActionButton'; -import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import styled from 'styled-components'; import NftAttribute from './nftAttribute'; -import DescriptionTile from './descriptionTile'; const Container = styled.div` display: flex; @@ -412,9 +412,11 @@ function NftDetailScreen() { {t('DESCRIPTION')} - - {nft?.rarity_score && } - + {nft?.rarity_score && ( + + )} + diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index 74bc1108c..1cd7c6871 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -1,54 +1,52 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import ArrowUp from '@assets/img/dashboard/arrow_up.svg'; -import ArrowUpRight from '@assets/img/dashboard/arrow_up_right.svg'; -import Globe from '@assets/img/nftDashboard/globe.svg'; import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import AccountHeaderComponent from '@components/accountHeader'; import AlertMessage from '@components/alertMessage'; +import { BetterBarLoader } from '@components/barLoader'; import ActionButton from '@components/button'; +import CollectibleDetailTile from '@components/collectibleDetailTile'; +import Separator from '@components/separator'; +import SquareButton from '@components/squareButton'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; -import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; -import useNftDataSelector from '@hooks/stores/useNftDataSelector'; -import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; -import useWalletSelector from '@hooks/useWalletSelector'; -import DescriptionTile from '@screens/nftDetail/descriptionTile'; +import { ArrowRight, ArrowUp, CubeTransparent, Share } from '@phosphor-icons/react'; import OrdinalImage from '@screens/ordinals/ordinalImage'; -import { isBrcTransferValid } from '@secretkeylabs/xverse-core/api'; -import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; -import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; -import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; -import styled, { useTheme } from 'styled-components'; -import { CubeTransparent, ArrowRight } from '@phosphor-icons/react'; -import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; -import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import { Tooltip } from 'react-tooltip'; +import styled from 'styled-components'; import OrdinalAttributeComponent from './ordinalAttributeComponent'; +import useOrdinalDetail from './useOrdinalDetail'; -const Container = styled.div` - display: flex; - flex-direction: column; - flex: 1; - overflow-y: auto; - margin-left: 5%; - margin-right: 5%; - &::-webkit-scrollbar { - display: none; - } -`; +interface DetailSectionProps { + isGallery: boolean; +} -const SendButtonContainer = styled.div((props) => ({ - marginRight: props.theme.spacing(3), - width: 182, +const GalleryScrollContainer = styled.div((props) => ({ + ...props.theme.scrollbar, + display: 'flex', + flexDirection: 'column', + flex: 1, + alignItems: 'center', })); +const GalleryContainer = styled.div({ + marginLeft: 'auto', + marginRight: 'auto', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + maxWidth: 1224, +}); + const BackButtonContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', + width: 820, marginTop: props.theme.spacing(40), })); @@ -57,20 +55,24 @@ const ButtonContainer = styled.div((props) => ({ position: 'relative', flexDirection: 'row', maxWidth: 400, + columnGap: props.theme.spacing(8), marginBottom: props.theme.spacing(10.5), })); -const ExtensionContainer = styled.div({ +const ExtensionContainer = styled.div((props) => ({ + ...props.theme.scrollbar, display: 'flex', flexDirection: 'column', - marginTop: 8, + marginTop: props.theme.spacing(4), alignItems: 'center', flex: 1, -}); + paddingLeft: props.theme.spacing(4), + paddingRight: props.theme.spacing(4), +})); const OrdinalsContainer = styled.div((props) => ({ - maxWidth: 450, - width: '60%', + width: 376.5, + height: 376.5, display: 'flex', aspectRatio: '1', flexDirection: 'column', @@ -81,8 +83,8 @@ const OrdinalsContainer = styled.div((props) => ({ })); const ExtensionOrdinalsContainer = styled.div((props) => ({ - maxHeight: 148, - width: 148, + maxHeight: 136, + width: 136, display: 'flex', aspectRatio: '1', justifyContent: 'center', @@ -94,32 +96,30 @@ const ExtensionOrdinalsContainer = styled.div((props) => ({ const OrdinalTitleText = styled.h1((props) => ({ ...props.theme.headline_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, + marginTop: props.theme.spacing(1), textAlign: 'center', })); const OrdinalGalleryTitleText = styled.h1((props) => ({ ...props.theme.headline_l, color: props.theme.colors.white['0'], - marginBottom: props.theme.spacing(12), })); const DescriptionText = styled.h1((props) => ({ ...props.theme.headline_l, color: props.theme.colors.white['0'], fontSize: 24, - marginBottom: props.theme.spacing(16), + marginBottom: props.theme.spacing(8), })); const NftOwnedByText = styled.h1((props) => ({ ...props.theme.body_medium_m, color: props.theme.colors.white['400'], - textAlign: 'center', })); const OwnerAddressText = styled.h1((props) => ({ ...props.theme.body_medium_m, - textAlign: 'center', marginLeft: props.theme.spacing(3), })); @@ -130,7 +130,8 @@ const BottomBarContainer = styled.div({ const RowContainer = styled.div((props) => ({ display: 'flex', alignItems: 'flex-start', - marginTop: props.theme.spacing(6), + marginTop: props.theme.spacing(8), + marginBottom: props.theme.spacing(12), flexDirection: 'row', })); @@ -141,6 +142,15 @@ const ColumnContainer = styled.div({ width: '100%', }); +const OrdinalDetailsContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'flex-start', + flexDirection: 'column', + wordBreak: 'break-all', + whiteSpace: 'pre-wrap', + width: props.isGallery ? 400 : '100%', +})); + const Row = styled.div({ display: 'flex', justifyContent: 'space-between', @@ -169,16 +179,43 @@ const WebGalleryButton = styled.button((props) => ({ marginTop: props.theme.spacing(6), })); -const ViewInExplorerButton = styled.button((props) => ({ +const ViewInExplorerButton = styled.button((props) => ({ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: 'transparent', - width: 190, - marginTop: props.theme.spacing(6), + width: props.isGallery ? 392 : 328, + height: 44, + padding: 12, + borderRadius: 12, + marginTop: props.theme.spacing(16), + marginBottom: props.theme.spacing(18), + border: `1px solid ${props.theme.colors.white_800}`, })); +const ButtonText = styled.h1((props) => ({ + ...props.theme.body_medium_m, + color: props.theme.colors.white['400'], +})); + +const ButtonHiglightedText = styled.h1((props) => ({ + ...props.theme.body_medium_m, + color: props.theme.colors.white['0'], + marginLeft: props.theme.spacing(2), + marginRight: props.theme.spacing(2), +})); + +const StyledTooltip = styled(Tooltip)` + &&& { + font-size: 12px; + background-color: #ffffff; + color: #12151e; + border-radius: 8px; + padding: 7px; + } +`; + const WebGalleryButtonText = styled.div((props) => ({ ...props.theme.body_m, fontWeight: 700, @@ -186,26 +223,6 @@ const WebGalleryButtonText = styled.div((props) => ({ textAlign: 'center', })); -const SendButton = styled.button((props) => ({ - backgroundColor: props.theme.colors.white['0'], - borderRadius: props.theme.radius(3), - display: 'flex', - width: 100, - flexDirection: 'row', - padding: '12px 14px', - alignItems: 'center', - transition: 'background-color 0.2s ease, opacity 0.2s ease', - ':hover': { - backgroundColor: props.theme.colors.action.classicLight, - opacity: 0.6, - }, - h1: { - ...props.theme.body_medium_m, - fontSize: '0.875rem', - marginLeft: props.theme.spacing(3), - }, -})); - const ButtonImage = styled.img((props) => ({ marginRight: props.theme.spacing(3), alignSelf: 'center', @@ -252,6 +269,11 @@ const CollectibleText = styled.h1((props) => ({ textAlign: 'center', })); +const GalleryCollectibleText = styled.h1((props) => ({ + ...props.theme.body_bold_l, + color: props.theme.colors.white['400'], +})); + const Text = styled.h1((props) => ({ ...props.theme.body_bold_m, textTransform: 'uppercase', @@ -295,95 +317,101 @@ const BundleLinkText = styled.div((props) => ({ marginRight: props.theme.spacing(1), })); -interface DetailSectionProps { - isGallery: boolean; -} +const GalleryButtonContainer = styled.div` + width: 190px; + border-radius: 12px; +`; + +const RowButtonContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', + columnGap: props.theme.spacing(11), + paddingBottom: props.theme.spacing(16), + marginBottom: props.theme.spacing(16), + marginTop: props.theme.spacing(4), + width: '100%', + borderBottom: `1px solid ${props.theme.colors.elevation3}`, +})); const DetailSection = styled.div((props) => ({ display: 'flex', flexDirection: !props.isGallery ? 'row' : 'column', justifyContent: 'space-between', width: '100%', - paddingRight: props.theme.spacing(20), })); -function OrdinalDetailScreen() { - const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); - const navigate = useNavigate(); - const { ordinalsAddress, network, selectedAccount } = useWalletSelector(); - const { selectedOrdinal } = useNftDataSelector(); - const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); - const { isPending, pendingTxHash } = usePendingOrdinalTxs(selectedOrdinal?.tx_id); - const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); - const [isBrc20Ordinal, setIsBrc20Ordinal] = useState(false); - const textContent = useTextOrdinalContent(selectedOrdinal!); - const theme = useTheme(); - const { hasActivatedRareSatsKey } = useWalletSelector(); - const { bundle, isPartOfABundle } = useGetUtxoOrdinalBundle( - selectedOrdinal?.output, - hasActivatedRareSatsKey, - ); - const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); - - const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); - const isTransferValid = useMemo( - () => (isBrcTransferValid(selectedOrdinal!) ? 'Valid' : 'Void'), - [selectedOrdinal], - ); - - useResetUserFlow('/ordinal-detail'); - - useEffect(() => { - if (textContent?.includes('brc-20')) { - setIsBrc20Ordinal(true); - } - }, [textContent]); - - const handleBackButtonClick = () => { - setSelectedOrdinalDetails(null); - navigate('/nft-dashboard'); - }; +const ExtensionLoaderContainer = styled.div({ + height: '100%', + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-around', + alignItems: 'center', +}); - const openInGalleryView = async () => { - setSelectedOrdinalDetails(selectedOrdinal); - await chrome.tabs.create({ - url: chrome.runtime.getURL('options.html#/nft-dashboard/ordinal-detail'), - }); - }; +const StyledBarLoader = styled(BetterBarLoader)<{ + withMarginBottom?: boolean; +}>((props) => ({ + padding: 0, + borderRadius: 6, + marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, +})); - const showAlert = () => { - setshowSendOridnalsAlert(true); - }; +const StyledSeparator = styled(Separator)` + width: 100%; +`; - const onCloseAlert = () => { - setshowSendOridnalsAlert(false); - }; +const TitleLoader = styled.div` + display: flex; + flex-direction: column; +`; - const handleSendOrdinal = async () => { - if (isPending) { - showAlert(); - return; - } +const ActionButtonsLoader = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + columnGap: props.theme.spacing(11), +})); - if (isLedgerAccount(selectedAccount)) { - await chrome.tabs.create({ - url: chrome.runtime.getURL('options.html#/send-ordinal'), - }); - return; - } +const ActionButtonLoader = styled.div((props) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + rowGap: props.theme.spacing(4), +})); - navigate('send-ordinal'); - }; +const InfoContainer = styled.div((props) => ({ + width: '100%', + display: 'flex', + justifyContent: 'space-between', + padding: `0 ${props.theme.spacing(8)}px`, +})); - const handleRedirectToTx = () => { - if (pendingTxHash) { - window.open(getBtcTxStatusUrl(pendingTxHash, network), '_blank', 'noopener,noreferrer'); - } - }; +function OrdinalDetailScreen() { + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); + const ordinalDetails = useOrdinalDetail(); + const { + ordinal, + collectionMarketData, + isLoading, + ordinalsAddress, + showSendOridnalsAlert, + isBrc20Ordinal, + isPartOfABundle, + isGalleryOpen, + brc20InscriptionStatus, + brc20InscriptionStatusColor, + textContent, + handleSendOrdinal, + onCloseAlert, + handleBackButtonClick, + openInGalleryView, + handleRedirectToTx, + openInOrdinalsExplorer, + handleNavigationToRareSatsBundle, + onCopyClick, + } = ordinalDetails; - const openInOrdinalsExplorer = () => { - window.open(`${XVERSE_ORDIVIEW_URL}/inscription/${selectedOrdinal?.id}`); - }; + useResetUserFlow('/ordinal-detail'); const ownedByView = ( @@ -401,34 +429,74 @@ function OrdinalDetailScreen() { ); - const ordinalDescriptionData = ( - <> - - {selectedOrdinal?.content_length && ( - - )} - {selectedOrdinal?.content_type && ( - - )} - {selectedOrdinal?.value && ( - - )} - {selectedOrdinal?.timestamp && ( - + const ordinalDetailAttributes = ( + + {!isGalleryOpen && ordinal?.collection_id && ( + + + + )} - {selectedOrdinal?.genesis_block_height && ( - )} - {selectedOrdinal?.location && ( - - )} - + + + {!isGalleryOpen && } + + {ordinal?.value && ( + + )} + {ordinal?.sat_ordinal && ( + + )} + + + {ordinal?.content_length && ( + + )} + {ordinal?.content_type && ( + + )} + + + {ordinal?.genesis_block_height && ( + + )} + {ordinal?.genesis_fee && ( + + )} + + + ); const showBrc20OrdinalDetail = (isGallery: boolean) => { @@ -462,12 +530,8 @@ function OrdinalDetailScreen() { @@ -510,18 +574,10 @@ function OrdinalDetailScreen() { return null; } } catch (error) { - return isGallery ? ordinalDescriptionData : ownedByView; + return isGallery ? ordinalDetailAttributes : ownedByView; } }; - const handleNavigationToRareSatsBundle = () => { - if (!bundle) { - return; - } - setSelectedSatBundleDetails(bundle); - navigate('/nft-dashboard/rare-sats-bundle'); - }; - const rareSats = isPartOfABundle && ( @@ -537,80 +593,155 @@ function OrdinalDetailScreen() { ); - const extensionView = ( + const extensionView = isLoading ? ( + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + +
+
+
+ ) : ( - {isBrc20Ordinal ? t('BRC20_INSCRIPTION') : t('COLLECTIBLE')} + {isBrc20Ordinal ? t('BRC20_INSCRIPTION') : ordinal?.collection_name || t('INSCRIPTION')} - {`${t('INSCRIPTION')} ${selectedOrdinal?.number}`} + {ordinal?.number} <> {t('WEB_GALLERY')} - - - - + - - - arrow -

{t('SEND')}

-
-
+ + } + text={t('SEND')} + onPress={handleSendOrdinal} + /> + } + text={t('SHARE')} + onPress={onCopyClick} + hoverDialogId={`copy-url-${ordinal?.id}`} + isTransparent + /> + + {rareSats} - {isBrc20Ordinal ? showBrc20OrdinalDetail(false) : ownedByView} + {isBrc20Ordinal ? showBrc20OrdinalDetail(false) : ordinalDetailAttributes} + + {t('VIEW_IN')} + {t('ORDINAL_VIEWER')} +
); const galleryView = ( - - - - - - {`${t('INSCRIPTION')} ${selectedOrdinal?.number}` ?? t('INSCRIPTION')} - - - - - - - - - - - - - {ownedByView} - - - {t('DESCRIPTION')} - {rareSats} - {isBrc20Ordinal ? showBrc20OrdinalDetail(true) : ordinalDescriptionData} - - - + + + + + + + + + + + + + {isBrc20Ordinal + ? t('BRC20_INSCRIPTION') + : ordinal?.collection_name || t('INSCRIPTION')} + + {ordinal?.number} + + {t('OWNED_BY')} + {`${ordinalsAddress.substring( + 0, + 4, + )}...${ordinalsAddress.substring( + ordinalsAddress.length - 4, + ordinalsAddress.length, + )}`} + + + + + } + text={t('SEND')} + onPress={handleSendOrdinal} + /> + + + } + text={t('SHARE')} + onPress={onCopyClick} + hoverDialogId={`copy-url-${ordinal?.id}`} + transparent + /> + + + + {t('DATA')} + {rareSats} + {isBrc20Ordinal ? showBrc20OrdinalDetail(true) : ordinalDetailAttributes} + + {t('VIEW_IN')} + {t('ORDINAL_VIEWER')} + + + + + ); + const displayContent = isGalleryOpen && ordinal !== null ? galleryView : extensionView; + return ( <> {isGalleryOpen ? ( @@ -618,18 +749,16 @@ function OrdinalDetailScreen() { ) : ( )} - - {showSendOridnalsAlert && ( - - )} - {isGalleryOpen && selectedOrdinal !== null ? galleryView : extensionView} - + {showSendOridnalsAlert && ( + + )} + {displayContent} {!isGalleryOpen && ( diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts new file mode 100644 index 000000000..5b6c4d4eb --- /dev/null +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -0,0 +1,133 @@ +import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; +import useInscriptionCollectionMarketData from '@hooks/queries/ordinals/useCollectionMarketData'; +import useAddressInscription from '@hooks/queries/ordinals/useInscription'; +import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; +import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; +import { + getInscriptionsCollectionGridItemSubText, + getInscriptionsCollectionGridItemSubTextColor, +} from '@utils/inscriptions'; +import { useEffect, useMemo, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; + +export default function useOrdinalDetail() { + const navigate = useNavigate(); + const { ordinalsAddress, network, selectedAccount } = useWalletSelector(); + const { id } = useParams(); + const { selectedOrdinal } = useNftDataSelector(); + const { data: ordinalData, isLoading } = useAddressInscription(id!, selectedOrdinal); + const { data: collectionMarketData } = useInscriptionCollectionMarketData( + ordinalData?.collection_id, + ); + + const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); + const { isPending, pendingTxHash } = usePendingOrdinalTxs(ordinalData?.tx_id); + const textContent = useTextOrdinalContent(ordinalData!); + const { hasActivatedRareSatsKey } = useWalletSelector(); + const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); + const { bundle, isPartOfABundle } = useGetUtxoOrdinalBundle( + ordinalData?.output, + hasActivatedRareSatsKey, + ); + + const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); + const [isBrc20Ordinal, setIsBrc20Ordinal] = useState(false); + + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + const brc20InscriptionStatus = getInscriptionsCollectionGridItemSubText(ordinalData); + const brc20InscriptionStatusColor = getInscriptionsCollectionGridItemSubTextColor(ordinalData); + + useEffect(() => { + if (textContent?.includes('brc-20')) { + setIsBrc20Ordinal(true); + } + }, [textContent]); + + const handleBackButtonClick = () => { + setSelectedOrdinalDetails(null); + if (ordinalData?.collection_id) + navigate(`/nft-dashboard/ordinals-collection/${ordinalData?.collection_id}`); + else navigate('/nft-dashboard'); + }; + + const openInGalleryView = async () => { + if (ordinalData) setSelectedOrdinalDetails(ordinalData); + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/nft-dashboard/ordinal-detail/${id}`), + }); + }; + + const showAlert = () => { + setshowSendOridnalsAlert(true); + }; + + const onCloseAlert = () => { + setshowSendOridnalsAlert(false); + }; + + const handleSendOrdinal = async () => { + if (isPending) { + showAlert(); + return; + } + if (ordinalData) setSelectedOrdinalDetails(ordinalData); + if (isLedgerAccount(selectedAccount)) { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/nft-dashboard/ordinal-detail/${id}/send-ordinal`), + }); + return; + } + + navigate('send-ordinal'); + }; + + const handleRedirectToTx = () => { + if (pendingTxHash) { + window.open(getBtcTxStatusUrl(pendingTxHash, network), '_blank', 'noopener,noreferrer'); + } + }; + + const openInOrdinalsExplorer = () => { + window.open(`${XVERSE_ORDIVIEW_URL}/inscription/${ordinalData?.id}`); + }; + + const handleNavigationToRareSatsBundle = () => { + if (!bundle) { + return; + } + setSelectedSatBundleDetails(bundle); + navigate('/nft-dashboard/rare-sats-bundle'); + }; + + const onCopyClick = () => { + navigator.clipboard.writeText(`${XVERSE_ORDIVIEW_URL}/inscription/${ordinalData?.id}`); + }; + + return { + ordinal: ordinalData, + collectionMarketData, + isLoading, + ordinalsAddress, + showSendOridnalsAlert, + isBrc20Ordinal, + isPartOfABundle, + isGalleryOpen, + brc20InscriptionStatus, + brc20InscriptionStatusColor, + textContent, + handleSendOrdinal, + onCloseAlert, + handleBackButtonClick, + openInGalleryView, + handleRedirectToTx, + openInOrdinalsExplorer, + handleNavigationToRareSatsBundle, + onCopyClick, + }; +} diff --git a/src/app/screens/ordinals/brc20Tile.tsx b/src/app/screens/ordinals/brc20Tile.tsx index 6ff4a22cb..8d1d6440b 100644 --- a/src/app/screens/ordinals/brc20Tile.tsx +++ b/src/app/screens/ordinals/brc20Tile.tsx @@ -1,5 +1,6 @@ import PlaceholderImage from '@assets/img/nftDashboard/nft_fallback.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; +import { Brc20Definition } from '@utils/brc20'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import stc from 'string-to-color'; @@ -41,38 +42,73 @@ const OrdinalContentText = styled.h1((props) => ({ interface TextProps { inNftSend?: boolean; withoutSizeIncrease?: boolean; + isSmallImage?: boolean; } -const BRC20Text = styled.h1((props) => ({ - ...props.theme.body_bold_l, - color: props.theme.colors.white[0], - fontSize: props.inNftSend || props.withoutSizeIncrease ? 16 : 'calc(0.8vw + 2vh)', - textAlign: 'center', -})); +const BRC20Text = styled.h1((props) => { + let fontSize = 'calc(0.8vw + 2vh)'; + if (props.isSmallImage) { + fontSize = '0.625rem'; + } else if (props.inNftSend || props.withoutSizeIncrease) { + fontSize = '1rem'; + } + + return { + ...props.theme.body_bold_l, + color: props.theme.colors.white[0], + fontSize, + textAlign: 'center', + }; +}); interface TickerProps { enlargeTicker?: boolean; + isSmallImage?: boolean; + isGalleryOpen?: boolean; } -const TickerIconContainer = styled.div((props) => ({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: props.enlargeTicker ? 50 : 34.65, - width: props.enlargeTicker ? 50 : 34.65, - marginTop: 3, - marginBottom: 3, - borderRadius: 50, - backgroundColor: props.color, -})); +const TickerIconContainer = styled.div((props) => { + let size = 34.65; + if (props.isSmallImage) { + size = 25; + } else if (props.isGalleryOpen && props.enlargeTicker) { + size = 80; + } else if (props.isGalleryOpen || props.enlargeTicker) { + size = 56; + } -const TickerIconText = styled.h1((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], - textAlign: 'center', - wordBreak: 'break-all', - fontSize: 10, -})); + return { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: size, + width: size, + marginTop: 3, + marginBottom: 3, + borderRadius: 50, + backgroundColor: props.color, + }; +}); + +const TickerIconText = styled.h1<{ + enlargeTicker?: boolean; + isGalleryOpen?: boolean; +}>((props) => { + let fontSize = '0.625rem'; + if (props.enlargeTicker && props.isGalleryOpen) { + fontSize = '1.25rem'; + } else if (props.enlargeTicker || props.isGalleryOpen) { + fontSize = '0.875rem'; + } + + return { + ...props.theme.body_bold_m, + color: props.theme.colors.white['0'], + textAlign: 'center', + wordBreak: 'break-all', + fontSize, + }; +}); const OrdinalsTag = styled.div((props) => ({ display: 'flex', @@ -103,12 +139,13 @@ const Text = styled.h1((props) => ({ })); interface Brc20TileProps { - brcContent: string; + brcContent: Brc20Definition; isNftDashboard?: boolean; inNftDetail?: boolean; isSmallImage?: boolean; isGalleryOpen: boolean; withoutSizeIncrease?: boolean; + withoutTitles?: boolean; } export default function Brc20Tile(props: Brc20TileProps) { @@ -119,23 +156,27 @@ export default function Brc20Tile(props: Brc20TileProps) { inNftDetail, isGalleryOpen, withoutSizeIncrease, + withoutTitles, } = props; const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); - function renderFTIcon(ticker: string) { + const renderFTIcon = (ticker: string) => { const background = stc(ticker.toUpperCase()); ticker = ticker && ticker.substring(0, 4); return ( - - {ticker} + + + {ticker} + ); - } + }; try { - const regex = /”/g; - const validBrcContentValue = brcContent.replace(regex, '"'); - const content = JSON.parse(validBrcContentValue); - const generateOrdinalContent = (type: 'MINT' | 'TRANSFER' | 'DEPLOY') => ( - {t(type)} - {renderFTIcon(content?.tick)} - {type !== 'DEPLOY' && ( + {!withoutTitles && ( + + {t(type)} + + )} + {renderFTIcon(brcContent?.tick)} + {!withoutTitles && type !== 'DEPLOY' && ( ( - {text} + + {text} + )} /> )} @@ -165,7 +212,7 @@ export default function Brc20Tile(props: Brc20TileProps) { ); - switch (content?.op) { + switch (brcContent?.op) { case 'mint': return generateOrdinalContent('MINT'); case 'transfer': @@ -187,7 +234,7 @@ export default function Brc20Tile(props: Brc20TileProps) { isGalleryOpen={isGalleryOpen} > - {brcContent} + {JSON.stringify(brcContent)} {isNftDashboard && ( diff --git a/src/app/screens/ordinals/index.tsx b/src/app/screens/ordinals/index.tsx index 223b4c765..7ce326e4b 100644 --- a/src/app/screens/ordinals/index.tsx +++ b/src/app/screens/ordinals/index.tsx @@ -50,7 +50,7 @@ function Ordinal({ asset, isGalleryOpen }: Props) { const handleOnClick = () => { setSelectedOrdinalDetails(asset); - navigate('/nft-dashboard/ordinal-detail'); + navigate(`/nft-dashboard/ordinal-detail/${asset.id}`); }; return ( diff --git a/src/app/screens/ordinals/ordinalImage.tsx b/src/app/screens/ordinals/ordinalImage.tsx index f7cc4dae1..2bdb38434 100644 --- a/src/app/screens/ordinals/ordinalImage.tsx +++ b/src/app/screens/ordinals/ordinalImage.tsx @@ -1,13 +1,14 @@ import PlaceholderImage from '@assets/img/nftDashboard/nft_fallback.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; +import { BetterBarLoader } from '@components/barLoader'; import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; -import { Inscription, getErc721Metadata } from '@secretkeylabs/xverse-core'; +import { CondensedInscription, getErc721Metadata, Inscription } from '@secretkeylabs/xverse-core'; +import { getBrc20Details } from '@utils/brc20'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; import { getFetchableUrl } from '@utils/helper'; import Image from 'rc-image'; -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { MoonLoader } from 'react-spinners'; import styled from 'styled-components'; import Brc20Tile from './brc20Tile'; @@ -60,21 +61,6 @@ const OrdinalsTag = styled.div((props) => ({ padding: '3px 6px', })); -const LoaderContainer = styled.div((props) => ({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - position: 'absolute', - width: '100%', - height: props.isGalleryOpen ? 300 : 150, - minHeight: props.isGalleryOpen ? 300 : 150, - maxHeight: props.isGalleryOpen ? 300 : 150, - left: 0, - bottom: 0, - right: 0, - top: 0, -})); - const Text = styled.h1((props) => ({ ...props.theme.body_bold_m, textTransform: 'uppercase', @@ -119,13 +105,22 @@ const StyledImage = styled(Image)` image-rendering: pixelated; `; +export const StyledBarLoader = styled(BetterBarLoader)<{ + withMarginBottom?: boolean; +}>((props) => ({ + padding: 0, + borderRadius: 6, + marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, +})); + interface Props { - ordinal: Inscription; + ordinal: Inscription | CondensedInscription; isNftDashboard?: boolean; inNftDetail?: boolean; inNftSend?: boolean; isSmallImage?: boolean; withoutSizeIncrease?: boolean; + withoutTitles?: boolean; } function OrdinalImage({ @@ -135,6 +130,7 @@ function OrdinalImage({ inNftSend = false, isSmallImage = false, withoutSizeIncrease = false, + withoutTitles = false, }: Props) { const isGalleryOpen: boolean = document.documentElement.clientWidth > 360 && !withoutSizeIncrease; const textContent = useTextOrdinalContent(ordinal); @@ -175,9 +171,7 @@ function OrdinalImage({ - - + } src={src} /> @@ -190,11 +184,18 @@ function OrdinalImage({ ); - if (ordinal?.content_type.includes('image/svg')) { + const contentType = ordinal?.content_type ?? ''; + + const brc20Details = useMemo( + () => getBrc20Details(textContent!, contentType), + [textContent, contentType], + ); + + if (contentType.includes('image/svg')) { return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL}/thumbnail/${ordinal.id}`); } - if (ordinal?.content_type.includes('image')) { + if (contentType.includes('image')) { return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL}/content/${ordinal.id}`); } @@ -202,35 +203,30 @@ function OrdinalImage({ return renderImage('BRC-721e', brc721eImage); } - if ( - (ordinal?.content_type.includes('text/plain') || - ordinal?.content_type.includes('application/json')) && - textContent?.includes('brc-20') - ) { + if (brc20Details) { return ( ); } - if (ordinal?.content_type.includes('text')) { + if (contentType.includes('text')) { if (!textContent) { return ( - - - + ); } - if (ordinal?.content_type.includes('html')) { + if (contentType.includes('html')) { return ( diff --git a/src/app/screens/ordinalsCollection/index.tsx b/src/app/screens/ordinalsCollection/index.tsx new file mode 100644 index 000000000..0c8a032be --- /dev/null +++ b/src/app/screens/ordinalsCollection/index.tsx @@ -0,0 +1,254 @@ +import AccountHeaderComponent from '@components/accountHeader'; +import ActionButton from '@components/button'; +import CollectibleDetailTile from '@components/collectibleDetailTile'; +import Separator from '@components/separator'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import WebGalleryButton from '@components/webGalleryButton'; +import WrenchErrorMessage from '@components/wrenchErrorMessage'; +import useAddressInscriptions from '@hooks/queries/ordinals/useAddressInscriptions'; +import useInscriptionCollectionMarketData from '@hooks/queries/ordinals/useCollectionMarketData'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import { ArrowLeft } from '@phosphor-icons/react'; +import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; +import { TilesSkeletonLoader } from '@screens/nftDashboard/tilesSkeletonLoader'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams } from 'react-router-dom'; +import styled from 'styled-components'; +import { OrdinalsCollectionGridItem } from './ordinalsCollectionGridItem'; + +interface DetailSectionProps { + isGalleryOpen?: boolean; +} + +/* layout */ +// TODO tim: create a reusable layout +const Container = styled.div` + overflow-y: auto; + display: flex; + flex-direction: column; + flex: 1; + overflow-y: auto; + ${(props) => props.theme.scrollbar} +`; + +const PageHeader = styled.div` + padding: ${(props) => props.theme.space.s}; + padding-top: 0; + max-width: 1224px; + margin-top: ${(props) => (props.isGalleryOpen ? props.theme.space.xxl : props.theme.space.l)}; + margin-left: auto; + margin-right: auto; + width: 100%; +`; + +// TODO tim: use media queries for this once we get responsive layouts with breakpoints +const PageHeaderContent = styled.div` + display: flex; + flex-direction: ${(props) => (props.isGalleryOpen ? 'row' : 'column')}; + justify-content: ${(props) => (props.isGalleryOpen ? 'space-between' : 'initial')}; + row-gap: ${(props) => props.theme.space.xl}; +`; + +const AttributesContainer = styled.div` + display: flex; + flex-direction: ${(props) => (props.isGalleryOpen ? 'column' : 'row')}; + justify-content: ${(props) => (props.isGalleryOpen ? 'space-between' : 'initial')}; + column-gap: ${(props) => props.theme.space.m}; + max-width: 285px; +`; + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const StyledSeparator = styled(Separator)` + margin-bottom: ${(props) => props.theme.space.xxl}; +`; + +const StyledGridContainer = styled(GridContainer)` + margin-top: ${(props) => props.theme.space.s}; + padding: 0 ${(props) => props.theme.space.s}; + padding-bottom: ${(props) => props.theme.space.xl}; + max-width: 1224px; + margin-left: auto; + margin-right: auto; + width: 100%; +`; + +/* components */ + +const StyledWebGalleryButton = styled(WebGalleryButton)` + margin-top: ${(props) => props.theme.space.xs}; +`; + +const StyledWrenchErrorMessage = styled(WrenchErrorMessage)` + margin-top: ${(props) => props.theme.space.xxl}; +`; + +const BackButtonContainer = styled.div` + display: flex; + flex-direction: row; + margin-bottom: ${(props) => props.theme.space.xxl}; +`; + +const BackButton = styled.button((props) => ({ + display: 'flex', + alignItems: 'center', + gap: props.theme.space.xxs, + background: 'transparent', + marginBottom: props.theme.spacing(12), + color: props.theme.colors.white_0, +})); + +const NoCollectiblesText = styled.p((props) => ({ + ...props.theme.body_bold_m, + color: props.theme.colors.white_200, + marginTop: props.theme.spacing(16), + marginBottom: 'auto', + textAlign: 'center', +})); + +const LoadMoreButtonContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginBottom: props.theme.spacing(30), + marginTop: props.theme.space.xl, + button: { + width: 156, + }, +})); + +const LoaderContainer = styled.div((props) => ({ + width: '100%', + display: 'flex', + justifyContent: 'space-between', + paddingLeft: props.theme.spacing(6), + paddingRight: props.theme.spacing(6), +})); + +const StyledTilesSkeletonLoader = styled(TilesSkeletonLoader)` + width: 100%; +`; + +function OrdinalsCollection() { + const { t } = useTranslation('translation', { keyPrefix: 'ORDINALS_COLLECTION_SCREEN' }); + const navigate = useNavigate(); + const { id: collectionId } = useParams(); + const { data, error, isLoading, hasNextPage, isFetchingNextPage, fetchNextPage } = + useAddressInscriptions(collectionId); + const { data: collectionMarketData } = useInscriptionCollectionMarketData(collectionId); + + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + + useResetUserFlow('/ordinals-collection'); + + const handleBackButtonClick = () => { + navigate('/nft-dashboard?tab=inscriptions'); + }; + + const openInGalleryView = async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/nft-dashboard/ordinals-collection/${collectionId}`), + }); + }; + + const isEmpty = !isLoading && !error && data?.pages?.[0]?.data?.total === 0; + + const collectionHeading = data?.pages?.[0].collection_name; + const estPortfolioValue = + data && data?.pages?.[0].portfolio_value !== 0 + ? `${data?.pages?.[0].portfolio_value.toFixed(10)} BTC` + : '--'; + const collectionFloorPrice = collectionMarketData?.floor_price + ? `${collectionMarketData?.floor_price?.toFixed(10).toString()} BTC` + : '--'; + + return ( + <> + {isGalleryOpen ? ( + + ) : ( + + )} + + + {isGalleryOpen && ( + + + + + {t('BACK_TO_GALLERY')} + + + + )} + +
+ + {t('COLLECTION')} + + + {collectionHeading} + + {!isGalleryOpen && } +
+ + + + +
+
+ {isGalleryOpen && } +
+ {isLoading && ( + + + + )} + {isEmpty && {t('NO_COLLECTIBLES')}} + {!!error && } + + {data?.pages + ?.map((page) => page?.data) + .flat() + .map((inscription) => ( + + ))} + + {hasNextPage && ( + + + + )} +
+
+ {!isGalleryOpen && ( + + + + )} + + ); +} + +export default OrdinalsCollection; diff --git a/src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx b/src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx new file mode 100644 index 000000000..933c6d92a --- /dev/null +++ b/src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx @@ -0,0 +1,83 @@ +import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import type { Inscription } from '@secretkeylabs/xverse-core'; +import { StyledP } from '@ui-library/common.styled'; +import { + getInscriptionsCollectionGridItemId, + getInscriptionsCollectionGridItemSubText, + getInscriptionsCollectionGridItemSubTextColor, +} from '@utils/inscriptions'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; + +const InfoContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; +`; + +const StyledItemId = styled(StyledP)` + text-align: left; + text-wrap: nowrap; + overflow: hidden; + width: 100%; +`; + +const StyledItemSub = styled(StyledP)` + text-align: left; + text-overflow: ellipsis; + text-wrap: nowrap; + overflow: hidden; + width: 100%; + text-transform: capitalize; +`; + +const ImageContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + aspect-ratio: 1; + overflow: hidden; + border-radius: ${(props) => props.theme.radius(3)}px; + background: ${(props) => props.theme.colors.elevation1}; +`; + +const GridItemContainer = styled.button` + display: flex; + flex-direction: column; + background: transparent; + gap: ${(props) => props.theme.space.s}; +`; + +export function OrdinalsCollectionGridItem({ item }: { item: Inscription }) { + const navigate = useNavigate(); + const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); + + const handleOnClick = () => { + setSelectedOrdinalDetails(item); + navigate(`/nft-dashboard/ordinal-detail/${item.id}`); + }; + + const itemId = getInscriptionsCollectionGridItemId(item); + const itemSubText = getInscriptionsCollectionGridItemSubText(item); + const itemSubTextColor = getInscriptionsCollectionGridItemSubTextColor(item); + + return ( + + + + + + + {itemId} + + + {itemSubText} + + + + ); +} +export default OrdinalsCollectionGridItem; diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx index 20d0298fa..ed00dc4ef 100644 --- a/src/app/screens/rareSatsBundle/index.tsx +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -2,23 +2,24 @@ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import AccountHeaderComponent from '@components/accountHeader'; import AlertMessage from '@components/alertMessage'; import ActionButton from '@components/button'; +import Separator from '@components/separator'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; +import WebGalleryButton from '@components/webGalleryButton'; import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; +import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; +import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; +import { BundleItem } from '@utils/rareSats'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; -import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; -import { StyledHeading, StyledP } from '@ui-library/common.styled'; -import WebGalleryButton from '@components/webGalleryButton'; -import { BundleItem } from '@utils/rareSats'; -import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; import { RareSatsBundleGridItem } from './rareSatsBundleGridItem'; @@ -53,11 +54,8 @@ const AttributesContainer = styled.div` max-width: 285px; `; -const StyledSeparator = styled.hr` - margin-top: ${(props) => props.theme.space.m}; +const StyledSeparator = styled(Separator)` margin-bottom: ${(props) => props.theme.space.xxl}; - border: none; - border-top: 1px solid ${(props) => props.theme.colors.elevation3}; `; const StyledGridContainer = styled(GridContainer)` diff --git a/src/app/screens/receive/index.tsx b/src/app/screens/receive/index.tsx index 32bb91a84..4c84ae8a4 100644 --- a/src/app/screens/receive/index.tsx +++ b/src/app/screens/receive/index.tsx @@ -1,18 +1,18 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import TopRow from '@components/topRow'; -import { useNavigate, useParams } from 'react-router-dom'; -import QRCode from 'react-qr-code'; import Copy from '@assets/img/dashboard/copy_black_icon.svg'; import Tick from '@assets/img/dashboard/tick.svg'; -import { useState } from 'react'; import ActionButton from '@components/button'; -import useWalletSelector from '@hooks/useWalletSelector'; -import BottomTabBar from '@components/tabBar'; import InfoContainer from '@components/infoContainer'; import ShowBtcReceiveAlert from '@components/showBtcReceiveAlert'; import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; -import { isLedgerAccount } from '@utils/helper'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import QRCode from 'react-qr-code'; +import { useNavigate, useParams } from 'react-router-dom'; +import styled from 'styled-components'; +import UpdatedReceive from './updatedReceiveScreen'; const OuterContainer = styled.div` display: flex; @@ -157,7 +157,10 @@ function Receive(): JSX.Element { } }; - return ( + // TODO: Shift UpdatedReceive logic in this file and handle STX & BTC UI + return currency === 'ORD' ? ( + + ) : ( <> diff --git a/src/app/screens/receive/qrCode.tsx b/src/app/screens/receive/qrCode.tsx new file mode 100644 index 000000000..d645b63c2 --- /dev/null +++ b/src/app/screens/receive/qrCode.tsx @@ -0,0 +1,71 @@ +import QRCodeStyling, { DotType, Options } from 'qr-code-styling'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import styled from 'styled-components'; + +interface Props { + image: string; + data: string; + gradientColor: string; +} + +const QRCodeContainer = styled.div({ + display: 'flex', +}); + +function QrCode({ image, data, gradientColor }: Props) { + const options: Options = useMemo( + () => ({ + width: 154, + height: 154, + data, + image, + dotsOptions: { + color: 'white', + type: 'dots' as DotType, + gradient: { + type: 'radial', + rotation: 90, + colorStops: [ + { offset: 0, color: gradientColor }, + { offset: 1, color: '#000000' }, + ], + }, + }, + backgroundOptions: { + color: 'white', + }, + cornersSquareOptions: { + color: 'black', + type: 'dot', + }, + cornersDotOptions: { + color: 'black', + type: 'dot', + }, + imageOptions: { + hideBackgroundDots: true, + imageSize: 1, + }, + qrOptions: { + errorCorrectionLevel: 'L', + }, + }), + [data, image, gradientColor], + ); + const [qrCode] = useState(new QRCodeStyling(options)); + const ref = useRef(null); + useEffect(() => { + if (ref.current) { + qrCode.append(ref.current); + } + }, [qrCode, ref]); + + useEffect(() => { + if (!qrCode) return; + qrCode.update(options); + }, [qrCode, options]); + + return ; +} + +export default QrCode; diff --git a/src/app/screens/receive/updatedReceiveScreen.tsx b/src/app/screens/receive/updatedReceiveScreen.tsx new file mode 100644 index 000000000..5745fa7f5 --- /dev/null +++ b/src/app/screens/receive/updatedReceiveScreen.tsx @@ -0,0 +1,177 @@ +import Ordinal from '@assets/img/receive_ordinals_image.svg'; +import ShowBtcReceiveAlert from '@components/showBtcReceiveAlert'; +import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { Check, Copy } from '@phosphor-icons/react'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import { Tooltip } from 'react-tooltip'; +import styled from 'styled-components'; +import QrCode from './qrCode'; + +export const OuterContainer = styled.div((props) => ({ + ...props.theme.scrollbar, + display: 'flex', + flexDirection: 'column', + flex: 1, + paddingLeft: props.theme.spacing(4), + paddingRight: props.theme.spacing(4), +})); + +const TopTitleText = styled.h1((props) => ({ + ...props.theme.headline_s, + textAlign: 'center', + marginTop: props.theme.spacing(12), +})); + +const DescriptionText = styled.p((props) => ({ + ...props.theme.body_m, + textAlign: 'center', + color: props.theme.colors.white_200, + marginTop: props.theme.spacing(6), +})); + +const AddressContainer = styled.div((props) => ({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'flex-start', + columnGap: 16, + marginTop: props.theme.spacing(26.5), +})); + +const QRCodeContainer = styled.div((props) => ({ + display: 'flex', + backgroundColor: props.theme.colors.white['0'], + justifyContent: 'center', + alignItems: 'center', + borderRadius: props.theme.radius(1), + width: 159, + height: 159, + alignSelf: 'center', + marginTop: props.theme.spacing(15), +})); + +const AddressText = styled.h1((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white['200'], + wordBreak: 'break-all', +})); + +const BottomBarContainer = styled.div({ + marginTop: 22, +}); + +const Button = styled.button((props) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginLeft: props.theme.spacing(3), + padding: 12, + background: props.theme.colors.elevation2, + borderRadius: 24, + width: 40, + height: 40, +})); + +function UpdatedReceive(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'RECEIVE' }); + const [isCopied, setIsCopied] = useState(false); + const [isBtcReceiveAlertVisible, setIsBtcReceiveAlertVisible] = useState(false); + const [isOrdinalReceiveAlertVisible, setIsOrdinalReceiveAlertVisible] = useState(false); + const navigate = useNavigate(); + const { stxAddress, btcAddress, ordinalsAddress, showOrdinalReceiveAlert } = useWalletSelector(); + + // TODO : Get currency from param + const currency = 'ORD'; + + const getAddress = () => { + switch (currency) { + case 'STX': + return stxAddress; + case 'BTC': + return btcAddress; + case 'FT': + return stxAddress; + case 'ORD': + return ordinalsAddress; + default: + return ''; + } + }; + const handleBackButtonClick = () => { + navigate(-1); + }; + + const renderHeading = () => { + if (currency === 'ORD') { + return ( + <> + {t('ORDINAL_ADDRESS')} + {t('ORDINALS_RECEIVE_MESSAGE')} + + ); + } + return ( + <> + {t('STX_ADDRESS')} + {t('STX_RECEIVE_MESSAGE')} + + ); + }; + + const onReceiveAlertClose = () => { + setIsBtcReceiveAlertVisible(false); + }; + + const onOrdinalReceiveAlertClose = () => { + setIsOrdinalReceiveAlertVisible(false); + }; + + const handleOnClick = () => { + setIsCopied(true); + navigator.clipboard.writeText(getAddress()); + if (currency === 'ORD' && showOrdinalReceiveAlert) { + setIsOrdinalReceiveAlertVisible(true); + } + }; + + return ( + <> + + + {renderHeading()} + + + + + {getAddress()} + + + + + + + + {isBtcReceiveAlertVisible && ( + + )} + {isOrdinalReceiveAlertVisible && ( + + )} + + ); +} + +export default UpdatedReceive; diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index f2059638c..c475a2b10 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -1,15 +1,13 @@ -import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import AccountHeaderComponent from '@components/accountHeader'; -import SendForm from '@components/sendForm'; +import ActionButton from '@components/button'; import BottomBar from '@components/tabBar'; import TopRow from '@components/topRow'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; import useWalletSelector from '@hooks/useWalletSelector'; -import OrdinalImage from '@screens/ordinals/ordinalImage'; -import { isOrdinalOwnedByAccount } from '@secretkeylabs/xverse-core/api'; +import { ArrowLeft } from '@phosphor-icons/react'; +import { isOrdinalOwnedByAccount } from '@secretkeylabs/xverse-core'; import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; import { SignedBtcTx, @@ -18,86 +16,127 @@ import { import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { useMutation } from '@tanstack/react-query'; +import Callout from '@ui-library/callout'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { InputFeedback, InputFeedbackProps, isDangerFeedback } from '@ui-library/inputFeedback'; import { isLedgerAccount } from '@utils/helper'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import { devices } from 'theme'; -const ScrollContainer = styled.div` +const ScrollContainer = styled.div((props) => ({ + display: 'flex', + flex: 1, + flexDirection: 'column', + ...props.theme.scrollbar, +})); + +const Container = styled.div` display: flex; flex: 1; flex-direction: column; - overflow-y: auto; - &::-webkit-scrollbar { - display: none; - } - width: 360px; margin: auto; + margin-top: ${(props) => props.theme.space.xxs}; + padding: 0 ${(props) => props.theme.space.s}; + justify-content: space-between; + max-width: 360px; + + @media only screen and ${devices.min.s} { + flex: initial; + max-width: 588px; + border: 1px solid ${(props) => props.theme.colors.elevation3}; + border-radius: ${(props) => props.theme.space.s}; + padding: ${(props) => props.theme.space.l} ${(props) => props.theme.space.m}; + padding-bottom: ${(props) => props.theme.space.xxl}; + margin-top: ${(props) => props.theme.space.xxxxl}; + min-height: 600px; + } `; -const Container = styled.div({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - flex: 1, -}); +const FooterContainer = styled.div` + display: flex; + justify-content: center; + margin-bottom: ${(props) => props.theme.space.xxl}; +`; -const NftContainer = styled.div((props) => ({ - maxHeight: 148, - width: 148, - display: 'flex', - aspectRatio: 1, - justifyContent: 'center', - alignItems: 'center', - borderRadius: 8, - marginTop: props.theme.spacing(8), - marginBottom: props.theme.spacing(6), -})); +const StyledSendTo = styled(StyledHeading)` + margin-bottom: ${(props) => props.theme.space.l}; +`; -const OrdinalInscriptionNumber = styled.h1((props) => ({ - ...props.theme.headline_s, - color: props.theme.colors.white['0'], - textAlign: 'center', +const NextButtonContainer = styled.div((props) => ({ + position: 'sticky', + bottom: 0, + paddingBottom: props.theme.spacing(12), + paddingTop: props.theme.spacing(12), + backgroundColor: props.theme.colors.elevation0, })); -const BottomBarContainer = styled.div({ - marginTop: 'auto', -}); +const InputGroup = styled.div` + margin-top: ${(props) => props.theme.spacing(8)}px; +`; -const ButtonContainer = styled.div((props) => ({ +const Label = styled.label((props) => ({ + ...props.theme.body_medium_m, + color: props.theme.colors.white_200, display: 'flex', - flexDirection: 'row', - marginLeft: '15%', - marginTop: props.theme.spacing(40), + flex: 1, })); -const Button = styled.button((props) => ({ +const AmountInputContainer = styled.div<{ error: boolean }>((props) => ({ display: 'flex', flexDirection: 'row', - justifyContent: 'flex-end', alignItems: 'center', + marginTop: props.theme.spacing(4), + marginBottom: props.theme.spacing(4), + border: props.error + ? `1px solid ${props.theme.colors.danger_dark_200}` + : `1px solid ${props.theme.colors.white_800}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - opacity: 0.8, - marginTop: props.theme.spacing(5), + paddingLeft: props.theme.spacing(5), + paddingRight: props.theme.spacing(5), + height: 44, +})); + +const InputFieldContainer = styled.div(() => ({ + flex: 1, })); -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, +const InputField = styled.input((props) => ({ + ...props.theme.body_m, + backgroundColor: 'transparent', color: props.theme.colors.white['0'], - textAlign: 'center', + width: '100%', + border: 'transparent', })); -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', +const ErrorContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(3), + marginBottom: props.theme.spacing(12), })); +const RowContainer = styled.div({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', +}); + +const StyledCallout = styled(Callout)` + margin-bottom: ${(props) => props.theme.spacing(14)}px; +`; + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const Button = styled.button` + display: flex; + background-color: transparent; + margin-bottom: ${(props) => props.theme.space.l}; +`; + function SendOrdinal() { const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); const navigate = useNavigate(); @@ -107,15 +146,11 @@ function SendOrdinal() { const { network, ordinalsAddress, btcAddress, selectedAccount, seedPhrase, btcFiatRate } = useWalletSelector(); const [ordinalUtxo, setOrdinalUtxo] = useState(undefined); - const [error, setError] = useState(''); - const [recipientAddress, setRecipientAddress] = useState(''); - const [warning, setWarning] = useState(''); + const [recipientAddress, setRecipientAddress] = useState(location.state?.recipientAddress ?? ''); + const [recipientError, setRecipientError] = useState(null); + + useResetUserFlow('/send-ordinal'); - const textContent = useTextOrdinalContent(selectedOrdinal!); - const address: string | undefined = useMemo( - () => (location.state ? location.state.recipientAddress : undefined), - [location.state], - ); const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); const { @@ -127,7 +162,7 @@ function SendOrdinal() { mutationFn: async (recipient) => { const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); const ordUtxo = addressUtxos.find( - (utx) => `${utx.txid}:${utx.vout}` === selectedOrdinal?.output, + (utxo) => `${utxo.txid}:${utxo.vout}` === selectedOrdinal?.output, ); setOrdinalUtxo(ordUtxo); if (ordUtxo) { @@ -148,12 +183,14 @@ function SendOrdinal() { useEffect(() => { if (txError) { if (Number(txError) === ErrorCodes.InSufficientBalance) { - setError(t('ERRORS.INSUFFICIENT_BALANCE')); + setRecipientError({ variant: 'danger', message: t('ERRORS.INSUFFICIENT_BALANCE') }); } else if (Number(txError) === ErrorCodes.InSufficientBalanceWithTxFee) { - setError(t('ERRORS.INSUFFICIENT_BALANCE_FEES')); - } else setError(txError.toString()); + setRecipientError({ variant: 'danger', message: t('ERRORS.INSUFFICIENT_BALANCE_FEES') }); + } else { + setRecipientError({ variant: 'danger', message: txError.toString() }); + } } - }, [txError]); + }, [txError, t]); useEffect(() => { if (data) { @@ -176,89 +213,103 @@ function SendOrdinal() { navigate(-1); }; - useResetUserFlow('/send-ordinal'); - const activeAccountOwnsOrdinal = selectedOrdinal && selectedAccount && isOrdinalOwnedByAccount(selectedOrdinal, selectedAccount); - function validateFields(associatedAddress: string): boolean { + const validateRecipientAddress = (address: string): boolean => { if (!activeAccountOwnsOrdinal) { - setError(t('ERRORS.ORDINAL_NOT_OWNED')); + setRecipientError({ variant: 'danger', message: t('ERRORS.ORDINAL_NOT_OWNED') }); return false; } - if (!associatedAddress) { - setError(t('ERRORS.ADDRESS_REQUIRED')); + if (!address) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_REQUIRED') }); return false; } - - if (!validateBtcAddress({ btcAddress: associatedAddress, network: network.type })) { - setError(t('ERRORS.ADDRESS_INVALID')); + if ( + !validateBtcAddress({ + btcAddress: address, + network: network.type, + }) + ) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_INVALID') }); return false; } - + if (address === ordinalsAddress || address === btcAddress) { + setRecipientError({ variant: 'info', message: t('YOU_ARE_TRANSFERRING_TO_YOURSELF') }); + return true; + } + setRecipientError(null); return true; - } + }; - const onPressNext = async (associatedAddress: string) => { - setRecipientAddress(associatedAddress); - if (validateFields(associatedAddress)) { - mutate(associatedAddress); + const onPressNext = async () => { + if (validateRecipientAddress(recipientAddress)) { + mutate(recipientAddress); } }; - const currencyType = textContent?.includes('brc-20') ? 'brc20-Ordinal' : 'Ordinal'; - - const handleInputChange = (inputAddress: string) => { - if (inputAddress === ordinalsAddress) { - return setWarning( - currencyType === 'brc20-Ordinal' - ? t('SEND_BRC20_ORDINAL_TO_SELF_WARNING') - : t('SEND_ORDINAL_TO_SELF_WARNING'), - ); - } - setWarning(''); + const handleAddressChange = (e: React.ChangeEvent) => { + validateRecipientAddress(e.target.value); + setRecipientAddress(e.target.value); }; + const isNextEnabled = !isDangerFeedback(recipientError) && !!recipientAddress; + const year = new Date().getFullYear(); + return ( <> {isGalleryOpen && ( - <> - - {!isLedgerAccount(selectedAccount) && ( - - - - )} - + )} + {!isGalleryOpen && } - {!isGalleryOpen && ( - + +
+ {isGalleryOpen && !isLedgerAccount(selectedAccount) && ( + + )} + + {t('SEND_TO')} + + + + + + + + + + + + {recipientError && } + + + +
+ + + +
+ {isGalleryOpen && ( + + + {t('COPYRIGHT', { year })} + + )} - - - - - - {`Inscription ${selectedOrdinal?.number}`} - - - {!isGalleryOpen && }
+ {!isGalleryOpen && } ); } diff --git a/src/app/screens/settings/privacyPreferences/index.tsx b/src/app/screens/settings/privacyPreferences/index.tsx index abc0ec011..ac32cdd50 100644 --- a/src/app/screens/settings/privacyPreferences/index.tsx +++ b/src/app/screens/settings/privacyPreferences/index.tsx @@ -1,12 +1,12 @@ -import styled, { useTheme } from 'styled-components'; import BottomBar from '@components/tabBar'; import TopRow from '@components/topRow'; -import { useNavigate } from 'react-router-dom'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { hasOptedInMixPanelTracking, optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; import Switch from 'react-switch'; -import { useEffect, useState } from 'react'; -import { hasOptedInMixPanelTracking, optInMixPanel, optOutMixPanel } from '@utils/mixpanel'; -import useWalletSelector from '@hooks/useWalletSelector'; +import styled, { useTheme } from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -21,7 +21,7 @@ const Container = styled.div((props) => ({ }, })); -const TextContiner = styled.div({ +const TextContainer = styled.div({ lineHeight: '140%', }); @@ -78,11 +78,11 @@ function PrivacyPreferencesScreen() { <> - {t('PRIVACY_PREFERENCES.DESCRIPTION')} + {t('PRIVACY_PREFERENCES.DESCRIPTION')}
{t('PRIVACY_PREFERENCES.AUTHORIZE_DATA_COLLECTION')}
({ display: 'flex', diff --git a/src/app/screens/swap/index.tsx b/src/app/screens/swap/index.tsx index 65a48ad55..eb14465be 100644 --- a/src/app/screens/swap/index.tsx +++ b/src/app/screens/swap/index.tsx @@ -1,15 +1,15 @@ -import { useNavigate } from 'react-router-dom'; -import TopRow from '@components/topRow'; -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; +import ActionButton from '@components/button'; import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import { ArrowDown } from '@phosphor-icons/react'; +import CoinSelectModal from '@screens/home/coinSelectModal'; +import { SwapInfoBlock } from '@screens/swap/swapInfoBlock'; import SwapTokenBlock from '@screens/swap/swapTokenBlock'; -import ArrowDown from '@assets/img/swap/arrow_swap.svg'; import { useSwap } from '@screens/swap/useSwap'; import { useCallback, useState } from 'react'; -import { SwapInfoBlock } from '@screens/swap/swapInfoBlock'; -import ActionButton from '@components/button'; -import CoinSelectModal from '@screens/home/coinSelectModal'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const ScrollContainer = styled.div` display: flex; @@ -34,9 +34,10 @@ const Container = styled.div((props) => ({ const DownArrowButton = styled.button((props) => ({ alignSelf: 'center', - borderRadius: props.theme.radius(3), + borderRadius: props.theme.radius(2), width: props.theme.spacing(18), height: props.theme.spacing(18), + background: props.theme.colors.elevation3, transition: 'all 0.2s ease', ':hover': { opacity: 0.8, @@ -84,7 +85,7 @@ function SwapScreen() { onSelectCoin={() => setSelecting('from')} /> - arrow-down + ` diff --git a/src/app/utils/brc20.ts b/src/app/utils/brc20.ts index 37bb79dbe..a8fe73293 100644 --- a/src/app/utils/brc20.ts +++ b/src/app/utils/brc20.ts @@ -1,4 +1,4 @@ -import { UTXO, brc20TransferEstimateFees, FungibleToken } from '@secretkeylabs/xverse-core'; +import { brc20TransferEstimateFees, FungibleToken, UTXO } from '@secretkeylabs/xverse-core'; import BigNumber from 'bignumber.js'; export type TransferEstimateResult = Awaited>; @@ -41,3 +41,88 @@ export const getFeeValuesForBrc20OneStepTransfer = ({ return { txFee, inscriptionFee, totalFee, transferUtxoValue: new BigNumber(transferUtxoValue) }; }; + +export const isValidContentType = (contentType: string) => + contentType.startsWith('text/plain') || contentType.startsWith('application/json'); + +export const isValidFields = ( + parsedFields: string[], + requiredFields: Set, + optionalFields?: Set, +) => + parsedFields.every((f) => requiredFields.has(f) || optionalFields?.has(f)) && + [...requiredFields].every((f) => parsedFields.includes(f)); + +export const isNumber = (value: string) => !Number.isNaN(Number(value)); + +export type Brc20Definition = { + op: 'deploy' | 'mint' | 'transfer'; + tick: string; + value: string; +}; + +export const getBrc20Details = ( + content: string, + contentType: string, +): undefined | Brc20Definition => { + if (!isValidContentType(contentType)) { + return undefined; + } + + try { + const parsedContent = JSON.parse(content); + + if ( + parsedContent.p !== 'brc-20' || + !['deploy', 'mint', 'transfer'].includes(parsedContent.op) + ) { + return undefined; + } + + const parsedFields = Object.keys(parsedContent); + const parsedValues = Object.values(parsedContent); + + if (parsedValues.some((v) => typeof v !== 'string')) { + return undefined; + } + + const deployRequiredFields = new Set(['p', 'op', 'tick', 'max']); + const deployOptionalFields = new Set(['lim', 'desc']); + + const mintRequiredFields = new Set(['p', 'op', 'tick', 'amt']); + + const transferRequiredFields = new Set(['p', 'op', 'tick', 'amt']); + + const isValidDeploy = + parsedContent.op === 'deploy' && + isValidFields(parsedFields, deployRequiredFields, deployOptionalFields) && + parsedContent.tick.length === 4 && + isNumber(parsedContent.max) && + (!parsedContent.lim || isNumber(parsedContent.lim)) && + (!parsedContent.desc || typeof parsedContent.desc === 'string'); + + const isValidMint = + parsedContent.op === 'mint' && + isValidFields(parsedFields, mintRequiredFields) && + parsedContent.tick.length === 4 && + isNumber(parsedContent.amt); + + const isValidTransfer = + parsedContent.op === 'transfer' && + isValidFields(parsedFields, transferRequiredFields) && + parsedContent.tick.length === 4 && + isNumber(parsedContent.amt); + + if (!isValidDeploy && !isValidMint && !isValidTransfer) { + return undefined; + } + + return { + op: parsedContent.op, + tick: parsedContent.tick.toUpperCase(), + value: parsedContent.max || parsedContent.amt, + }; + } catch (e) { + return undefined; + } +}; diff --git a/src/app/utils/inscriptions.ts b/src/app/utils/inscriptions.ts new file mode 100644 index 000000000..27a8dc6b8 --- /dev/null +++ b/src/app/utils/inscriptions.ts @@ -0,0 +1,55 @@ +import { + CondensedInscription, + Inscription, + InscriptionCollectionsData, + isBrcTransferValid, +} from '@secretkeylabs/xverse-core'; +import type { Color } from 'theme'; +import { BundleItem } from './rareSats'; + +export type Brc20Status = 'valid' | 'used'; + +export const isCollection = (collection: InscriptionCollectionsData): boolean => + collection.collection_id !== null; + +export const getCollectionKey = (collection: InscriptionCollectionsData): string => + (isCollection(collection) + ? collection.collection_id + : collection.thumbnail_inscriptions?.[0]?.id) ?? ''; + +export const getInscriptionsCollectionGridItemId = (inscription?: Inscription): string => + inscription?.number?.toString() ?? ''; + +export const getInscriptionsCollectionGridItemSubText = (inscription?: Inscription): string => { + if (inscription?.category === 'brc-20') { + return isBrcTransferValid(inscription) ? 'valid' : 'used'; + } + return ''; +}; + +export const getInscriptionsCollectionGridItemSubTextColor = (inscription?: Inscription): Color => { + if (inscription?.category === 'brc-20') { + return isBrcTransferValid(inscription) ? 'success_light' : 'white_400'; + } + return 'white_400'; +}; + +export const getInscriptionsTabGridItemId = (collection: InscriptionCollectionsData) => + (isCollection(collection) + ? collection.collection_name + : collection.thumbnail_inscriptions?.[0]?.number?.toString()) ?? ''; // TODO needs to be added to API + +export const getInscriptionsTabGridItemSubText = (collection: InscriptionCollectionsData) => { + if (!isCollection(collection)) { + return ''; + } + return collection.total_inscriptions > 1 ? `${collection.total_inscriptions} Items` : '1 Item'; +}; + +export const mapCondensedInscriptionToBundleItem = ( + inscription: CondensedInscription, +): BundleItem => ({ + inscription, + type: 'inscription', + rarity_ranking: 'common', // TODO eventually want to fetch this rarity and display it +}); diff --git a/src/app/utils/query.ts b/src/app/utils/query.ts index c16152893..db4b2b5be 100644 --- a/src/app/utils/query.ts +++ b/src/app/utils/query.ts @@ -1,5 +1,5 @@ -import { QueryClient } from '@tanstack/react-query'; import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'; +import { QueryClient } from '@tanstack/react-query'; export class InvalidParamsError extends Error { constructor(message: string) { diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index a474fa046..91a7f1ecf 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -1,5 +1,4 @@ import { t } from 'i18next'; -import type { Account } from '@secretkeylabs/xverse-core/types'; import { getTruncatedAddress } from './helper'; const RoadArmorRareSats = ['uncommon', 'rare', 'epic', 'legendary', 'mythic', 'common'] as const; diff --git a/src/assets/img/receive_ordinals_image.svg b/src/assets/img/receive_ordinals_image.svg new file mode 100644 index 000000000..15b566511 --- /dev/null +++ b/src/assets/img/receive_ordinals_image.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 3b6941066..4042e773e 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -233,17 +233,19 @@ "COPIED_ADDRESS": "Address copied to clipboard", "BTC_ADDRESS": "Bitcoin address", "ORDINAL_ADDRESS": "Ordinal & BRC-20 address", - "ORDINALS_RECEIVE_MESSAGE": "Only send Ordinals and BRC-20 tokens to this address.", + "ORDINALS_RECEIVE_MESSAGE": "Only use this address to receive Ordinals and BRC-20.", + "STX_RECEIVE_MESSAGE": "Only send SIP-010 tokens to this address.", "BTC_RECEIVE_MESSAGE": "Do not send Ordinals to this address, use your Ordinals NFT receive address." }, "SEND": { + "SEND_TO": "Send to", "SEND": "Send", "AMOUNT": "Amount", "BALANCE": "Balance", "RECIPIENT": "Recipient", "RECIPIENT_PLACEHOLDER": "STX Address or .btc domain", "BTC_RECIPIENT_PLACEHOLDER": "Enter Bitcoin address", - "ORDINAL_RECIPIENT_PLACEHOLDER": "Enter Ordinals address", + "ORDINAL_RECIPIENT_PLACEHOLDER": "Enter address", "MEMO": "Add a memo (optional)", "MEMO_PLACEHOLDER": "Memo", "ASSOCIATED_ADDRESS": "Associated Address", @@ -271,12 +273,13 @@ "ASSOCIATED_BNS_DOMAIN": "Associated BNS Name", "SWITCH_TO": "Switch to", "SEND_ORDINAL_TITLE": "Send Ordinal", - "SEND_ORDINAL_WALLET_WARNING": "You are about to transfer an Ordinal. Make sure the recipient wallet supports Ordinals.", + "MAKE_SURE_THE_RECIPIENT": "Make sure the recipient address support Ordinals. Items sent to the wrong address cannot be recovered.", "SEND_BRC20_ORDINAL_WALLET_WARNING": "Transferring this Ordinal inscription will initiate the transfer of your BRC-20 tokens.", "SEND_ORDINAL_TO_SELF_WARNING": "You are about to transfer an Ordinal to yourself", "SEND_BRC20_ORDINAL_TO_SELF_WARNING": "You are about to transfer BRC-20 tokens to yourself", "SEND_BTC_TO_SELF_WARNING": "You are about to transfer BTC to yourself", - "YOU_ARE_TRANSFERRING_TO_YOURSELF": "You are transferring to yourself" + "YOU_ARE_TRANSFERRING_TO_YOURSELF": "You are transferring to yourself", + "COPYRIGHT": "© {{year}} Secret Key Labs Limited" }, "CONFIRM_TRANSACTION": { "SEND": "Confirm Transaction", @@ -524,6 +527,7 @@ "NFT_DASHBOARD_SCREEN": { "COLLECTIBLES": "Collectibles", "NO_COLLECTIBLES": "There's nothing here yet.", + "INSCRIPTIONS": "Inscriptions", "ERROR_RETRIEVING": "We are having trouble retrieving data.", "TRY_AGAIN": "Please try again later.", "LOAD_MORE": "Load more", @@ -537,7 +541,7 @@ "MAIL": "Share by Mail", "COPY": "Copy link", "NFT_DETAIL": "Item detail", - "RECEIVE_NFT": "Receive NFT", + "RECEIVE_NFT": "Receive", "STACKS_NFT": "Stacks NFT", "ORDINALS": "Ordinals", "ORDINAL": "Ordinal", @@ -566,7 +570,7 @@ "SUPPORTED_RARITIES": "Supported rarities", "RARITY_INFO": "Currently, only the default rarity scale is supported. Your sats could have other attributes." }, - "NFTS": "INSCRIPTIONS & NFTs", + "NFTS": "NFTs", "RARE_SATS": "Rare Sats", "NEW_FEATURE": "New Feature, Rare Sats", "NEW_FEAT_RARE_SATS_DESCRIPTION": "Enable rare sats to display rare, interesting and unique sats in your wallet. You can change this setting at any time.", @@ -632,9 +636,10 @@ "CONTENT_LENGTH": "Content length", "ADDRESS": "Address", "CONTENT_TYPE": "Content type", - "OUTPUT_VALUE": "Output value", + "OUTPUT_VALUE": "Bitcoin value", "TIMESTAMP": "Timestamp", - "GENESIS_HEIGHT": "genesis height", + "GENESIS_HEIGHT": "Genesis height", + "GENESIS_FEE": "Genesis fee", "LOCATION": "Location", "ORDINAL_NOT_DISPLAYED": "This ordinal cannot be displayed.", "COLLECTIBLE": "Collectible", @@ -644,9 +649,18 @@ "BRC20_TRANSFER_STATUS": "Status", "TOTAL_SUPPLY": "Total supply", "MINT_LIMIT": "Mint limit", + "VIEW_IN": "Open in", + "ORDINAL_VIEWER": "Ordinal Viewer", "VIEW_IN_ORDINALS_EXPLORER": "Open in Ordinal Viewer", "RARE_SATS_BUNDLE_DESCRIPTION": "This inscription belongs to the same bundle as other assets.", - "RARE_SATS_BUNDLE_LINK": "See bundle" + "RARE_SATS_BUNDLE_LINK": "See bundle", + "COLLECTION": "Collection", + "COLLECTION_FLOOR_PRICE": "Collection floor price", + "EST_ITEM_VALUE": "Est. item value", + "SAT": "Sat", + "NFT_TYPE": "Asset Type", + "DATA": "Data", + "COPIED": "Sharing Link Copied" }, "RESET_WALLET_SCREEN": { "ENTER_PASSWORD": "Enter your password to reset your wallet", @@ -1081,5 +1095,12 @@ "BUNDLE_PENDING_SEND_DESCRIPTION": "This bundle is already in a pending transfer.", "RARE_SAT": "Rare Sat", "INSCRIBED_SAT": "Inscribed Sat" + }, + "ORDINALS_COLLECTION_SCREEN": { + "BACK_TO_GALLERY": "Back to gallery", + "COLLECTION_FLOOR_PRICE": "Collection floor price", + "EST_PORTFOLIO_VALUE": "Est. portfolio value", + "COLLECTION": "Collection", + "LOAD_MORE": "Load more" } } diff --git a/src/pages/Options/index.css b/src/pages/Options/index.css index b7590e5fe..3e7675c0d 100644 --- a/src/pages/Options/index.css +++ b/src/pages/Options/index.css @@ -37,3 +37,9 @@ header h2 { .optionsContainer { height: 600px !important; } + +:focus-within, +:focus-visible, +:focus { + outline: none; +} diff --git a/src/pages/Popup/index.css b/src/pages/Popup/index.css index a0d902281..a67cb26a8 100644 --- a/src/pages/Popup/index.css +++ b/src/pages/Popup/index.css @@ -13,6 +13,7 @@ body { justify-content: center; align-items: center; } + #app { width: 360px; height: 600px; @@ -21,3 +22,9 @@ body { ::-webkit-scrollbar { display: none; } + +:focus-within, +:focus-visible, +:focus { + outline: none; +} diff --git a/src/theme/index.ts b/src/theme/index.ts index eea920b66..10cd318c9 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -1,10 +1,29 @@ -const Theme = { - breakpoints: { - s: '0px', - md: '700px', - lg: '1025px', - xlg: '1536px', +export const breakpoints = { + xs: '360', + s: '480', + md: '768', + lg: '920', + xl: '1200', +}; + +export const devices = { + min: { + xs: `(min-width: ${breakpoints.xs}px)`, + s: `(min-width: ${breakpoints.s}px)`, + md: `(min-width: ${breakpoints.md}px)`, + lg: `(min-width: ${breakpoints.lg}px)`, + xl: `(min-width: ${breakpoints.xl}px)`, }, + max: { + xs: `(max-width: ${breakpoints.xs}px)`, + s: `(max-width: ${breakpoints.s}px)`, + md: `(max-width: ${breakpoints.md}px)`, + lg: `(max-width: ${breakpoints.lg}px)`, + xl: `(max-width: ${breakpoints.xl}px)`, + }, +}; + +const Theme = { spacing: (multiple: number) => multiple * 2, space: { xxxs: '2px', @@ -351,4 +370,8 @@ const Theme = { }, /* above: deprecated */ }; + +export type Color = keyof typeof Theme.colors | 'currentColor'; +export type Typography = keyof typeof Theme.typography; + export default Theme; From c5f6a897409c9cb3f673531b18c7e42567d62675 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Thu, 16 Nov 2023 16:25:42 +0800 Subject: [PATCH 07/28] Release/0.21.0 (#49) --- package-lock.json | 4 +- package.json | 2 +- .../collectibleDetailTile/index.tsx | 15 +++- .../components/rareSatAsset/rareSatAsset.tsx | 2 + .../tilesSkeletonLoader.tsx | 31 +++++-- .../transactions/btcTransaction.tsx | 11 +-- .../transactions/transactionAmount.tsx | 19 +++- .../transactions/transactionRecipient.tsx | 16 +++- .../transactions/transactionStatusIcon.tsx | 29 ++++-- .../transactions/transactionTitle.tsx | 21 ++++- .../useAddressInscriptionCollections.ts | 10 --- .../ordinals/useAddressInscriptions.ts | 11 --- src/app/hooks/queries/useTransactions.ts | 44 ++++----- src/app/screens/coinDashboard/index.tsx | 24 ++--- .../coinDashboard/transactionsHistoryList.tsx | 47 ++++++---- .../screens/nftDashboard/collectiblesTabs.tsx | 90 ++++++++++--------- src/app/screens/nftDashboard/index.tsx | 49 ++-------- src/app/screens/nftDashboard/nftImage.tsx | 26 ++++-- src/app/screens/nftDetail/index.tsx | 2 +- src/app/screens/ordinalDetail/index.tsx | 58 ++++++++++-- .../screens/ordinalDetail/useOrdinalDetail.ts | 19 +++- src/app/screens/ordinals/ordinalImage.tsx | 37 +++++--- src/app/screens/ordinalsCollection/index.tsx | 57 ++++++------ src/app/utils/inscriptions.ts | 4 +- src/app/utils/transactions/transactions.ts | 29 +++++- src/locales/en.json | 6 +- 26 files changed, 409 insertions(+), 254 deletions(-) rename src/app/{screens/nftDashboard => components}/tilesSkeletonLoader.tsx (51%) diff --git a/package-lock.json b/package-lock.json index b34b45a3b..87820a7dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "xverse-web-extension", - "version": "0.20.0", + "version": "0.21.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xverse-web-extension", - "version": "0.20.0", + "version": "0.21.0", "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", diff --git a/package.json b/package.json index 4be7b10bd..cf9d28fcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xverse-web-extension", "description": "A Bitcoin wallet for Web3", - "version": "0.20.0", + "version": "0.21.0", "private": true, "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", diff --git a/src/app/components/collectibleDetailTile/index.tsx b/src/app/components/collectibleDetailTile/index.tsx index 36af9cd06..7ef735d22 100644 --- a/src/app/components/collectibleDetailTile/index.tsx +++ b/src/app/components/collectibleDetailTile/index.tsx @@ -29,8 +29,8 @@ interface ContainerProps { const Container = styled.div((props) => ({ display: 'flex', flexDirection: props.isColumnAlignment ? 'column' : 'row', - justifyContent: 'space-between', width: '100%', + justifyContent: 'space-between', })); const ValueContainer = styled.h1((props) => ({ @@ -38,9 +38,14 @@ const ValueContainer = styled.h1((props) => ({ marginBottom: props.isGallery ? props.theme.spacing(6) : props.theme.spacing(8), })); +const LoaderContainer = styled.div((props) => ({ + display: 'flex', + justifyContent: props.isGallery ? 'flex-end' : 'flex-start', +})); + const StyledBarLoader = styled(BetterBarLoader)` padding: 0; - border-radius: 6px; + border-radius: 8px; `; interface Props { @@ -66,7 +71,11 @@ function CollectibleDetailTile({ {title} - {isLoading && } + {isLoading && ( + + + + )} {!isLoading && allowThousandSeperator && ( ((props) => ({ diff --git a/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx b/src/app/components/tilesSkeletonLoader.tsx similarity index 51% rename from src/app/screens/nftDashboard/tilesSkeletonLoader.tsx rename to src/app/components/tilesSkeletonLoader.tsx index e514977cb..1252ced0d 100644 --- a/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx +++ b/src/app/components/tilesSkeletonLoader.tsx @@ -1,10 +1,14 @@ import { BetterBarLoader } from '@components/barLoader'; import styled from 'styled-components'; -const TilesLoaderContainer = styled.div({ +const TilesLoaderContainer = styled.div<{ + isGalleryOpen?: boolean; +}>((props) => ({ + width: '100%', display: 'flex', - justifyContent: 'space-between', -}); + justifyContent: 'flex-start', + columnGap: props.isGalleryOpen ? props.theme.spacing(16) : props.theme.spacing(12), +})); const TileLoaderContainer = styled.div({ display: 'flex', @@ -13,27 +17,40 @@ const TileLoaderContainer = styled.div({ export const StyledBarLoader = styled(BetterBarLoader)<{ withMarginBottom?: boolean; + isGalleryOpen?: boolean; }>((props) => ({ padding: 0, - borderRadius: 6, + borderRadius: props.theme.radius(props.isGalleryOpen ? 3 : 1), marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, })); export function TilesSkeletonLoader({ className, tileSize = 151, + isGalleryOpen, }: { className?: string; tileSize?: number; + isGalleryOpen?: boolean; }) { return ( - + - + - + diff --git a/src/app/components/transactions/btcTransaction.tsx b/src/app/components/transactions/btcTransaction.tsx index e9f33a75f..c4e835d88 100644 --- a/src/app/components/transactions/btcTransaction.tsx +++ b/src/app/components/transactions/btcTransaction.tsx @@ -1,6 +1,7 @@ import useWalletSelector from '@hooks/useWalletSelector'; -import { BtcTransactionData } from '@secretkeylabs/xverse-core'; +import { Brc20HistoryTransactionData, BtcTransactionData } from '@secretkeylabs/xverse-core'; import { getBtcTxStatusUrl } from '@utils/helper'; +import { isBtcTransaction } from '@utils/transactions/transactions'; import { useCallback } from 'react'; import styled from 'styled-components'; import TransactionAmount from './transactionAmount'; @@ -9,7 +10,7 @@ import TransactionStatusIcon from './transactionStatusIcon'; import TransactionTitle from './transactionTitle'; interface TransactionHistoryItemProps { - transaction: BtcTransactionData; + transaction: BtcTransactionData | Brc20HistoryTransactionData; } const TransactionContainer = styled.button((props) => ({ @@ -52,19 +53,19 @@ const TransactionRow = styled.div((props) => ({ export default function BtcTransactionHistoryItem(props: TransactionHistoryItemProps) { const { transaction } = props; const { network } = useWalletSelector(); - + const isBtc = isBtcTransaction(transaction) ? 'BTC' : 'brc20'; const openBtcTxStatusLink = useCallback(() => { window.open(getBtcTxStatusUrl(transaction.txid, network), '_blank', 'noopener,noreferrer'); }, []); return ( - + - + diff --git a/src/app/components/transactions/transactionAmount.tsx b/src/app/components/transactions/transactionAmount.tsx index 2a5726299..c9dc2338f 100644 --- a/src/app/components/transactions/transactionAmount.tsx +++ b/src/app/components/transactions/transactionAmount.tsx @@ -1,5 +1,6 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { + Brc20HistoryTransactionData, BtcTransactionData, FungibleToken, microstacksToStx, @@ -13,7 +14,7 @@ import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; interface TransactionAmountProps { - transaction: StxTransactionData | BtcTransactionData; + transaction: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData; coin: CurrencyTypes; } @@ -78,6 +79,22 @@ export default function TransactionAmount(props: TransactionAmountProps): JSX.El /> ); } + } else if (coin === 'brc20') { + const brc20Transaction = transaction as Brc20HistoryTransactionData; + const prefix = brc20Transaction.incoming ? '' : '-'; + if (!new BigNumber(brc20Transaction.amount).isEqualTo(0)) { + return ( + ( + {`${prefix}${value} ${brc20Transaction.ticker.toUpperCase()}`} + )} + /> + ); + } } return null; } diff --git a/src/app/components/transactions/transactionRecipient.tsx b/src/app/components/transactions/transactionRecipient.tsx index a909f0792..d3af568db 100644 --- a/src/app/components/transactions/transactionRecipient.tsx +++ b/src/app/components/transactions/transactionRecipient.tsx @@ -1,4 +1,9 @@ -import { BtcTransactionData, StxTransactionData } from '@secretkeylabs/xverse-core'; +import { + Brc20HistoryTransactionData, + BtcTransactionData, + StxTransactionData, +} from '@secretkeylabs/xverse-core'; +import { isBrc20Transaction } from '@utils/transactions/transactions'; import styled from 'styled-components'; const RecipientAddress = styled.p((props) => ({ @@ -8,10 +13,12 @@ const RecipientAddress = styled.p((props) => ({ })); interface TransactionRecipientProps { - transaction: StxTransactionData | BtcTransactionData; + transaction: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData; } -function isBtcTransaction(tx: StxTransactionData | BtcTransactionData): tx is BtcTransactionData { +function isBtcTransaction( + tx: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData, +): tx is BtcTransactionData { return (tx as BtcTransactionData).txType === 'bitcoin'; } @@ -24,6 +31,9 @@ export default function TransactionRecipient(props: TransactionRecipientProps): if (isBtcTransaction(transaction)) { return {formatAddress(transaction.recipientAddress ?? '')}; } + if (isBrc20Transaction(transaction)) { + return {formatAddress(transaction.to ?? '')}; + } if (transaction.txType === 'token_transfer' || transaction.txType === 'coinbase') { return ( diff --git a/src/app/components/transactions/transactionStatusIcon.tsx b/src/app/components/transactions/transactionStatusIcon.tsx index c8834e2ad..b32eaa863 100644 --- a/src/app/components/transactions/transactionStatusIcon.tsx +++ b/src/app/components/transactions/transactionStatusIcon.tsx @@ -1,14 +1,18 @@ -import { BtcTransactionData, StxTransactionData } from '@secretkeylabs/xverse-core'; -import { CurrencyTypes } from '@utils/constants'; -import ReceiveIcon from '@assets/img/transactions/received.svg'; -import SendIcon from '@assets/img/transactions/sent.svg'; -import PendingIcon from '@assets/img/transactions/pending.svg'; import ContractIcon from '@assets/img/transactions/contract.svg'; import FailedIcon from '@assets/img/transactions/failed.svg'; import OrdinalsIcon from '@assets/img/transactions/ordinal.svg'; +import PendingIcon from '@assets/img/transactions/pending.svg'; +import ReceiveIcon from '@assets/img/transactions/received.svg'; +import SendIcon from '@assets/img/transactions/sent.svg'; +import { + Brc20HistoryTransactionData, + BtcTransactionData, + StxTransactionData, +} from '@secretkeylabs/xverse-core'; +import { CurrencyTypes } from '@utils/constants'; interface TransactionStatusIconPros { - transaction: StxTransactionData | BtcTransactionData; + transaction: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData; currency: CurrencyTypes; } @@ -46,6 +50,19 @@ function TransactionStatusIcon(props: TransactionStatusIconPros) { } return sent; } + if (currency === 'brc20') { + const tx = transaction as Brc20HistoryTransactionData; + if (tx.txStatus === 'pending') { + return pending; + } + if (tx.incoming) { + return received; + } + if (tx.operation === 'transfer_send' && !tx.incoming) { + return sent; + } + return inscribe-transaction; + } return contract; } export default TransactionStatusIcon; diff --git a/src/app/components/transactions/transactionTitle.tsx b/src/app/components/transactions/transactionTitle.tsx index 134f1ba7b..ed277e063 100644 --- a/src/app/components/transactions/transactionTitle.tsx +++ b/src/app/components/transactions/transactionTitle.tsx @@ -1,5 +1,6 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { + Brc20HistoryTransactionData, BtcTransactionData, StxTransactionData, TransactionData, @@ -9,7 +10,7 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; interface TransactionTitleProps { - transaction: StxTransactionData | BtcTransactionData; + transaction: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData; } const TransactionTitleText = styled.p((props) => ({ @@ -30,6 +31,22 @@ export default function TransactionTitle(props: TransactionTitleProps) { return tx.incoming ? t('TRANSACTION_RECEIVED') : t('TRANSACTION_SENT'); }; + const getBrc20TokenTitle = (tx: Brc20HistoryTransactionData): string => { + if (tx.txStatus === 'pending') { + return tx.incoming ? t('TRANSACTION_PENDING_RECEIVING') : t('TRANSACTION_PENDING_SENDING'); + } + if (tx.operation === 'transfer_send') { + return tx.incoming ? t('TRANSACTION_RECEIVED') : t('TRANSACTION_SENT'); + } + if (tx.operation === 'mint') { + return t('MINT'); + } + if (tx.operation === 'transfer') { + return t('INSCRIBE_TRANSFER'); + } + return tx.operation; + }; + const getBtcTokenTransferTitle = (tx: BtcTransactionData): string => { if (tx.txStatus === 'pending') { if (tx.isOrdinal) { @@ -87,6 +104,8 @@ export default function TransactionTitle(props: TransactionTitleProps) { return t('TRANSACTION_POISON_MICRO_BLOCK'); case 'bitcoin': return getBtcTokenTransferTitle(transaction as BtcTransactionData); + case 'brc20': + return getBrc20TokenTitle(transaction as Brc20HistoryTransactionData); default: return t('TRANSACTION_STATUS_UNKNOWN'); } diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts index 45967e8bc..16084988e 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts @@ -15,16 +15,6 @@ const useAddressInscriptionCollections = () => { if (!ordinalsAddress) { throw new InvalidParamsError('ordinalsAddress is required'); } - - // TODO cui: remove mock data after QA - const testAddress = localStorage.getItem('testAddress'); - if (testAddress) { - return getCollections( - testAddress, - pageParam || 0, // offset, - PAGE_SIZE, // limit - ); - } return getCollections(ordinalsAddress, pageParam || 0, PAGE_SIZE); }; diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts index ed3eeaaa3..ca39fefa9 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts @@ -15,17 +15,6 @@ const useAddressInscriptions = (collectionId?: string) => { if (!ordinalsAddress || !collectionId) { throw new InvalidParamsError('ordinalsAddress and collectionId are required'); } - - // TODO cui: remove mock data after QA - const testAddress = localStorage.getItem('testAddress'); - if (testAddress) { - return getCollectionSpecificInscriptions( - testAddress, - collectionId, - pageParam || 0, // offset, - PAGE_SIZE, // limit - ); - } return getCollectionSpecificInscriptions( ordinalsAddress, collectionId, diff --git a/src/app/hooks/queries/useTransactions.ts b/src/app/hooks/queries/useTransactions.ts index d0ef425b6..c78999312 100644 --- a/src/app/hooks/queries/useTransactions.ts +++ b/src/app/hooks/queries/useTransactions.ts @@ -1,6 +1,6 @@ -import { BtcTransactionData } from '@secretkeylabs/xverse-core/types'; import useWalletSelector from '@hooks/useWalletSelector'; -import { fetchBtcTransactionsData } from '@secretkeylabs/xverse-core/api'; +import { fetchBtcTransactionsData, getBrc20History } from '@secretkeylabs/xverse-core/api'; +import { Brc20HistoryTransactionData, BtcTransactionData } from '@secretkeylabs/xverse-core/types'; import { AddressTransactionWithTransfers, MempoolTransaction, @@ -10,34 +10,36 @@ import { CurrencyTypes, PAGINATION_LIMIT } from '@utils/constants'; import { getStxAddressTransactions } from '@utils/transactions/transactions'; import useNetworkSelector from '../useNetwork'; -export default function useTransactions(coinType: CurrencyTypes) { +export default function useTransactions(coinType: CurrencyTypes, brc20Token: string | null) { const { network, stxAddress, btcAddress, ordinalsAddress, hasActivatedOrdinalsKey } = useWalletSelector(); const selectedNetwork = useNetworkSelector(); const fetchTransactions = async (): Promise< - BtcTransactionData[] | (AddressTransactionWithTransfers | MempoolTransaction)[] + | BtcTransactionData[] + | (AddressTransactionWithTransfers | MempoolTransaction)[] + | Brc20HistoryTransactionData[] > => { - try { - if (coinType === 'STX' || coinType === 'FT' || coinType === 'NFT') { - return await getStxAddressTransactions(stxAddress, selectedNetwork, 0, PAGINATION_LIMIT); - } - if (coinType === 'BTC') { - const btcData = await fetchBtcTransactionsData( - btcAddress, - ordinalsAddress, - network.type, - hasActivatedOrdinalsKey as boolean, - ); - return btcData; - } - return []; - } catch (err) { - return Promise.reject(err); + if (coinType === 'STX' || coinType === 'FT' || coinType === 'NFT') { + return getStxAddressTransactions(stxAddress, selectedNetwork, 0, PAGINATION_LIMIT); } + if (coinType === 'BTC') { + const btcData = await fetchBtcTransactionsData( + btcAddress, + ordinalsAddress, + network.type, + hasActivatedOrdinalsKey as boolean, + ); + return btcData; + } + if (coinType === 'brc20' && brc20Token) { + const brc20Data = await getBrc20History(ordinalsAddress, brc20Token); + return brc20Data; + } + return []; }; return useQuery({ - queryKey: [`transactions-${coinType}`], + queryKey: [`transactions-${coinType}-${brc20Token}`], queryFn: fetchTransactions, refetchInterval: 10000, }); diff --git a/src/app/screens/coinDashboard/index.tsx b/src/app/screens/coinDashboard/index.tsx index 0b38c5141..bbda2f88d 100644 --- a/src/app/screens/coinDashboard/index.tsx +++ b/src/app/screens/coinDashboard/index.tsx @@ -1,16 +1,16 @@ -import TopRow from '@components/topRow'; +import linkIcon from '@assets/img/linkIcon.svg'; +import CopyButton from '@components/copyButton'; import BottomBar from '@components/tabBar'; -import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; -import useWalletSelector from '@hooks/useWalletSelector'; +import TopRow from '@components/topRow'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; -import styled from 'styled-components'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { FungibleToken } from '@secretkeylabs/xverse-core'; import { CurrencyTypes } from '@utils/constants'; +import { getExplorerUrl } from '@utils/helper'; import { useState } from 'react'; -import linkIcon from '@assets/img/linkIcon.svg'; import { useTranslation } from 'react-i18next'; -import { getExplorerUrl } from '@utils/helper'; -import CopyButton from '@components/copyButton'; -import { FungibleToken } from '@secretkeylabs/xverse-core'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import styled from 'styled-components'; import CoinHeader from './coinHeader'; import TransactionsHistoryList from './transactionsHistoryList'; @@ -187,18 +187,12 @@ export default function CoinDashboard() { ); } - } else if (brc20FtName) { - return ( - -

{t('TRANSACTION_HISTORY_TITLE')}

-

{`${t('COMING_SOON')}!`}

-
- ); } return ( ); }; diff --git a/src/app/screens/coinDashboard/transactionsHistoryList.tsx b/src/app/screens/coinDashboard/transactionsHistoryList.tsx index c01a74ae7..e05f6eb29 100644 --- a/src/app/screens/coinDashboard/transactionsHistoryList.tsx +++ b/src/app/screens/coinDashboard/transactionsHistoryList.tsx @@ -1,25 +1,27 @@ -import styled from 'styled-components'; -import { BtcTransactionData } from '@secretkeylabs/xverse-core/types'; -import { CurrencyTypes } from '@utils/constants'; +import BtcTransactionHistoryItem from '@components/transactions/btcTransaction'; +import StxTransactionHistoryItem from '@components/transactions/stxTransaction'; import useTransactions from '@hooks/queries/useTransactions'; -import { MoonLoader } from 'react-spinners'; -import { useTranslation } from 'react-i18next'; -import { formatDate } from '@utils/date'; +import { animated, config, useSpring } from '@react-spring/web'; +import { BtcTransactionData } from '@secretkeylabs/xverse-core/types'; import { AddressTransactionWithTransfers, MempoolTransaction, PostConditionFungible, } from '@stacks/stacks-blockchain-api-types'; -import { useMemo } from 'react'; -import { animated, config, useSpring } from '@react-spring/web'; +import { CurrencyTypes } from '@utils/constants'; +import { formatDate } from '@utils/date'; import { isAddressTransactionWithTransfers, + isBrc20Transaction, + isBrc20TransactionArr, isBtcTransaction, isBtcTransactionArr, Tx, } from '@utils/transactions/transactions'; -import BtcTransactionHistoryItem from '@components/transactions/btcTransaction'; -import StxTransactionHistoryItem from '@components/transactions/stxTransaction'; +import { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { MoonLoader } from 'react-spinners'; +import styled from 'styled-components'; const ListItemsContainer = styled.div({ display: 'flex', @@ -79,6 +81,7 @@ const SectionTitle = styled.p((props) => ({ interface TransactionsHistoryListProps { coin: CurrencyTypes; txFilter: string | null; + brc20Token: string | null; } const sortTransactionsByBlockHeight = (transactions: BtcTransactionData[]) => @@ -159,8 +162,11 @@ const filterTxs = ( }); export default function TransactionsHistoryList(props: TransactionsHistoryListProps) { - const { coin, txFilter } = props; - const { data, isLoading, isFetching } = useTransactions((coin as CurrencyTypes) || 'STX'); + const { coin, txFilter, brc20Token } = props; + const { data, isLoading, isFetching, error } = useTransactions( + (coin as CurrencyTypes) || 'STX', + brc20Token, + ); const styles = useSpring({ config: { ...config.stiff }, from: { opacity: 0 }, @@ -168,6 +174,7 @@ export default function TransactionsHistoryList(props: TransactionsHistoryListPr opacity: 1, }, }); + const { t } = useTranslation('translation', { keyPrefix: 'COIN_DASHBOARD_SCREEN' }); const groupedTxs = useMemo(() => { @@ -175,16 +182,19 @@ export default function TransactionsHistoryList(props: TransactionsHistoryListPr return; } - if (isBtcTransactionArr(data)) { + if (isBtcTransactionArr(data) || isBrc20TransactionArr(data)) { return groupBtcTxsByDate(data); } if (txFilter && coin === 'FT') { - const filteredTxs = filterTxs(data, txFilter); + const filteredTxs = filterTxs( + data as (AddressTransactionWithTransfers | MempoolTransaction)[], + txFilter, + ); return groupedTxsByDateMap(filteredTxs); } - return groupedTxsByDateMap(data); + return groupedTxsByDateMap(data as (AddressTransactionWithTransfers | MempoolTransaction)[]); }, [data, isLoading, isFetching]); return ( @@ -199,7 +209,7 @@ export default function TransactionsHistoryList(props: TransactionsHistoryListPr {groupedTxs[group].map((transaction) => { - if (isBtcTransaction(transaction)) { + if (isBtcTransaction(transaction) || isBrc20Transaction(transaction)) { return ( ); @@ -220,7 +230,10 @@ export default function TransactionsHistoryList(props: TransactionsHistoryListPr )} - {!isLoading && data?.length === 0 && ( + {!isLoading && error && ( + {t('TRANSACTIONS_LIST_ERROR')} + )} + {!isLoading && data?.length === 0 && !error && ( {t('TRANSACTIONS_LIST_EMPTY')} )} diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx index 3d81ae1c6..bc9b56d33 100644 --- a/src/app/screens/nftDashboard/collectiblesTabs.tsx +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -1,13 +1,14 @@ +import ActionButton from '@components/button'; import WrenchErrorMessage from '@components/wrenchErrorMessage'; import { StyledP, StyledTab, StyledTabList } from '@ui-library/common.styled'; import { ApiBundle, Bundle, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useSearchParams } from 'react-router-dom'; -import { MoonLoader } from 'react-spinners'; import { TabPanel, Tabs } from 'react-tabs'; import styled from 'styled-components'; import type { NftDashboardState } from '.'; +import { StyledBarLoader, TilesSkeletonLoader } from '../../components/tilesSkeletonLoader'; import Notice from './notice'; import RareSatsTabGridItem from './rareSatsTabGridItem'; @@ -51,26 +52,32 @@ const LoadMoreButtonContainer = styled.div((props) => ({ alignItems: 'center', marginBottom: props.theme.spacing(30), marginTop: props.theme.space.xl, + button: { + width: 156, + }, })); -const LoadMoreButton = styled.button((props) => ({ - ...props.theme.body_medium_l, - fontSize: 13, - width: 98, - height: 34, - color: props.theme.colors.white['0'], - border: `1px solid ${props.theme.colors.background.elevation3}`, - background: props.theme.colors.background.elevation0, - borderRadius: 24, - padding: '8px, 16px, 8px, 16px', - ':hover': { - background: props.theme.colors.background.elevation9, - }, - ':focus': { - background: props.theme.colors.background.elevation10, - }, +const LoaderContainer = styled.div({ + display: 'flex', + flexDirection: 'column', +}); + +const CountLoaderContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(6), + marginBottom: props.theme.spacing(12), })); +function SkeletonLoader({ isGalleryOpen }: { isGalleryOpen: boolean }) { + return ( + + + + + + + ); +} + const tabs: { key: string; label: string; @@ -99,13 +106,11 @@ export default function CollectiblesTabs({ nftListView, inscriptionListView, nftDashboard, - loader, }: { className?: string; nftListView: React.ReactNode; inscriptionListView: React.ReactNode; nftDashboard: NftDashboardState; - loader: React.ReactNode; }) { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); const navigate = useNavigate(); @@ -148,7 +153,7 @@ export default function CollectiblesTabs({ )} {isLoadingOrdinalCollections ? ( - loader + ) : ( <> {totalInscriptions > 0 && ( @@ -162,7 +167,7 @@ export default function CollectiblesTabs({ {isLoading ? ( - loader + ) : ( <> {totalNfts > 0 && ( @@ -175,13 +180,13 @@ export default function CollectiblesTabs({ )} - {ordinalBundleCount > 0 && ( + {!rareSatsQuery.isLoading && ordinalBundleCount > 0 && ( {t('TOTAL_ITEMS', { total: ordinalBundleCount })} )} - {showNoticeAlert && ( + {!rareSatsQuery.isLoading && showNoticeAlert && ( {t('NO_COLLECTIBLES')}} {!!rareSatsQuery.error && } - {rareSatsQuery.isLoading && loader} - - {hasActivatedOrdinalsKey && - !rareSatsQuery.error && - !rareSatsQuery.isLoading && - rareSatsQuery.data?.pages - ?.map((page) => page?.results) - .flat() - .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) - .map((bundle: Bundle) => )} - + {rareSatsQuery.isLoading ? ( + + ) : ( + + {hasActivatedOrdinalsKey && + !rareSatsQuery.error && + !rareSatsQuery.isLoading && + rareSatsQuery.data?.pages + ?.map((page) => page?.results) + .flat() + .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) + .map((bundle: Bundle) => )} + + )} {rareSatsQuery.hasNextPage && ( - {rareSatsQuery.isFetchingNextPage ? ( - - ) : ( - - {t('LOAD_MORE')} - - )} + )} diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index 3c9a0b0ad..3e432d575 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -27,7 +27,6 @@ import CollectiblesTabs, { GridContainer } from './collectiblesTabs'; import { InscriptionsTabGridItem } from './inscriptionsTabGridItem'; import Nft from './nft'; import ReceiveNftModal from './receiveNft'; -import { StyledBarLoader, TilesSkeletonLoader } from './tilesSkeletonLoader'; const Container = styled.div` display: flex; @@ -74,11 +73,6 @@ const CollectibleContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(12), })); -const LoaderContainer = styled.div({ - display: 'flex', - flexDirection: 'column', -}); - const ButtonContainer = styled.div({ display: 'flex', position: 'relative', @@ -92,24 +86,6 @@ const ReceiveButtonContainer = styled.div(() => ({ width: '100%', })); -const LoadMoreButton = styled.button((props) => ({ - ...props.theme.body_medium_l, - fontSize: 13, - width: 98, - height: 34, - color: props.theme.colors.white['0'], - border: `1px solid ${props.theme.colors.background.elevation3}`, - background: props.theme.colors.background.elevation0, - borderRadius: 24, - padding: '8px, 16px, 8px, 16px', - ':hover': { - background: props.theme.colors.background.elevation9, - }, - ':focus': { - background: props.theme.colors.background.elevation10, - }, -})); - const NoCollectiblesText = styled.h1((props) => ({ ...props.theme.body_bold_m, color: props.theme.colors.white['200'], @@ -137,11 +113,6 @@ const ErrorText = styled.div((props) => ({ color: props.theme.colors.white['200'], })); -const CountLoaderContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(6), - marginBottom: props.theme.spacing(12), -})); - const LoadMoreButtonContainer = styled.div((props) => ({ display: 'flex', justifyContent: 'center', @@ -353,11 +324,13 @@ const useNftDashboard = (): NftDashboardState => { {hasNextPage && ( - {isFetchingNextPage ? ( - - ) : ( - {t('LOAD_MORE')} - )} + )} @@ -497,14 +470,6 @@ function NftDashboard() { nftListView={} inscriptionListView={} nftDashboard={nftDashboard} - loader={ - - - - - - - } />
diff --git a/src/app/screens/nftDashboard/nftImage.tsx b/src/app/screens/nftDashboard/nftImage.tsx index 4016b6f26..553581172 100644 --- a/src/app/screens/nftDashboard/nftImage.tsx +++ b/src/app/screens/nftDashboard/nftImage.tsx @@ -1,10 +1,11 @@ -import { Suspense } from 'react'; -import styled from 'styled-components'; -import { MoonLoader } from 'react-spinners'; -import Image from 'rc-image'; +import NftPlaceholderImage from '@assets/img/nftDashboard/ic_nft_diamond.svg'; +import { BetterBarLoader } from '@components/barLoader'; import { TokenMetaData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; import { getFetchableUrl } from '@utils/helper'; -import NftPlaceholderImage from '@assets/img/nftDashboard/ic_nft_diamond.svg'; +import Image from 'rc-image'; +import { Suspense } from 'react'; +import { MoonLoader } from 'react-spinners'; +import styled from 'styled-components'; interface ContainerProps { isGalleryOpen: boolean; @@ -22,7 +23,7 @@ const ImageContainer = styled.div((props) => ({ aspectRatio: '1', })); -const LoaderContainer = styled.div((props) => ({ +const LoaderContainer = styled.div({ display: 'flex', justifyContent: 'center', alignItems: 'center', @@ -32,7 +33,11 @@ const LoaderContainer = styled.div((props) => ({ bottom: 0, right: 0, top: 0, - height: props.isGalleryOpen ? '100%' : 150, +}); + +const StyledBarLoader = styled(BetterBarLoader)((props) => ({ + padding: 0, + borderRadius: props.theme.radius(1), })); const Video = styled.video({ @@ -62,8 +67,11 @@ function NftImage({ metadata }: Props) { preview={false} src={getFetchableUrl(metadata.image_url ?? '', metadata.image_protocol ?? '')} placeholder={ - - + + } fallback={NftPlaceholderImage} diff --git a/src/app/screens/nftDetail/index.tsx b/src/app/screens/nftDetail/index.tsx index 0285ca758..9afbbc16d 100644 --- a/src/app/screens/nftDetail/index.tsx +++ b/src/app/screens/nftDetail/index.tsx @@ -289,7 +289,7 @@ function NftDetailScreen() { }, [nftDetailsData]); const handleBackButtonClick = () => { - navigate('/nft-dashboard'); + navigate('/nft-dashboard?tab=nfts'); }; const onSharePress = () => { diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index 1cd7c6871..f4cbc3925 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -89,7 +89,7 @@ const ExtensionOrdinalsContainer = styled.div((props) => ({ aspectRatio: '1', justifyContent: 'center', alignItems: 'center', - borderRadius: 8, + borderRadius: props.theme.radius(1), marginBottom: props.theme.spacing(12), marginTop: props.theme.spacing(12), })); @@ -127,12 +127,15 @@ const BottomBarContainer = styled.div({ marginTop: 'auto', }); -const RowContainer = styled.div((props) => ({ +const RowContainer = styled.div<{ + withGap?: boolean; +}>((props) => ({ display: 'flex', alignItems: 'flex-start', marginTop: props.theme.spacing(8), marginBottom: props.theme.spacing(12), flexDirection: 'row', + columnGap: props.withGap ? props.theme.spacing(20) : 0, })); const ColumnContainer = styled.div({ @@ -163,7 +166,6 @@ const MintLimitContainer = styled.div((props) => ({ const DescriptionContainer = styled.h1((props) => ({ display: 'flex', - marginLeft: props.theme.spacing(20), flexDirection: 'column', marginBottom: props.theme.spacing(30), })); @@ -349,11 +351,16 @@ const ExtensionLoaderContainer = styled.div({ alignItems: 'center', }); +const GalleryLoaderContainer = styled.div({ + display: 'flex', + flexDirection: 'column', +}); + const StyledBarLoader = styled(BetterBarLoader)<{ withMarginBottom?: boolean; }>((props) => ({ padding: 0, - borderRadius: 6, + borderRadius: props.theme.radius(1), marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, })); @@ -409,6 +416,7 @@ function OrdinalDetailScreen() { openInOrdinalsExplorer, handleNavigationToRareSatsBundle, onCopyClick, + backButtonText, } = ordinalDetails; useResetUserFlow('/ordinal-detail'); @@ -436,7 +444,7 @@ function OrdinalDetailScreen() { @@ -668,19 +676,53 @@ function OrdinalDetailScreen() { ); - const galleryView = ( + const galleryView = isLoading ? ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) : ( - + diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts index 5b6c4d4eb..ee74d30f3 100644 --- a/src/app/screens/ordinalDetail/useOrdinalDetail.ts +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -14,11 +14,14 @@ import { getInscriptionsCollectionGridItemSubTextColor, } from '@utils/inscriptions'; import { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate, useParams } from 'react-router-dom'; +import { useTheme } from 'styled-components'; export default function useOrdinalDetail() { const navigate = useNavigate(); - const { ordinalsAddress, network, selectedAccount } = useWalletSelector(); + const { ordinalsAddress, network, selectedAccount, hasActivatedRareSatsKey } = + useWalletSelector(); const { id } = useParams(); const { selectedOrdinal } = useNftDataSelector(); const { data: ordinalData, isLoading } = useAddressInscription(id!, selectedOrdinal); @@ -29,19 +32,22 @@ export default function useOrdinalDetail() { const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); const { isPending, pendingTxHash } = usePendingOrdinalTxs(ordinalData?.tx_id); const textContent = useTextOrdinalContent(ordinalData!); - const { hasActivatedRareSatsKey } = useWalletSelector(); const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); const { bundle, isPartOfABundle } = useGetUtxoOrdinalBundle( ordinalData?.output, hasActivatedRareSatsKey, ); + const theme = useTheme(); + const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); const [isBrc20Ordinal, setIsBrc20Ordinal] = useState(false); const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + const brc20InscriptionStatus = getInscriptionsCollectionGridItemSubText(ordinalData); - const brc20InscriptionStatusColor = getInscriptionsCollectionGridItemSubTextColor(ordinalData); + const brc20InscriptionStatusColor = + theme.colors[getInscriptionsCollectionGridItemSubTextColor(ordinalData)]; useEffect(() => { if (textContent?.includes('brc-20')) { @@ -53,7 +59,7 @@ export default function useOrdinalDetail() { setSelectedOrdinalDetails(null); if (ordinalData?.collection_id) navigate(`/nft-dashboard/ordinals-collection/${ordinalData?.collection_id}`); - else navigate('/nft-dashboard'); + else navigate('/nft-dashboard?tab=inscriptions'); }; const openInGalleryView = async () => { @@ -109,6 +115,10 @@ export default function useOrdinalDetail() { navigator.clipboard.writeText(`${XVERSE_ORDIVIEW_URL}/inscription/${ordinalData?.id}`); }; + const backButtonText = ordinalData?.collection_id + ? t('BACK_TO_COLLECTION') + : t('MOVE_TO_ASSET_DETAIL'); + return { ordinal: ordinalData, collectionMarketData, @@ -129,5 +139,6 @@ export default function useOrdinalDetail() { openInOrdinalsExplorer, handleNavigationToRareSatsBundle, onCopyClick, + backButtonText, }; } diff --git a/src/app/screens/ordinals/ordinalImage.tsx b/src/app/screens/ordinals/ordinalImage.tsx index 2bdb38434..71eb65eab 100644 --- a/src/app/screens/ordinals/ordinalImage.tsx +++ b/src/app/screens/ordinals/ordinalImage.tsx @@ -29,7 +29,7 @@ const ImageContainer = styled.div((props) => ({ fontSize: '3em', wordWrap: 'break-word', backgroundColor: props.theme.colors.elevation1, - borderRadius: 8, + borderRadius: props.theme.radius(1), '> img': { width: '100%', }, @@ -69,6 +69,18 @@ const Text = styled.h1((props) => ({ marginLeft: props.theme.spacing(4), })); +const LoaderContainer = styled.div({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + position: 'absolute', + width: '100%', + left: 0, + bottom: 0, + right: 0, + top: 0, +}); + interface TextProps { inNftSend?: boolean; isSmall?: boolean; @@ -105,12 +117,10 @@ const StyledImage = styled(Image)` image-rendering: pixelated; `; -export const StyledBarLoader = styled(BetterBarLoader)<{ - withMarginBottom?: boolean; -}>((props) => ({ +export const StyledBarLoader = styled(BetterBarLoader)((props) => ({ padding: 0, - borderRadius: 6, - marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, + borderRadius: props.theme.radius(1), + marginBottom: 0, })); interface Props { @@ -166,12 +176,21 @@ function OrdinalImage({ } }, [textContent]); + let loaderSize = 151; + if (inNftDetail && isGalleryOpen) { + loaderSize = 376.5; + } else if (isGalleryOpen) { + loaderSize = 276; + } + const renderImage = (tag: string, src?: string) => ( + + + } src={src} /> @@ -221,9 +240,7 @@ function OrdinalImage({ if (contentType.includes('text')) { if (!textContent) { - return ( - - ); + return ; } if (contentType.includes('html')) { diff --git a/src/app/screens/ordinalsCollection/index.tsx b/src/app/screens/ordinalsCollection/index.tsx index 0c8a032be..70017292e 100644 --- a/src/app/screens/ordinalsCollection/index.tsx +++ b/src/app/screens/ordinalsCollection/index.tsx @@ -1,8 +1,10 @@ import AccountHeaderComponent from '@components/accountHeader'; +import { BetterBarLoader } from '@components/barLoader'; import ActionButton from '@components/button'; import CollectibleDetailTile from '@components/collectibleDetailTile'; import Separator from '@components/separator'; import BottomTabBar from '@components/tabBar'; +import { TilesSkeletonLoader } from '@components/tilesSkeletonLoader'; import TopRow from '@components/topRow'; import WebGalleryButton from '@components/webGalleryButton'; import WrenchErrorMessage from '@components/wrenchErrorMessage'; @@ -11,7 +13,6 @@ import useInscriptionCollectionMarketData from '@hooks/queries/ordinals/useColle import { useResetUserFlow } from '@hooks/useResetUserFlow'; import { ArrowLeft } from '@phosphor-icons/react'; import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; -import { TilesSkeletonLoader } from '@screens/nftDashboard/tilesSkeletonLoader'; import { StyledHeading, StyledP } from '@ui-library/common.styled'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -35,7 +36,7 @@ const Container = styled.div` `; const PageHeader = styled.div` - padding: ${(props) => props.theme.space.s}; + padding: ${(props) => props.theme.space.xs}; padding-top: 0; max-width: 1224px; margin-top: ${(props) => (props.isGalleryOpen ? props.theme.space.xxl : props.theme.space.l)}; @@ -57,7 +58,6 @@ const AttributesContainer = styled.div` flex-direction: ${(props) => (props.isGalleryOpen ? 'column' : 'row')}; justify-content: ${(props) => (props.isGalleryOpen ? 'space-between' : 'initial')}; column-gap: ${(props) => props.theme.space.m}; - max-width: 285px; `; const BottomBarContainer = styled.div({ @@ -70,7 +70,7 @@ const StyledSeparator = styled(Separator)` const StyledGridContainer = styled(GridContainer)` margin-top: ${(props) => props.theme.space.s}; - padding: 0 ${(props) => props.theme.space.s}; + padding: 0 ${(props) => props.theme.space.xs}; padding-bottom: ${(props) => props.theme.space.xl}; max-width: 1224px; margin-left: auto; @@ -122,25 +122,20 @@ const LoadMoreButtonContainer = styled.div((props) => ({ }, })); -const LoaderContainer = styled.div((props) => ({ - width: '100%', - display: 'flex', - justifyContent: 'space-between', - paddingLeft: props.theme.spacing(6), - paddingRight: props.theme.spacing(6), +const StyledBarLoader = styled(BetterBarLoader)((props) => ({ + padding: 0, + borderRadius: props.theme.radius(1), + marginTop: props.theme.spacing(2), })); -const StyledTilesSkeletonLoader = styled(TilesSkeletonLoader)` - width: 100%; -`; - function OrdinalsCollection() { const { t } = useTranslation('translation', { keyPrefix: 'ORDINALS_COLLECTION_SCREEN' }); const navigate = useNavigate(); const { id: collectionId } = useParams(); const { data, error, isLoading, hasNextPage, isFetchingNextPage, fetchNextPage } = useAddressInscriptions(collectionId); - const { data: collectionMarketData } = useInscriptionCollectionMarketData(collectionId); + const { data: collectionMarketData, isLoading: isLoadingMarketData } = + useInscriptionCollectionMarketData(collectionId); const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); @@ -161,10 +156,10 @@ function OrdinalsCollection() { const collectionHeading = data?.pages?.[0].collection_name; const estPortfolioValue = data && data?.pages?.[0].portfolio_value !== 0 - ? `${data?.pages?.[0].portfolio_value.toFixed(10)} BTC` + ? `${data?.pages?.[0].portfolio_value.toFixed(8)} BTC` : '--'; const collectionFloorPrice = collectionMarketData?.floor_price - ? `${collectionMarketData?.floor_price?.toFixed(10).toString()} BTC` + ? `${collectionMarketData?.floor_price?.toFixed(8)} BTC` : '--'; return ( @@ -192,7 +187,7 @@ function OrdinalsCollection() { {t('COLLECTION')} - {collectionHeading} + {collectionHeading || } {!isGalleryOpen && } @@ -201,7 +196,7 @@ function OrdinalsCollection() { title={t('COLLECTION_FLOOR_PRICE')} value={collectionFloorPrice} isColumnAlignment={isGalleryOpen} - isLoading={isLoading} + isLoading={isLoadingMarketData} /> {isGalleryOpen && }
- {isLoading && ( - - - - )} {isEmpty && {t('NO_COLLECTIBLES')}} {!!error && } - {data?.pages - ?.map((page) => page?.data) - .flat() - .map((inscription) => ( - - ))} + {isLoading ? ( + + ) : ( + data?.pages + ?.map((page) => page?.data) + .flat() + .map((inscription) => ( + + )) + )} {hasNextPage && ( diff --git a/src/app/utils/inscriptions.ts b/src/app/utils/inscriptions.ts index 27a8dc6b8..2afc4b87c 100644 --- a/src/app/utils/inscriptions.ts +++ b/src/app/utils/inscriptions.ts @@ -22,7 +22,7 @@ export const getInscriptionsCollectionGridItemId = (inscription?: Inscription): export const getInscriptionsCollectionGridItemSubText = (inscription?: Inscription): string => { if (inscription?.category === 'brc-20') { - return isBrcTransferValid(inscription) ? 'valid' : 'used'; + return isBrcTransferValid(inscription) ? 'Valid' : 'Used'; } return ''; }; @@ -37,7 +37,7 @@ export const getInscriptionsCollectionGridItemSubTextColor = (inscription?: Insc export const getInscriptionsTabGridItemId = (collection: InscriptionCollectionsData) => (isCollection(collection) ? collection.collection_name - : collection.thumbnail_inscriptions?.[0]?.number?.toString()) ?? ''; // TODO needs to be added to API + : collection.thumbnail_inscriptions?.[0]?.number?.toString()) ?? ''; export const getInscriptionsTabGridItemSubText = (collection: InscriptionCollectionsData) => { if (!isCollection(collection)) { diff --git a/src/app/utils/transactions/transactions.ts b/src/app/utils/transactions/transactions.ts index 9cf8de285..e12311e31 100644 --- a/src/app/utils/transactions/transactions.ts +++ b/src/app/utils/transactions/transactions.ts @@ -1,4 +1,9 @@ -import { BtcTransactionData, StacksNetwork } from '@secretkeylabs/xverse-core'; +import { + Brc20HistoryTransactionData, + BtcTransactionData, + StacksNetwork, + StxTransactionData, +} from '@secretkeylabs/xverse-core'; import { getNetworkURL } from '@secretkeylabs/xverse-core/api/helper'; import { API_TIMEOUT_MILLI } from '@secretkeylabs/xverse-core/constant'; import { @@ -88,13 +93,31 @@ export function isAddressTransactionWithTransfers( } export function isBtcTransaction( - tx: AddressTransactionWithTransfers | Tx | BtcTransactionData, + tx: AddressTransactionWithTransfers | Tx | BtcTransactionData | Brc20HistoryTransactionData, ): tx is BtcTransactionData { return (tx as BtcTransactionData).txType === 'bitcoin'; } export function isBtcTransactionArr( - txs: (AddressTransactionWithTransfers | MempoolTransaction)[] | BtcTransactionData[], + txs: + | (AddressTransactionWithTransfers | MempoolTransaction)[] + | BtcTransactionData[] + | Brc20HistoryTransactionData[], ): txs is BtcTransactionData[] { return (txs as BtcTransactionData[])[0].txType === 'bitcoin'; } + +export function isBrc20TransactionArr( + txs: + | (AddressTransactionWithTransfers | MempoolTransaction)[] + | BtcTransactionData[] + | Brc20HistoryTransactionData[], +): txs is BtcTransactionData[] { + return (txs as Brc20HistoryTransactionData[])[0].txType === 'brc20'; +} + +export function isBrc20Transaction( + tx: StxTransactionData | BtcTransactionData | Brc20HistoryTransactionData, +): tx is Brc20HistoryTransactionData { + return (tx as Brc20HistoryTransactionData).txType === 'brc20'; +} diff --git a/src/locales/en.json b/src/locales/en.json index 4042e773e..bfc91043e 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -627,6 +627,7 @@ "DETAILS": "See detail on", "GAMMA": "Gamma.io", "MOVE_TO_ASSET_DETAIL": "Back to gallery", + "BACK_TO_COLLECTION": "Back to collection", "ORDINALS": "Ordinal", "ORDINAL_PENDING_SEND_TITLE": "Transfer Pending", "ORDINAL_PENDING_SEND_DESCRIPTION": "This Ordinal is already in a pending transfer.", @@ -711,7 +712,7 @@ "CONFIRM_YOUR_NEW_PASSWORD": "Confirm your new password", "TEXT_INPUT_NEW_PASSWORD_LABEL": "New Password", "ENABLE_RARE_SATS": "Enable Rare Sats (experimental)", - "ENABLE_RARE_SATS_DETAIL": "Display Rare Sats in the collectibles and allow to scan the wallet for Rare Sats. This feature can impact performance.", + "ENABLE_RARE_SATS_DETAIL": "Automatically scan and display rare sats in your Ordinals wallet.", "ADVANCED": "Advanced" }, "OPTIONS_DIALOG": { @@ -734,8 +735,11 @@ "BUY_COIN_BUTTON": "Buy", "TRANSACTION_HISTORY_TITLE": "Transaction history", "TRANSACTIONS_LIST_EMPTY": "No transactions found.", + "TRANSACTIONS_LIST_ERROR": "Error fetching transaction history for this token", "TRANSACTION_SENT": "Sent", "TRANSACTION_RECEIVED": "Received", + "MINT": "Mint", + "INSCRIBE_TRANSFER": "Inscribe Transfer", "TRANSACTION_PENDING_RECEIVING": "Receiving", "TRANSACTION_PENDING_SENDING": "Sending", "ORDINAL_TRANSACTION_PENDING_RECEIVING": "Receiving Ordinal", From 2efe5fcb2b286be44f657372f62f7c2bff573869 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Thu, 16 Nov 2023 17:13:50 +0800 Subject: [PATCH 08/28] chore: merge upstream develop (#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and code typo (#43) * unstaged package-lock.json * fix: update all custom switch colors --------- Co-authored-by: Tim Man * fix: inscriptions grid fixes (#44) * chore: bump core version to 1.9.1 * Update function to recognise and parse brc20 tokens (#46) * Update skeleton loader logic for Collectibles UI (#45) * Update skeleton loader logic for Collectibles UI * Add a separate `TilesSkeletonLoader` component, add skeleton loader on the Collection page * Add ordinal detail page skeleton loader for the extension view * Add skeleton loader for the ordinal image component * fix: collectibles fixes from review (#47) * Fix minor ui bugs in collectible screen (#48) --------- Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> * release: v0.21.0 * Small fixes for the Collectibles UI loading state (#50) * Small fixes for the Collectibles UI * Fix loader appearance in the Collectibles tabs * Fix skeleton loader on the main Collectibles tab gallery view * Fix skeleton loader on the Collection page gallery view * Add skeleton loader for the ordinal detail page * fix: container padding on ordinals collection page * chore: remove debug lines --------- Co-authored-by: Tim Man * fix: more collectible UI fixes (#52) * chore: remove testAddress and TODOs * fix: brc20 status in ordinal details * fix: back button from nft details goes to nfts tab and back button from ordinal detail says back to collection or gallery * Minor ui fixes (#51) * sort brc20 inscription array * Fix styling * Remove unused funciton --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> * feat: revamp all colors (#588) * Tim/eng 2317 consistent dashboard buttons in extension (#618) * fix: use revamped swap svg * fix: hide swap button on testnet * Ledger send btc screen crash when going back and forward (#615) * Make `Authorize data collection` property turned on by default (#614) * Make `Authorize data collection` property turned on by default * Change the html tag and text color constant * [ENG-2961] Fix eslint errors for web extension (#617) * [ENG-2961] Fix eslint errors for web extension * [ENG-2961] Fix eslint errors for web extension * Update src/app/hooks/queries/ordinals/useInscriptionDetails.ts Co-authored-by: Victor Kirov * Update src/app/hooks/queries/useAppConfig.ts Co-authored-by: Victor Kirov --------- Co-authored-by: Victor Kirov * [ENG-3059] fix: Remove ordinal callout from send rare sats (#619) * [ENG-3059] fix: Remove ordinal callout from send rare sats * Update `amount` field validation error styling * chore: turn on tsc --noEmit precommit hook (#622) * chore: add tsc-files dev dep and run on lint staged pre commit also ran npm audit fix for a critical vuln and updated direct svg import typings * chore: use string for svg typescript declarations * chore: run eslint on repo before passing the workflow checks * feat: allow unpublished UTXOs as inputs to PSBTs (#621) * feat: allow unpublished UTXOs as inputs to PSBTs * Use correct status from response --------- Co-authored-by: Tim Man * [ENG-3039] fix: Skeleton loader for BRC-20 icons in home dashboard (#620) it can be merged, tested on ledger as well * Mahmoud/eng 2284 seedphrase vault (#510) * refactor wallet flow to use seed vault * code cleanup * update auth flow and seedphrase usage * lock dependencies and user xverse-core beta * migrate onboarding to use seed vault * use account switch method from wallet reducer hook * use seed vault for stx swaps * removed seedPhrase from wallet store * rebase fixes * small fixes * clear home screen errors * revert hashing algo change * fix swap hook * Revert "clear home screen errors" This reverts commit 55da10e60ead4c0798c40d61701b904085d6e603. * apply core changes * clear encrypted seed after successfully migrating * type fixes * update core version * onboarding guard refactor * update seed vault hook * use chromeStorage driver for session storage * updated core-lib version * refactor onboarding guard to use hasSeed * update core-lib * small fixes * update auth guard and update core version * updated csp * deprecate internal message handler * update wallet exists guard * overwrite any existing seed on restore wallet * update flow to explicitly clear vault for onboarding * update image csp * reset navigation if seed is not pre-set * update sendRareSat screen to use seed vault * add rich media csp policy * added authguard to settings screen * updated lock file * minor fixes * fresh npm install using v18 * lock with develop * adde new package updates * use fixed version of core * update to core lts version --------- Co-authored-by: Victor Kirov Co-authored-by: Tim Man * [ENG-3115] fix: UI issue in the legal screen (#624) * feat: add vout to the end of the tx id for unknown rarities (#623) * feat: add vout to the end of the tx id for unknown rarities * chore: sed replace forward slash in workflow file should replace all occurrences --------- Co-authored-by: Tim Man * Fix minor UI issues (#625) * Have thousandths separators for STX balance * Add scrollbar in message signing screen * Fix spacing in ordinal detail screen * Add loader for recover ordinal screen * fix: disabling ordinals user should not see them in the (#627) * fix: only display tab buttons when more than one tab (#629) * chore: turn on eslint rule and fix up some core internal imports (#630) * chore: turn on eslint rule and fix up some core internal imports but not all, as some are not exported yet * chore: escape . in eslint rule * chore: use a different eslint rule for this * release: v0.22.0 (#626) * fix: unable to change the network to testnet on the latest (#636) * chore: investigate npm dependabot warnings on extension (#635) * Hotfix/fix (#646) * release: v0.22.0-rc.4 to main (#642) * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * feat: add sponsor swap transaction UI and add a hook with placeholder * feat: bump xverse-core dep version and use sponsor2 url * fix: bump xverse-core version and handle sponsor transaction error * feat(Dashboard): update new action button style and add swap button * feat(Swap): add swap screen placeholder * feat(swap): add swap basic UI * feat(swap): add more UI components * feat(swap): add slippage * feat(swap): make BitCoin and Stacks option in the coin select modal * feat(swap): add token selection logic * feat: add swap data connection * feat(swap): add runSwap * chore(swap): bump alex-sdk version * fix(swap): slippage setting * feat: swap confirm layout * feat: add data bindings * fix: function name and copy address * feat: add advanced settings to the confirmation page * feat: bump alex-sdk to latest and fix the issue where from is the same as to * feat: add math.floor before converting to bigInt * fix: skip action when input is invalid * chore: update package.lock * feat(swap): update to support amm v1_1 pools * chore: fix lint warnings * fix: update swap svg stroke and add missing translation * fix: add key to fix react warnings * chore: fix lint warnings * fix: add error 700 border to swap token card * fix: update swap error message and restrict input to number * chore: prettier * style: add a not-allowed cursor to disabled buttons * fix: update translations * fix: use background elevation_1 * style: update swap details spacing * style: use unicode arrow right for swap route details * feat: implement toggle tokens button in swaps * feat: add reset slippage button to swaps * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * style: prettier * chore: update package-lock with npm i * chore: fix package-lock.json for correct xverse-core dep * chore: replace workflow dep with github api calls * chore: remove erroneous ` * Fix Edit fees popup error * Fix Edit fees popup error * Add receiving address verification for ledger accounts * Fix warning display condition on the ledger verification screen * Dont close popup on checkbox click * fix: fix for JSON serialisation of location.state * chore: use the test instance URL * chore: upgrade to alex-sdk 0.1.14 * Show wrong ledger device error * Add custom ledger account name validation * fix: turn react deps warning back on and fix stale callback * fix: move sponsor url to constants and add sponsor to swap unsigned tx * fix: display the transaction explorer link on successful sponsored tx * fix: set swap transaction fee to 0 if being sponsored * The transaction history not showing a pending send transaction that was just sent from the address * release v0.14.0 * chore: update xverse-core to published release 1.4.0 * chore: update swaps xverse sponsor 2 host * fix: remove btc from swaps coin modal. change was removed during merge * fix: remove static text describing swap route * Add Before Getting Started screen for Ledger onboarding * update copy * add links and update copy * chore: add husky and pre commit prettier to staged files * chore: run prettier --write ./src * fix: show inscription service fee fiat amount * Fix ledger account name UI issue * Show loader instead of previous transaction history data * comment out swaps button * Add localization for onboarding flow Ledger Live warning screen * chore: automatically do husky install on npm install * chore: prefer .husky for hooks * chore: run prettier again * fix: fix unsigned tx serialisation in advance settings for swaps * fix: use getNewNonce to ensure swaps transactions have correct nonce * docs: comment * bump xverse-core to v1.4.2 * fix: only show swaps button if not on a ledger account * fix: post condition info should display to/from depending on the swap * Fix regression issues v0.14.0-rc.1 * fix: ensure we are sending the correct ordinal * fix: ensure we are sending the correct ordinal * 0.14.1 * fix: remove unnecessary nested BalanceAmountText * fix: use semantic html instead of all h1 * fix: add a filter list to not display coins for swaps * Fix screen crash when changing account on /send-brc20 screen * fix: button should always be disabled when processing and show loading state in swap with await, and fix typing * Update /send-brc20 screen logic * use toString to convert value to BigNumber * chore: bump xverse-core to 1.5.0 * fix: not all tickers are all uppercase e.g. xBTC * fix: decouple alex swap from/to token list and visible token list * Fix the case when address verification screen flashes when using wrong device * Add an override switch for sponsoring transaction in swap screen * Update function param name * chore: bump core version to 1.6.0 (#560) * Allow send ordinal to self and display warning instead of error (#525) * feat: allow send ordinal to self and display warning instead of error * feat: remove send btc send to self error and use warning also adjust send ordinal warning if sending brc20 ordinal to self * Release v0.15.0 (#544) * bump version to v0.15.0 * Switch to alex sdk & url for sponsoring service Inspect error code and show sponsoring service info block feat: move alex sponsored transaction hook to new file revert: changes to useSponsoredTransaction hook for future use fix: sponsor transaction switch should toggle userOverrideSponsorValue feat: add a try again button on failed swaps due to sponsor error * feat: add warning texts to explain why a swap cannot be sponsored (#553) * fix: enforce width on swap number input (#554) * Fix swap screen fee update issue (#555) * Use correct value for fee card component * Fix fee state management * Dont show fee block when sponsored * chore: bump xverse-core to 1.5.1 to include fetchStxPendingTxData fix * Fix ui glitch on the login screen (#556) * Remove css transition code * Add hover and active state * fix: use :disabled css pseudo class instead of props on buttons --------- Co-authored-by: Tim Man * Fix swaps tx history (#557) * Use ft transfer array to show token specific history * Add filter to only show specific token history * Refactor txTransfers file to reuse code * Use token ticker * Update variable name * Use correct decimal places for fungible token (#559) * Use ftDecimals function for fungible token amount * fix undefined check --------- Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> * chore: bump xverse-core to 1.6.1 (#561) * fix: Don't use ordinals as inputs when recovering ordinals (#558) * Use updated type from sats-connect (#546) * Use updated type from sats-connect * chore: bump sats-connect to 1.0.0 * Update package-lock.json --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * feat: remove binance onramp from buy screen (#567) * Release 0.16.0 (#565) * 0.16.0 * feat: change restore and backup wallet inputs (#566) * chore: fix eslint errors with typing and use of fragments * feat: move restore wallet route to larger screen size * feat: replace restore wallet seed phrase text area with input boxes * fix: ensure only one input can be visible at a time * feat: implement verify seed quiz * feat: disable copy of seed phrase view * fix: set error message properly * refactor: clean up to use one effect * fix: styling and input labels on backup/restore wallet * fix: handle edge case where new mnemonic already contains the answer * feat: seedPhraseInput will focus on next input on space and do not allow some common special characters * fix: decouple copy from restore wallet and change password screens * fix: bump xverse-core to 1.6.2 (#574) * Fix incorrect swap transaction fee ticker (#562) * Use STX as fee currency in swap screen * Fix typo * Fix variable name * Fix fiat rate state calculation * Show correct ticker and currency * Remove isSponsored check for fee amount * Add ability to remove connected Ledger account (#524) * Add ability to remove connected Ledger account * Improve the ledger account removal logic * Select the first account after ledger account removal * Create a reusable `optionsDialog` component * Fix account list logic, rename `seperator` component to `separator` * Fix option dialog indents * Add `deviceAccountIndex` value for ledger accounts that are missing it * Fix ledger account address verification * Move the `deviceAccountIndex` field migration to `loadActiveAccounts` func * Update copy --------- Co-authored-by: Tim Man * Support BTC message signing with ledger accounts (#549) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * release: v0.17.0 (#576) * release: v0.17.0 * chore: bump to 1.6.3-rc.1 (#575) * chore: bump to 1.6.3-rc.1 * bump core version --------- Co-authored-by: Yukan * update package-lock --------- Co-authored-by: Yukan * Filter out dead pending transactions (#568) * Filter out dead pending transactions * Get account current nonce from confirmed and pending transactions * Refactor filterng out dead pending transaction logic * Address comments * Update variable name * fix: account select navigation (#578) * Display pending fungible token transactions in token dashboard (#572) * Update filterTx function to show pending fungible transactions * Fix transaction title display * Show pending ordinal transactions (#563) * Show pending ordinal transactions * Slight refactor of getBtcTokenTransferTitle * Fix duplicate tx in groupBtcTxsByDate * chore: bump to xverse-core v1.6.4-rc.2 * Remove unused fallback value --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man * feat: add Xverse namespaced providers (#581) * add Xverse namespaced providers * fix comments * Enable PSBT signing for ledger BTC accounts (#570) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Enable PSBT signing for ledger BTC accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * Update PSBT signing screen copy * fix: allow display of brc-20 if application/json type (#587) * fix: allow display of brc-20 if application/json type * make bg colours for a BRC-20 coin consistent * fix: full screen and popup styling (#577) * fix: full screen and popup styling * fix screen container * fix app load styling * fix full screen popup pages --------- Co-authored-by: Tim Man * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Add STX support for Ledger accounts (#564) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Fix ledger account import when both BTC and STX options are selected * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Add error handling when user rejects stx address * Add a guard from account changing for the `/add-stx-address-ledger` route * Remove the back button on the ledger account import flow * Throw an error when `stacksCreds` were not fetched * Upgrade `@secretkeylabs/xverse-core` version to `^1.6.5-3bb284c` * Update package files * Fix add stx address error handling * Fix signing with 1st ledger account and bottom modal position * Skip the `No errors` value of the `errorMessage` for STX ledger signature * Remove the caret symbol in `sats-connect` package version * chore: bump xverse-core version 1.7.2 --------- Co-authored-by: Tim Man * fix: brc-20 balance number check (#592) * fix: don't show fees until we have UTXOs on inscription screen (#594) * fix: improve full screen popup styling (#593) * fix: improve full screen popup styling * fix: set height to 600 on options window * Release/v0.18.0 (#591) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json --------- Co-authored-by: Victor Kirov Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Fix Tx history screen reload & send form navigation issues (#584) * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * Update dependency array for useEffect * Add comment * Fix memo error * Support script outputs in psbts (#534) * Support script outputs * Update copy * Revert package.json change * Add info message for output script * Use Array.some * Remove unused style * Update core versio and address comments * Remove pretext from output script ui * Refactor render script output logic * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * chore: turn on eslint for staged files on precommit and turn off no-plusplus rule * Fix eslint issues * Update dependency array for useEffect * Add comment * Fix script count * fix: eslint fix --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * Mismatch when verifying the addresses from the ledger device (#580) * Handle min fee rate returned by the API (#583) * Handle min fee rate returned by the API * Add a check for the STX tx min fee * Fix a couple of tslint errors * fix: don't show loader on balance refetch on home screen ENG-2757 (#589) * Add refetch loader * resize loading spinner * Release/v0.18.2 (#600) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json * release v0.18.2 * fix send through app fees when inscribing * update package-lock --------- Co-authored-by: Tim Man Co-authored-by: Victor Kirov Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * feat: 1 step brc 20 transfers (#585) * chore: use xverse-core with brc20 hooks * refactor: make reusable fiat row component from sendForm * feat: update send brc20 form to use 1 step mode * feat: update theme elevations to revamp elevations * fix: ensure brc20 currencies are uppercase * fix: remove margin on reusable component tokenImage * feat: create confirm brc20 transaction screen * chore: add jsx key eslint rule * feat: style the brc20 review screen & fees component * feat: implement edit fees for brc20 transfer * fix: show brc20 ticker and image on confirm screen * fix: styling of account header and other brc20 fixes * feat: remove copy buttons from account header * feat: bottom bar will always maintain height * fix: padding and margins on confirm brc20 screen * feat: create a file for common styles and new screen for execute brc20 * fix: styling, react errors, and estimate fees on click edit fees buttons * fix: edit fees button width * fix: account list padding * feat: implement loading status animation * feat: integrate the animations for loading transaction status * fix: clean up TODOs * feat: use content loader in brc20 edit fees * chore: rename the common styled file * fix: fix reset user flow on confirmBrc20Transaction and unused styles * Revert "feat: bottom bar will always maintain height" This reverts commit 07e9fca564beb0a971c4703aa07893a8a9491e5d. * docs: comment * Update src/app/screens/confirmBrc20Transaction/index.tsx Co-authored-by: Victor Kirov * style: use relative import for consistency * style: remove unused comment * docs: add todo to existing comment * fix: reset user flow to '/' and other review fixes * fix: don't clear input if a disallowed key is pressed * fix: ensure only run executeBrc20Transaction once * refactor: simplify usage of useResetUserFlow * chore: remove unused types * chore: update core version to use new brc20 hook * refactor: use useBrc20EstimateTransfer hook * refactor: save edit fees previous state if user clicks cancel * refactor: separate logic to hook * fix: add hook typings and use phosphor icon * fix: actually pass the user input fee rate to execute transfer * fix: disable cancel and confirm buttons while estimate fee is loading * fix: add padding back in account row list on btc select address screen * fix: colors on options and popup css * fix: button positioning on full screen ledger view * refactor: rename one step brc20 send screen and put TODOs for ledger * revert: restore 2 step brc20 send form for ledger support * fix: apply useResetUserFlow update to sendBrc20 * fix: restore 2 step brc20 translations * fix: update new pages to refactored reset user flow hook --------- Co-authored-by: Victor Kirov * update license (#606) * Add scrollbar on all scrollable screens (#582) * Update scrollbar * Include scrollbar styling in theme file * Show transparent scrollbar in account list screen * Remove disable cycle dependency flag * Revert unrelated eslint fixes * Update src/theme/index.ts Co-authored-by: Tim Man * Update theme file * Add missing hidden scrollbar css --------- Co-authored-by: Tim Man * fix: loader on home page issues (#603) Co-authored-by: Tim Man * Fix scrollbar in landing page (#609) * Fix scrollbar in landing page * Revert "Fix scrollbar in landing page" This reverts commit 46c1a8f45cd4f308c84a15db2e57bc284515bbbe. * fix: add back the global CSS to hide scrollbars by default and add display: block on scrollbars CSS when desired --------- Co-authored-by: Tim Man * feat: notice for an non taproot address when sending brc 20 tokens (#602) * refactor: move fiatRow into separate component * feat: add callout and inputFeedback to send brc20 one step screen and include components in ui-library * feat: add conditional callouts to confirm brc20 screen * feat: update the recipient card on confirm brc20 transaction * fix: input borders should reflect errors only, not info feedback * refactor: include a helper function for checking if error state * refactor: make styles consistent in callout.tsx * fix: remove unused icon variants * fix: fix styling and imports on brc20 one step and callout component * refactor: use recipient card props instead of type from core * fix: update success callout color and add to theme * fix: fix estimate fee error not showing, and vertical align of callout body * refactor: use styled components instead of React.createElement * Revert "refactor: use styled components instead of React.createElement" This reverts commit 31faea642fdcc867b0cec707bf2ff8a5814aab44. * fix: disable key presses for - and . on brc20 edit fees * refactor: use styled icon instead of React.createElement * refactor: use fiatAmountText component and allow styling * fix: use input feedback in editFees and update components to allow styled components * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and code t… * Fix main dev drift (#647) * release: v0.22.0-rc.4 to main (#642) * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * feat: add sponsor swap transaction UI and add a hook with placeholder * feat: bump xverse-core dep version and use sponsor2 url * fix: bump xverse-core version and handle sponsor transaction error * feat(Dashboard): update new action button style and add swap button * feat(Swap): add swap screen placeholder * feat(swap): add swap basic UI * feat(swap): add more UI components * feat(swap): add slippage * feat(swap): make BitCoin and Stacks option in the coin select modal * feat(swap): add token selection logic * feat: add swap data connection * feat(swap): add runSwap * chore(swap): bump alex-sdk version * fix(swap): slippage setting * feat: swap confirm layout * feat: add data bindings * fix: function name and copy address * feat: add advanced settings to the confirmation page * feat: bump alex-sdk to latest and fix the issue where from is the same as to * feat: add math.floor before converting to bigInt * fix: skip action when input is invalid * chore: update package.lock * feat(swap): update to support amm v1_1 pools * chore: fix lint warnings * fix: update swap svg stroke and add missing translation * fix: add key to fix react warnings * chore: fix lint warnings * fix: add error 700 border to swap token card * fix: update swap error message and restrict input to number * chore: prettier * style: add a not-allowed cursor to disabled buttons * fix: update translations * fix: use background elevation_1 * style: update swap details spacing * style: use unicode arrow right for swap route details * feat: implement toggle tokens button in swaps * feat: add reset slippage button to swaps * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * style: prettier * chore: update package-lock with npm i * chore: fix package-lock.json for correct xverse-core dep * chore: replace workflow dep with github api calls * chore: remove erroneous ` * Fix Edit fees popup error * Fix Edit fees popup error * Add receiving address verification for ledger accounts * Fix warning display condition on the ledger verification screen * Dont close popup on checkbox click * fix: fix for JSON serialisation of location.state * chore: use the test instance URL * chore: upgrade to alex-sdk 0.1.14 * Show wrong ledger device error * Add custom ledger account name validation * fix: turn react deps warning back on and fix stale callback * fix: move sponsor url to constants and add sponsor to swap unsigned tx * fix: display the transaction explorer link on successful sponsored tx * fix: set swap transaction fee to 0 if being sponsored * The transaction history not showing a pending send transaction that was just sent from the address * release v0.14.0 * chore: update xverse-core to published release 1.4.0 * chore: update swaps xverse sponsor 2 host * fix: remove btc from swaps coin modal. change was removed during merge * fix: remove static text describing swap route * Add Before Getting Started screen for Ledger onboarding * update copy * add links and update copy * chore: add husky and pre commit prettier to staged files * chore: run prettier --write ./src * fix: show inscription service fee fiat amount * Fix ledger account name UI issue * Show loader instead of previous transaction history data * comment out swaps button * Add localization for onboarding flow Ledger Live warning screen * chore: automatically do husky install on npm install * chore: prefer .husky for hooks * chore: run prettier again * fix: fix unsigned tx serialisation in advance settings for swaps * fix: use getNewNonce to ensure swaps transactions have correct nonce * docs: comment * bump xverse-core to v1.4.2 * fix: only show swaps button if not on a ledger account * fix: post condition info should display to/from depending on the swap * Fix regression issues v0.14.0-rc.1 * fix: ensure we are sending the correct ordinal * fix: ensure we are sending the correct ordinal * 0.14.1 * fix: remove unnecessary nested BalanceAmountText * fix: use semantic html instead of all h1 * fix: add a filter list to not display coins for swaps * Fix screen crash when changing account on /send-brc20 screen * fix: button should always be disabled when processing and show loading state in swap with await, and fix typing * Update /send-brc20 screen logic * use toString to convert value to BigNumber * chore: bump xverse-core to 1.5.0 * fix: not all tickers are all uppercase e.g. xBTC * fix: decouple alex swap from/to token list and visible token list * Fix the case when address verification screen flashes when using wrong device * Add an override switch for sponsoring transaction in swap screen * Update function param name * chore: bump core version to 1.6.0 (#560) * Allow send ordinal to self and display warning instead of error (#525) * feat: allow send ordinal to self and display warning instead of error * feat: remove send btc send to self error and use warning also adjust send ordinal warning if sending brc20 ordinal to self * Release v0.15.0 (#544) * bump version to v0.15.0 * Switch to alex sdk & url for sponsoring service Inspect error code and show sponsoring service info block feat: move alex sponsored transaction hook to new file revert: changes to useSponsoredTransaction hook for future use fix: sponsor transaction switch should toggle userOverrideSponsorValue feat: add a try again button on failed swaps due to sponsor error * feat: add warning texts to explain why a swap cannot be sponsored (#553) * fix: enforce width on swap number input (#554) * Fix swap screen fee update issue (#555) * Use correct value for fee card component * Fix fee state management * Dont show fee block when sponsored * chore: bump xverse-core to 1.5.1 to include fetchStxPendingTxData fix * Fix ui glitch on the login screen (#556) * Remove css transition code * Add hover and active state * fix: use :disabled css pseudo class instead of props on buttons --------- Co-authored-by: Tim Man * Fix swaps tx history (#557) * Use ft transfer array to show token specific history * Add filter to only show specific token history * Refactor txTransfers file to reuse code * Use token ticker * Update variable name * Use correct decimal places for fungible token (#559) * Use ftDecimals function for fungible token amount * fix undefined check --------- Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> * chore: bump xverse-core to 1.6.1 (#561) * fix: Don't use ordinals as inputs when recovering ordinals (#558) * Use updated type from sats-connect (#546) * Use updated type from sats-connect * chore: bump sats-connect to 1.0.0 * Update package-lock.json --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * feat: remove binance onramp from buy screen (#567) * Release 0.16.0 (#565) * 0.16.0 * feat: change restore and backup wallet inputs (#566) * chore: fix eslint errors with typing and use of fragments * feat: move restore wallet route to larger screen size * feat: replace restore wallet seed phrase text area with input boxes * fix: ensure only one input can be visible at a time * feat: implement verify seed quiz * feat: disable copy of seed phrase view * fix: set error message properly * refactor: clean up to use one effect * fix: styling and input labels on backup/restore wallet * fix: handle edge case where new mnemonic already contains the answer * feat: seedPhraseInput will focus on next input on space and do not allow some common special characters * fix: decouple copy from restore wallet and change password screens * fix: bump xverse-core to 1.6.2 (#574) * Fix incorrect swap transaction fee ticker (#562) * Use STX as fee currency in swap screen * Fix typo * Fix variable name * Fix fiat rate state calculation * Show correct ticker and currency * Remove isSponsored check for fee amount * Add ability to remove connected Ledger account (#524) * Add ability to remove connected Ledger account * Improve the ledger account removal logic * Select the first account after ledger account removal * Create a reusable `optionsDialog` component * Fix account list logic, rename `seperator` component to `separator` * Fix option dialog indents * Add `deviceAccountIndex` value for ledger accounts that are missing it * Fix ledger account address verification * Move the `deviceAccountIndex` field migration to `loadActiveAccounts` func * Update copy --------- Co-authored-by: Tim Man * Support BTC message signing with ledger accounts (#549) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * release: v0.17.0 (#576) * release: v0.17.0 * chore: bump to 1.6.3-rc.1 (#575) * chore: bump to 1.6.3-rc.1 * bump core version --------- Co-authored-by: Yukan * update package-lock --------- Co-authored-by: Yukan * Filter out dead pending transactions (#568) * Filter out dead pending transactions * Get account current nonce from confirmed and pending transactions * Refactor filterng out dead pending transaction logic * Address comments * Update variable name * fix: account select navigation (#578) * Display pending fungible token transactions in token dashboard (#572) * Update filterTx function to show pending fungible transactions * Fix transaction title display * Show pending ordinal transactions (#563) * Show pending ordinal transactions * Slight refactor of getBtcTokenTransferTitle * Fix duplicate tx in groupBtcTxsByDate * chore: bump to xverse-core v1.6.4-rc.2 * Remove unused fallback value --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man * feat: add Xverse namespaced providers (#581) * add Xverse namespaced providers * fix comments * Enable PSBT signing for ledger BTC accounts (#570) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Enable PSBT signing for ledger BTC accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * Update PSBT signing screen copy * fix: allow display of brc-20 if application/json type (#587) * fix: allow display of brc-20 if application/json type * make bg colours for a BRC-20 coin consistent * fix: full screen and popup styling (#577) * fix: full screen and popup styling * fix screen container * fix app load styling * fix full screen popup pages --------- Co-authored-by: Tim Man * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Add STX support for Ledger accounts (#564) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Fix ledger account import when both BTC and STX options are selected * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Add error handling when user rejects stx address * Add a guard from account changing for the `/add-stx-address-ledger` route * Remove the back button on the ledger account import flow * Throw an error when `stacksCreds` were not fetched * Upgrade `@secretkeylabs/xverse-core` version to `^1.6.5-3bb284c` * Update package files * Fix add stx address error handling * Fix signing with 1st ledger account and bottom modal position * Skip the `No errors` value of the `errorMessage` for STX ledger signature * Remove the caret symbol in `sats-connect` package version * chore: bump xverse-core version 1.7.2 --------- Co-authored-by: Tim Man * fix: brc-20 balance number check (#592) * fix: don't show fees until we have UTXOs on inscription screen (#594) * fix: improve full screen popup styling (#593) * fix: improve full screen popup styling * fix: set height to 600 on options window * Release/v0.18.0 (#591) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json --------- Co-authored-by: Victor Kirov Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Fix Tx history screen reload & send form navigation issues (#584) * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * Update dependency array for useEffect * Add comment * Fix memo error * Support script outputs in psbts (#534) * Support script outputs * Update copy * Revert package.json change * Add info message for output script * Use Array.some * Remove unused style * Update core versio and address comments * Remove pretext from output script ui * Refactor render script output logic * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * chore: turn on eslint for staged files on precommit and turn off no-plusplus rule * Fix eslint issues * Update dependency array for useEffect * Add comment * Fix script count * fix: eslint fix --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * Mismatch when verifying the addresses from the ledger device (#580) * Handle min fee rate returned by the API (#583) * Handle min fee rate returned by the API * Add a check for the STX tx min fee * Fix a couple of tslint errors * fix: don't show loader on balance refetch on home screen ENG-2757 (#589) * Add refetch loader * resize loading spinner * Release/v0.18.2 (#600) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json * release v0.18.2 * fix send through app fees when inscribing * update package-lock --------- Co-authored-by: Tim Man Co-authored-by: Victor Kirov Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * feat: 1 step brc 20 transfers (#585) * chore: use xverse-core with brc20 hooks * refactor: make reusable fiat row component from sendForm * feat: update send brc20 form to use 1 step mode * feat: update theme elevations to revamp elevations * fix: ensure brc20 currencies are uppercase * fix: remove margin on reusable component tokenImage * feat: create confirm brc20 transaction screen * chore: add jsx key eslint rule * feat: style the brc20 review screen & fees component * feat: implement edit fees for brc20 transfer * fix: show brc20 ticker and image on confirm screen * fix: styling of account header and other brc20 fixes * feat: remove copy buttons from account header * feat: bottom bar will always maintain height * fix: padding and margins on confirm brc20 screen * feat: create a file for common styles and new screen for execute brc20 * fix: styling, react errors, and estimate fees on click edit fees buttons * fix: edit fees button width * fix: account list padding * feat: implement loading status animation * feat: integrate the animations for loading transaction status * fix: clean up TODOs * feat: use content loader in brc20 edit fees * chore: rename the common styled file * fix: fix reset user flow on confirmBrc20Transaction and unused styles * Revert "feat: bottom bar will always maintain height" This reverts commit 07e9fca564beb0a971c4703aa07893a8a9491e5d. * docs: comment * Update src/app/screens/confirmBrc20Transaction/index.tsx Co-authored-by: Victor Kirov * style: use relative import for consistency * style: remove unused comment * docs: add todo to existing comment * fix: reset user flow to '/' and other review fixes * fix: don't clear input if a disallowed key is pressed * fix: ensure only run executeBrc20Transaction once * refactor: simplify usage of useResetUserFlow * chore: remove unused types * chore: update core version to use new brc20 hook * refactor: use useBrc20EstimateTransfer hook * refactor: save edit fees previous state if user clicks cancel * refactor: separate logic to hook * fix: add hook typings and use phosphor icon * fix: actually pass the user input fee rate to execute transfer * fix: disable cancel and confirm buttons while estimate fee is loading * fix: add padding back in account row list on btc select address screen * fix: colors on options and popup css * fix: button positioning on full screen ledger view * refactor: rename one step brc20 send screen and put TODOs for ledger * revert: restore 2 step brc20 send form for ledger support * fix: apply useResetUserFlow update to sendBrc20 * fix: restore 2 step brc20 translations * fix: update new pages to refactored reset user flow hook --------- Co-authored-by: Victor Kirov * update license (#606) * Add scrollbar on all scrollable screens (#582) * Update scrollbar * Include scrollbar styling in theme file * Show transparent scrollbar in account list screen * Remove disable cycle dependency flag * Revert unrelated eslint fixes * Update src/theme/index.ts Co-authored-by: Tim Man * Update theme file * Add missing hidden scrollbar css --------- Co-authored-by: Tim Man * fix: loader on home page issues (#603) Co-authored-by: Tim Man * Fix scrollbar in landing page (#609) * Fix scrollbar in landing page * Revert "Fix scrollbar in landing page" This reverts commit 46c1a8f45cd4f308c84a15db2e57bc284515bbbe. * fix: add back the global CSS to hide scrollbars by default and add display: block on scrollbars CSS when desired --------- Co-authored-by: Tim Man * feat: notice for an non taproot address when sending brc 20 tokens (#602) * refactor: move fiatRow into separate component * feat: add callout and inputFeedback to send brc20 one step screen and include components in ui-library * feat: add conditional callouts to confirm brc20 screen * feat: update the recipient card on confirm brc20 transaction * fix: input borders should reflect errors only, not info feedback * refactor: include a helper function for checking if error state * refactor: make styles consistent in callout.tsx * fix: remove unused icon variants * fix: fix styling and imports on brc20 one step and callout component * refactor: use recipient card props instead of type from core * fix: update success callout color and add to theme * fix: fix estimate fee error not showing, and vertical align of callout body * refactor: use styled components instead of React.createElement * Revert "refactor: use styled components instead of React.createElement" This reverts commit 31faea642fdcc867b0cec707bf2ff8a5814aab44. * fix: disable key presses for - and . on brc20 edit fees * refactor: use styled icon instead of React.createElement * refactor: use fiatAmountText component and allow styling * fix: use input feedback in editFees and update components to allow styled components * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch an… * fix: when clicking on the inscription image in the details view (#659) * fix: settings layover (#657) * navigate back to the screen that triggers login (#651) * fix: bad merge with imports --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> Co-authored-by: Mahmoud Aboelenein Co-authored-by: Kyle Fang Co-authored-by: Denys Hriaznov Co-authored-by: Imamah-Zafar --- .eslintrc.json | 30 +- .github/workflows/build.yml | 10 +- .github/workflows/release.yml | 8 +- package-lock.json | 19429 ++++++++-------- package.json | 24 +- src/app/components/accountHeader/index.tsx | 25 +- src/app/components/accountRow/index.tsx | 12 +- src/app/components/alertMessage/index.tsx | 12 +- src/app/components/backHeader/index.tsx | 47 - src/app/components/bottomModal/index.tsx | 2 +- src/app/components/button/index.tsx | 12 +- src/app/components/checkBox/index.tsx | 2 +- .../confirmBtcTransactionComponent/index.tsx | 72 +- .../inputOutputComponent.tsx | 26 +- .../confirmStxTransactionComponent/index.tsx | 53 +- .../transferMemoView/index.tsx | 8 +- .../confirmTransactionScreen/index.tsx | 58 - src/app/components/copyButton/index.tsx | 6 +- .../extendedScreenContainer/index.tsx | 9 +- src/app/components/guards/auth.tsx | 51 +- .../components/guards/onboarding/index.tsx | 19 +- src/app/components/infoContainer/index.tsx | 12 +- .../ledger/connectLedgerView/index.tsx | 2 +- .../ledger/failLedgerView/index.tsx | 2 +- .../ledger/fullScreenHeader/index.tsx | 2 +- .../ledger/ledgerAddressComponent/index.tsx | 6 +- .../ledger/ledgerAssetSelectCard/index.tsx | 4 +- .../components/ledger/ledgerInput/index.tsx | 4 +- .../circularSvgAnimation.tsx | 8 +- .../optionsDialog/optionsDialog.tsx | 2 +- src/app/components/passwordInput/index.tsx | 20 +- .../components/receiveCardComponent/index.tsx | 4 +- .../components/recipientAddressView/index.tsx | 10 +- .../components/recipientComponent/index.tsx | 28 +- src/app/components/resetWallet/index.tsx | 2 +- src/app/components/screenContainer/index.tsx | 15 +- src/app/components/seedPhraseInput/index.tsx | 16 +- src/app/components/seedPhraseView/index.tsx | 20 +- src/app/components/seedPhraseView/word.tsx | 2 +- src/app/components/sendForm/index.tsx | 96 +- src/app/components/shareNft/index.tsx | 14 +- src/app/components/shareNft/shareLinkRow.tsx | 2 +- .../components/smallActionButton/index.tsx | 8 +- src/app/components/stepper/index.tsx | 23 +- src/app/components/steps/index.tsx | 6 +- src/app/components/tabBar/index.tsx | 2 +- src/app/components/tokenImage/index.tsx | 10 +- src/app/components/tokenTile/index.tsx | 70 +- src/app/components/topRow/index.tsx | 11 +- .../transactionDetailComponent/index.tsx | 16 +- .../components/transactionSetting/editFee.tsx | 46 +- .../transactionSetting/editNonce.tsx | 10 +- .../components/transactionSetting/index.tsx | 20 +- .../transactions/btcTransaction.tsx | 4 +- .../transactions/stxTransaction.tsx | 12 +- .../transactions/stxTransferTransaction.tsx | 16 +- .../transactions/transactionAmount.tsx | 2 +- .../transactions/transactionRecipient.tsx | 2 +- .../transactions/transactionTitle.tsx | 2 +- .../components/transactions/txTransfers.tsx | 22 +- .../ContractCallRequest.tsx | 188 +- .../ContractDeployTransaction.tsx | 36 +- .../transferAmountComponent/index.tsx | 16 +- .../components/transferAmountView/index.tsx | 4 +- .../components/transferDetailView/index.tsx | 14 +- src/app/components/transferFeeView/index.tsx | 8 +- .../useAddressInscriptionCollections.ts | 7 +- .../ordinals/useAddressInscriptions.ts | 6 +- .../queries/ordinals/useAddressRareSats.ts | 14 +- .../ordinals/useCollectionMarketData.ts | 5 +- .../hooks/queries/ordinals/useInscription.ts | 4 +- .../queries/ordinals/useInscriptionDetails.ts | 11 +- src/app/hooks/queries/useAppConfig.ts | 17 +- src/app/hooks/queries/useBtcCoinsBalance.ts | 4 +- src/app/hooks/queries/useBtcWalletData.ts | 6 +- src/app/hooks/queries/useCoinData.ts | 28 +- src/app/hooks/queries/useCoinRates.ts | 13 +- src/app/hooks/queries/useFeeMultipliers.ts | 22 +- src/app/hooks/queries/usePendingOrdinalTx.ts | 4 +- src/app/hooks/queries/useStackingData.ts | 16 +- .../hooks/queries/useStacksCollectibles.ts | 9 +- src/app/hooks/queries/useStxPendingTxData.ts | 4 +- src/app/hooks/queries/useStxWalletData.ts | 7 +- src/app/hooks/queries/useTransactions.ts | 6 +- src/app/hooks/useBtcFeeRate.ts | 6 +- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 32 +- src/app/hooks/useOrdinalsApi.ts | 4 +- src/app/hooks/useOrdinalsByAddress.ts | 4 +- src/app/hooks/useSeedVault.ts | 46 + src/app/hooks/useSendBtcRequest.ts | 6 +- src/app/hooks/useSignPsbtTx.ts | 5 +- src/app/hooks/useSignatureRequest.ts | 29 +- src/app/hooks/useTextOrdinalContent.ts | 11 +- src/app/hooks/useWalletReducer.ts | 99 +- src/app/hooks/useWalletSession.ts | 26 +- src/app/routes/index.tsx | 6 +- src/app/screens/accountList/index.tsx | 8 +- .../screens/authenticationRequest/index.tsx | 41 +- src/app/screens/backupWallet/index.tsx | 37 +- src/app/screens/backupWalletSteps/index.tsx | 34 +- .../screens/backupWalletSteps/seedCheck.tsx | 6 +- .../screens/backupWalletSteps/verifySeed.tsx | 12 +- .../btcSelectAddressScreen/accountView.tsx | 6 +- .../screens/btcSelectAddressScreen/index.tsx | 22 +- src/app/screens/btcSendScreen/index.tsx | 1 - src/app/screens/buy/index.tsx | 22 +- src/app/screens/buy/redirectButton.tsx | 6 +- src/app/screens/coinDashboard/coinHeader.tsx | 44 +- src/app/screens/coinDashboard/index.tsx | 101 +- .../coinDashboard/transactionsHistoryList.tsx | 6 +- .../brc20FeesComponent.tsx | 8 +- .../confirmBrc20Transaction/editFees.tsx | 30 +- .../screens/confirmBrc20Transaction/index.tsx | 3 +- .../screens/confirmBtcTransaction/index.tsx | 48 +- .../confirmInscriptionRequest/index.tsx | 76 +- .../screens/confirmNftTransaction/index.tsx | 82 +- .../confirmOrdinalTransaction/index.tsx | 4 +- .../createInscription/ContentLabel/index.tsx | 17 +- .../createInscription/ErrorModal/index.tsx | 2 +- src/app/screens/createInscription/index.tsx | 22 +- src/app/screens/createPassword/index.tsx | 28 +- src/app/screens/createWalletSuccess/index.tsx | 8 +- src/app/screens/error/index.tsx | 16 +- .../screens/executeBrc20Transaction/index.tsx | 16 +- src/app/screens/forgotPassword/index.tsx | 59 +- src/app/screens/home/balanceCard/index.tsx | 8 +- .../screens/home/coinSelectModal/index.tsx | 14 +- src/app/screens/home/index.tsx | 11 +- src/app/screens/landing/index.tsx | 14 +- .../confirmLedgerTransaction/index.styled.ts | 8 +- .../index.styled.ts | 6 +- src/app/screens/legalLinks/index.tsx | 29 +- src/app/screens/login/index.tsx | 44 +- .../screens/manageTokens/coinItem/index.tsx | 6 +- .../screens/nftDashboard/collectiblesTabs.tsx | 165 +- src/app/screens/nftDashboard/index.tsx | 124 +- src/app/screens/nftDashboard/notice.tsx | 2 +- .../nftDashboard/tilesSkeletonLoader.tsx | 41 + src/app/screens/nftDetail/index.tsx | 22 +- src/app/screens/nftDetail/nftAttribute.tsx | 6 +- src/app/screens/onboarding/index.tsx | 2 +- src/app/screens/ordinalDetail/index.tsx | 80 +- .../ordinalAttributeComponent.tsx | 4 +- .../screens/ordinalDetail/useOrdinalDetail.ts | 6 +- src/app/screens/ordinals/brc20Tile.tsx | 4 +- src/app/screens/ordinals/index.tsx | 2 +- src/app/screens/ordinals/ordinalImage.tsx | 65 +- .../screens/rareSatsDetail/rareSatsDetail.tsx | 16 +- src/app/screens/receive/index.tsx | 6 +- src/app/screens/restoreFunds/fundsRow.tsx | 6 +- src/app/screens/restoreFunds/index.tsx | 6 +- .../screens/restoreFunds/restoreBtc/index.tsx | 67 +- .../restoreFunds/restoreOrdinals/index.tsx | 75 +- .../restoreOrdinals/ordinalRow.tsx | 14 +- .../screens/restoreWallet/enterSeedphrase.tsx | 2 +- src/app/screens/restoreWallet/index.tsx | 4 +- .../screens/sendBrc20/brc20TransferForm.tsx | 12 +- .../screens/sendBrc20/brc20TransferInfo.tsx | 4 +- src/app/screens/sendBrc20/index.tsx | 14 +- src/app/screens/sendBrc20OneStep/index.tsx | 1 + src/app/screens/sendBtc/index.tsx | 18 +- src/app/screens/sendNft/index.tsx | 42 +- src/app/screens/sendOrdinal/index.tsx | 5 +- src/app/screens/sendRareSat/index.tsx | 13 +- src/app/screens/sendStx/index.tsx | 25 +- .../screens/settings/backupWallet/index.tsx | 24 +- .../screens/settings/changeNetwork/index.tsx | 24 +- .../settings/changeNetwork/networkRow.tsx | 8 +- .../screens/settings/changePassword/index.tsx | 35 +- .../settings/fiatCurrency/currencyRow.tsx | 8 +- src/app/screens/settings/index.tsx | 38 +- .../screens/settings/lockCountdown/index.tsx | 22 +- .../settings/settingComponent/index.tsx | 5 +- .../signPsbtRequest/bundleItemsComponent.tsx | 10 +- src/app/screens/signPsbtRequest/index.tsx | 2 +- .../signatureRequest/clarityMessageView.tsx | 4 +- .../signatureRequest/collapsableContainer.tsx | 10 +- src/app/screens/signatureRequest/index.tsx | 47 +- .../signatureRequestMessage.tsx | 4 +- .../signatureRequestStructuredData.tsx | 14 - src/app/screens/stacking/index.tsx | 12 +- .../stacking/stackingProgress/index.tsx | 2 +- .../stackingProgress/stackingStatusTile.tsx | 14 +- .../screens/stacking/startStacking/index.tsx | 26 +- .../stacking/startStacking/stackInfoTile.tsx | 6 +- src/app/screens/swap/slippageModal/index.tsx | 14 +- .../advanceSettings/index.tsx | 13 +- .../swap/swapConfirmation/feesBlock/index.tsx | 12 +- .../swapConfirmation/functionBlock/index.tsx | 4 +- .../screens/swap/swapConfirmation/index.tsx | 26 +- .../swapConfirmation/routeBlock/index.tsx | 12 +- .../swapConfirmation/stxInfoBlock/index.tsx | 26 +- .../swap/swapConfirmation/useConfirmSwap.tsx | 21 +- src/app/screens/swap/swapInfoBlock/index.tsx | 14 +- src/app/screens/swap/swapTokenBlock/index.tsx | 20 +- src/app/screens/swap/types.ts | 47 + .../screens/swap/useCurrencyConversion.tsx | 2 +- src/app/screens/swap/useSwap.tsx | 60 +- src/app/screens/transactionRequest/index.tsx | 22 +- src/app/screens/transactionStatus/index.tsx | 24 +- src/app/screens/walletExists/index.tsx | 10 +- src/app/stores/index.ts | 12 +- .../stores/wallet/actions/actionCreators.ts | 39 +- src/app/stores/wallet/actions/types.ts | 40 +- src/app/stores/wallet/reducer.ts | 35 +- src/app/utils/brc20.ts | 8 +- .../utils/{storage.ts => chromeStorage.ts} | 6 +- src/app/utils/constants.ts | 7 +- src/app/utils/currency.ts | 16 +- src/app/utils/encryptionUtils.ts | 63 +- src/app/utils/localStorage.ts | 9 - src/app/utils/mixpanel.ts | 4 +- src/app/utils/query.ts | 19 +- src/app/utils/rareSats.ts | 7 +- src/assets/img/dashboard/swap.svg | 6 - src/assets/img/icons/ArrowSwap.svg | 6 + src/background/background.ts | 7 + src/common/utils/messageHandlers.ts | 24 - src/locales/en.json | 21 +- src/manifest.json | 2 +- src/pages/Options/index.tsx | 12 - src/pages/Popup/index.tsx | 16 - src/react-app-env.d.ts | 5 +- src/theme/index.ts | 221 +- 224 files changed, 12146 insertions(+), 12030 deletions(-) delete mode 100644 src/app/components/backHeader/index.tsx delete mode 100644 src/app/components/confirmTransactionScreen/index.tsx create mode 100644 src/app/hooks/useSeedVault.ts create mode 100644 src/app/screens/nftDashboard/tilesSkeletonLoader.tsx create mode 100644 src/app/screens/swap/types.ts rename src/app/utils/{storage.ts => chromeStorage.ts} (80%) delete mode 100644 src/assets/img/dashboard/swap.svg create mode 100644 src/assets/img/icons/ArrowSwap.svg diff --git a/.eslintrc.json b/.eslintrc.json index 296f35535..e8b938d9e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,10 +20,23 @@ "sourceType": "module", "project": "./tsconfig.json" }, - "plugins": ["react", "prettier", "eslint-plugin-no-inline-styles", "@tanstack/query"], + "plugins": [ + "react", + "prettier", + "eslint-plugin-no-inline-styles", + "@tanstack/query" + ], "rules": { "consistent-return": "off", "import/prefer-default-export": 1, + "no-restricted-imports": [ + "warn", + { + "patterns": [ + "@secretkeylabs/xverse-core/**/*" + ] + } + ], "no-promise-executor-return": "warn", "max-len": "off", "no-inline-styles/no-inline-styles": 2, @@ -42,13 +55,22 @@ "argsIgnorePattern": "^_" } ], - "no-plusplus": "off" + "no-plusplus": "off", + "@tanstack/query/exhaustive-deps": 1 }, "settings": { "import/resolver": { "node": { - "extensions": [".js", ".jsx", ".ts", ".tsx"], - "moduleDirectory": ["node_modules", "src/"] + "extensions": [ + ".js", + ".jsx", + ".ts", + ".tsx" + ], + "moduleDirectory": [ + "node_modules", + "src/" + ] } } } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23a9ffad3..081a0afd5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,24 +14,26 @@ jobs: uses: actions/setup-node@v3 with: always-auth: true - node-version: '16.x' + node-version: '18.x' registry-url: https://npm.pkg.github.com scope: '@secretkeylabs' - name: Install dependencies run: npm ci --legacy-peer-deps env: NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_REGISTRY_TOKEN }} + - name: Test + run: npx eslint . + # run: npx tsc --noEmit + # run: npm test --passWithNoTests - name: Build env: TRANSAC_API_KEY: ${{ secrets.TRANSAC_API_KEY }} MOON_PAY_API_KEY: ${{ secrets.MOON_PAY_API_KEY }} MIX_PANEL_TOKEN: ${{ secrets.MIX_PANEL_TOKEN }} run: npm run build --if-present - # - name: Test - # run: npm test --passWithNoTests - name: Save Filename run: | - BRANCH_NAME=$(echo ${{ github.head_ref }} | sed 's/\//-/') + BRANCH_NAME=$(echo ${{ github.head_ref }} | sed 's/\//-/g') GIT_SHA_SHORT=$(git rev-parse --short ${{ github.sha }}) echo "FILENAME=xverse-extension.$BRANCH_NAME.$GIT_SHA_SHORT" >> $GITHUB_ENV - name: Upload Archive diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff22ad986..b5874ae3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,21 +14,23 @@ jobs: uses: actions/setup-node@v3 with: always-auth: true - node-version: '16.x' + node-version: '18.x' registry-url: https://npm.pkg.github.com scope: '@secretkeylabs' - name: Install dependencies run: npm ci env: NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_REGISTRY_TOKEN }} + - name: Test + run: npx eslint . + # run: npx tsc --noEmit + # run: npm test --passWithNoTests - name: Build env: TRANSAC_API_KEY: ${{ secrets.TRANSAC_API_KEY }} MOON_PAY_API_KEY: ${{ secrets.MOON_PAY_API_KEY }} MIX_PANEL_TOKEN: ${{ secrets.MIX_PANEL_TOKEN }} run: npm run build --if-present - # - name: Test - # run: npm test --passWithNoTests - name: Save Filename id: save-filename run: | diff --git a/package-lock.json b/package-lock.json index 87820a7dd..6d2709260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,21 @@ { "name": "xverse-web-extension", - "version": "0.21.0", + "version": "0.22.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xverse-web-extension", - "version": "0.21.0", + "version": "0.22.1", "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.9.1", + "@secretkeylabs/xverse-core": "2.3.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", - "@stacks/stacks-blockchain-api-types": "^6.1.1", - "@stacks/transactions": "^4.3.8", + "@stacks/stacks-blockchain-api-types": "6.1.1", + "@stacks/transactions": "4.3.8", "@tanstack/query-sync-storage-persister": "^4.29.1", "@tanstack/react-query": "^4.29.3", "@tanstack/react-query-devtools": "^4.29.3", @@ -70,7 +70,9 @@ "zxcvbn": "^4.4.2" }, "devDependencies": { - "@babel/preset-react": "^7.18.6", + "@babel/core": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-react": "^7.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@tanstack/eslint-plugin-query": "^4.29.4", "@types/argon2-browser": "^1.18.1", @@ -85,11 +87,10 @@ "@types/zxcvbn": "^4.4.1", "@typescript-eslint/eslint-plugin": "^5.37.0", "@typescript-eslint/parser": "^5.37.0", - "babel-core": "^6.26.3", + "babel-core": "^7.0.0-bridge.0", + "babel-jest": "^27.5.1", "babel-loader": "^8.2.5", "babel-plugin-styled-components": "^2.0.7", - "babel-preset-env": "^1.7.0", - "babel-preset-react": "^6.24.1", "base64-loader": "^1.0.0", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^11.0.0", @@ -122,12 +123,16 @@ "terser-webpack-plugin": "^5.3.6", "ts-jest": "^27.0.5", "ts-loader": "^8.4.0", + "tsc-files": "^1.1.4", "tsconfig-paths-webpack-plugin": "^4.0.0", "type-fest": "^2.19.0", "typescript": "^4.8.2", "webpack": "^5.61.0", "webpack-cli": "^4.0.0", "webpack-dev-server": "^4.11.0" + }, + "engines": { + "node": "^18.18.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -157,20 +162,21 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "engines": { "node": ">=6.9.0" } @@ -205,11 +211,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -229,17 +235,66 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dependencies": { "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, "engines": { "node": ">=6.9.0" }, @@ -247,21 +302,75 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -278,27 +387,39 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -307,6 +428,18 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-plugin-utils": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", @@ -315,6 +448,40 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/helper-simple-access": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", @@ -326,6 +493,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", @@ -346,17 +525,31 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, "engines": { "node": ">=6.9.0" } @@ -375,12 +568,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -388,9 +581,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -398,6 +591,50 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -434,6 +671,75 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -544,6 +850,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -574,10 +895,26 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-display-name": { + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", - "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -589,17 +926,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", - "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { "node": ">=6.9.0" @@ -608,13 +944,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { + "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", "dev": true, "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.22.5" + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -623,13 +961,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { + "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", - "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -639,18 +976,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-react": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", - "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.5", - "@babel/plugin-transform-react-display-name": "^7.22.5", - "@babel/plugin-transform-react-jsx": "^7.22.5", - "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -659,1068 +991,1402 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", - "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.11" + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/types": { + "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "to-fast-properties": "^2.0.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@bitcoinerlab/descriptors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.1.1.tgz", - "integrity": "sha512-AMFkbBBg9T1iWtEmWB23oADk7zaOQix6wUPLXalhTyFDjhkFXDd6pCRfto/HAdaPg/ccM4GMTVgYLee9WdYFyQ==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dev": true, "dependencies": { - "@bitcoinerlab/miniscript": "^1.2.1", - "@bitcoinerlab/secp256k1": "^1.0.5", - "bip32": "^4.0.0", - "bitcoinjs-lib": "^6.1.3", - "ecpair": "^2.1.0" + "@babel/helper-plugin-utils": "^7.22.5" }, - "peerDependencies": { - "ledger-bitcoin": "^0.2.2" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "ledger-bitcoin": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@bitcoinerlab/miniscript": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.4.0.tgz", - "integrity": "sha512-BsG3dmwQmgKHnRZecDgUsPjwcpnf1wgaZbolcMTByS10k1zYzIx97W51LzG7GvokRJ+wnzTX/GhC8Y3L2X0CQA==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, "dependencies": { - "bip68": "^1.0.4" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@bitcoinerlab/secp256k1": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.0.5.tgz", - "integrity": "sha512-8gT+ukTCFN2rTxn4hD9Jq3k+UJwcprgYjfK/SQUSLgznXoIgsBnlPuARMkyyuEjycQK9VvnPiejKdszVTflh+w==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, "dependencies": { - "@noble/hashes": "^1.1.5", - "@noble/secp256k1": "^1.7.1" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, "engines": { - "node": ">=10.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dev": true, "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "stylis": "4.2.0" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, "dependencies": { - "@emotion/memoize": "^0.8.1" + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/react": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", - "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, - "peerDependencies": { - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/serialize": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", - "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, - "node_modules/@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", - "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", - "dependencies": { - "@floating-ui/utils": "^0.1.1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/dom": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", - "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, "dependencies": { - "@floating-ui/core": "^1.4.1", - "@floating-ui/utils": "^0.1.1" + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/utils": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", - "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { - "node": ">=6" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz", + "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@babel/plugin-transform-react-jsx": "^7.22.5" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@babel/plugin-transform-regenerator/node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@babel/runtime": "^7.8.4" } }, - "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "node": ">=6.9.0" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/preset-env": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/preset-react": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", + "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", "dev": true }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dependencies": { - "has-flag": "^4.0.0" + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@bitcoinerlab/descriptors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/descriptors/-/descriptors-1.1.1.tgz", + "integrity": "sha512-AMFkbBBg9T1iWtEmWB23oADk7zaOQix6wUPLXalhTyFDjhkFXDd6pCRfto/HAdaPg/ccM4GMTVgYLee9WdYFyQ==", "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "@bitcoinerlab/miniscript": "^1.2.1", + "@bitcoinerlab/secp256k1": "^1.0.5", + "bip32": "^4.0.0", + "bitcoinjs-lib": "^6.1.3", + "ecpair": "^2.1.0" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "peerDependencies": { + "ledger-bitcoin": "^0.2.2" + }, + "peerDependenciesMeta": { + "ledger-bitcoin": { + "optional": true + } } }, - "node_modules/@jest/source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/@bitcoinerlab/miniscript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/miniscript/-/miniscript-1.4.0.tgz", + "integrity": "sha512-BsG3dmwQmgKHnRZecDgUsPjwcpnf1wgaZbolcMTByS10k1zYzIx97W51LzG7GvokRJ+wnzTX/GhC8Y3L2X0CQA==", + "dependencies": { + "bip68": "^1.0.4" + } + }, + "node_modules/@bitcoinerlab/secp256k1": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.0.5.tgz", + "integrity": "sha512-8gT+ukTCFN2rTxn4hD9Jq3k+UJwcprgYjfK/SQUSLgznXoIgsBnlPuARMkyyuEjycQK9VvnPiejKdszVTflh+w==", + "dependencies": { + "@noble/hashes": "^1.1.5", + "@noble/secp256k1": "^1.7.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10.0.0" } }, - "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, - "dependencies": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=0.10.0" } }, - "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@emotion/memoize": "^0.8.1" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", + "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "react": ">=16.8.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" } }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@jest/transform/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@jest/transform/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "type-fest": "^0.20.2" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/types": { + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", + "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "dependencies": { + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", + "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "dependencies": { + "@floating-ui/core": "^1.4.1", + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/types": "^27.5.1", "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { + "node_modules/@jest/console/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -1735,7 +2401,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/types/node_modules/chalk": { + "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -1751,7 +2417,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/types/node_modules/color-convert": { + "node_modules/@jest/console/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -1763,13 +2429,13 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/types/node_modules/color-name": { + "node_modules/@jest/console/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/types/node_modules/has-flag": { + "node_modules/@jest/console/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -1778,7 +2444,7 @@ "node": ">=8" } }, - "node_modules/@jest/types/node_modules/supports-color": { + "node_modules/@jest/console/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -1790,661 +2456,709 @@ "node": ">=8" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "engines": { - "node": ">=6.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@ledgerhq/devices": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.0.5.tgz", - "integrity": "sha512-Cy4LOfcYhYGWLd2nRA/CY/AneJT+Q3RyNwzoRx28gqAN21vF3+IZtL0jqs1n78rZ2bTEHyBS1GMOX13s5Y+O4g==", - "dependencies": { - "@ledgerhq/errors": "^6.13.0", - "@ledgerhq/logs": "^6.10.1", - "rxjs": "6", - "semver": "^7.3.5" + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@ledgerhq/devices/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@ledgerhq/devices/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" }, "engines": { - "node": ">=10" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@ledgerhq/devices/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/@ledgerhq/errors": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.13.0.tgz", - "integrity": "sha512-cMFNX2AN6Gdj4RVIizI/7vWb+JYRu5na0rQSjybf7xGW5MSVdFVRcOg90VvqnDRsNfgFBbJzhpf7o4D7S3yFgg==" - }, - "node_modules/@ledgerhq/hw-transport": { - "version": "6.28.6", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.28.6.tgz", - "integrity": "sha512-0VVB4jIG6ZTRtHusI5kO2jPcc1yFQ+iIcNKiTaaBHytsdGjTfhipje+W4vxo+nCdOKdrkOqB80GwykmKuNNXyA==", + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, "dependencies": { - "@ledgerhq/devices": "^8.0.5", - "@ledgerhq/errors": "^6.13.0", - "events": "^3.3.0" + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "6.27.17", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.27.17.tgz", - "integrity": "sha512-HRh3PWwAHqfuibAif15H2X5ZbH8nNisDX49IxBoexBz/fM5ivP95kZZQsXLxzPxey5ima49B7AjWY3LyGBytqA==", + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, "dependencies": { - "@ledgerhq/devices": "^8.0.5", - "@ledgerhq/errors": "^6.13.0", - "@ledgerhq/hw-transport": "^6.28.6", - "@ledgerhq/logs": "^6.10.1" + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@ledgerhq/logs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.10.1.tgz", - "integrity": "sha512-z+ILK8Q3y+nfUl43ctCPuR4Y2bIxk/ooCQFwZxhtci1EhAtMDzMAx2W25qx8G1PPL9UUOdnUax19+F0OjXoj4w==" - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, "dependencies": { - "@noble/hashes": "1.3.2" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 16" + "node": ">=8" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 16" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 8" + "node": ">=7.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@phosphor-icons/react": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.0.10.tgz", - "integrity": "sha512-q5ITPNFhmEiYZLZOvEhjo2phlfxoOmit7vE1tBYMxcMqnZX2vdbMw3deDE7wCegpBKM/q/p39BJmhhoPcjZyCg==", - "engines": { - "node": ">=10" + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" }, - "peerDependencies": { - "react": ">= 16.8", - "react-dom": ">= 16.8" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", - "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "node_modules/@jest/source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", "dev": true, "dependencies": { - "ansi-html-community": "^0.0.8", - "common-path-prefix": "^3.0.0", - "core-js-pure": "^3.23.3", - "error-stack-parser": "^2.0.6", - "find-up": "^5.0.0", - "html-entities": "^2.1.0", - "loader-utils": "^2.0.4", - "schema-utils": "^3.0.0", - "source-map": "^0.7.3" + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">= 10.13" - }, - "peerDependencies": { - "@types/webpack": "4.x || 5.x", - "react-refresh": ">=0.10.0 <1.0.0", - "sockjs-client": "^1.4.0", - "type-fest": ">=0.17.0 <4.0.0", - "webpack": ">=4.43.0 <6.0.0", - "webpack-dev-server": "3.x || 4.x", - "webpack-hot-middleware": "2.x", - "webpack-plugin-serve": "0.x || 1.x" - }, - "peerDependenciesMeta": { - "@types/webpack": { - "optional": true - }, - "sockjs-client": { - "optional": true - }, - "type-fest": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - }, - "webpack-hot-middleware": { - "optional": true - }, - "webpack-plugin-serve": { - "optional": true - } + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@rc-component/portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", - "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" }, "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@react-spring/animated": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", - "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, "dependencies": { - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@react-spring/core": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", - "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@react-spring/animated": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "color-convert": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/react-spring/donate" + "engines": { + "node": ">=8" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@react-spring/shared": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", - "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@react-spring/types": "~9.7.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@react-spring/types": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", - "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" - }, - "node_modules/@react-spring/web": { - "version": "9.7.3", - "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", - "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@react-spring/animated": "~9.7.3", - "@react-spring/core": "~9.7.3", - "@react-spring/shared": "~9.7.3", - "@react-spring/types": "~9.7.3" + "color-name": "~1.1.4" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@remix-run/router": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", - "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==", + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=8" } }, - "node_modules/@scure/base": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", - "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@jest/transform/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=8" } }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "engines": { - "node": ">= 16" + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@scure/btc-signer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.1.0.tgz", - "integrity": "sha512-kCX7WaaTJr0VZIXDvaY0wNZfzZoZuLnPz4G0qmKXN8bnNx5M86wb1cce9XrZcfzb0jrVAbZJqNpxmE1e7Ka2hA==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.3", - "micro-packed": "~0.3.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@secretkeylabs/xverse-core": { - "version": "1.9.1", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.9.1/ea80ed9482e6a537cf26af36718dbcd56d55010c", - "integrity": "sha512-zAyst55gv5CrY9cWfMQYRIjDJn91Se89CgMPPOGjThoCQVOI7h/oX9JvVAZMVNEPZJwJvVpIdwpJ6kuPhc7U9Q==", - "license": "ISC", + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@bitcoinerlab/secp256k1": "^1.0.2", - "@noble/secp256k1": "^1.7.1", - "@scure/base": "^1.1.1", - "@scure/btc-signer": "1.1.0", - "@stacks/auth": "^6.5.1", - "@stacks/encryption": "6.1.1", - "@stacks/network": "4.3.5", - "@stacks/storage": "^6.0.0", - "@stacks/transactions": "4.3.5", - "@stacks/wallet-sdk": "^5.0.2", - "@zondax/ledger-stacks": "^1.0.4", - "axios": "0.27.2", - "base64url": "^3.0.1", - "bip32": "^4.0.0", - "bip39": "3.0.3", - "bitcoin-address-validation": "^2.2.1", - "bitcoinjs-lib": "^6.1.3", - "bitcoinjs-message": "^2.2.0", - "bn.js": "^5.1.3", - "bs58check": "^3.0.1", - "buffer": "6.0.3", - "c32check": "^2.0.0", - "ecdsa-sig-formatter": "^1.0.11", - "ecpair": "^2.1.0", - "jsontokens": "^4.0.1", - "ledger-bitcoin": "^0.2.1", - "process": "^0.11.10", - "util": "^0.12.4", - "uuidv4": "^6.2.13", - "varuint-bitcoin": "^1.1.2" + "color-name": "~1.1.4" }, - "peerDependencies": { - "bignumber.js": "^9.0.0", - "react": ">18.0.0" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@scure/bip39": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", - "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.1.1", - "@scure/base": "~1.1.0" + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/encryption": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.1.1.tgz", - "integrity": "sha512-tS0Foo83h1ixwxCAbFh3uX0Hty3b3EFcqOb62udgBFlDmsjBD9Pld8t+ApKLTwiad6YhRu6rW+hDAJmhYQToMw==", + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@scure/bip39": "1.1.0", - "@stacks/common": "^6.0.0", - "@types/node": "^18.0.4", - "base64-js": "^1.5.1", - "bs58": "^5.0.0", - "ripemd160-min": "^0.0.6", - "varuint-bitcoin": "^1.1.2" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/network": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", - "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dependencies": { - "@stacks/common": "^4.3.5", - "cross-fetch": "^3.1.5" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/network/node_modules/@stacks/common": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", - "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4", - "buffer": "^6.0.3" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.5.tgz", - "integrity": "sha512-tTkuVlIfpD6QKF0vHoJvUZ2h3Ua82l4HhxzzVs3ZKr5M9WYULZQo1RMaMloJLgUMxsexDZ1Mib6ADiXgBefrBQ==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@stacks/common": "^4.3.5", - "@stacks/network": "^4.3.5", - "@types/node": "^18.0.4", - "@types/sha.js": "^2.4.0", - "c32check": "^1.1.3", - "lodash.clonedeep": "^4.5.0", - "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "smart-buffer": "^4.1.0" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/@stacks/common": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", - "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4", - "buffer": "^6.0.3" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/c32check": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", - "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@ledgerhq/devices": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.0.5.tgz", + "integrity": "sha512-Cy4LOfcYhYGWLd2nRA/CY/AneJT+Q3RyNwzoRx28gqAN21vF3+IZtL0jqs1n78rZ2bTEHyBS1GMOX13s5Y+O4g==", "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.6.0", - "cross-sha256": "^1.2.0" - }, - "engines": { - "node": ">=8" + "@ledgerhq/errors": "^6.13.0", + "@ledgerhq/logs": "^6.10.1", + "rxjs": "6", + "semver": "^7.3.5" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/c32check/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@ledgerhq/devices/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "node_modules/@ledgerhq/devices/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/@ledgerhq/devices/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@ledgerhq/errors": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.13.0.tgz", + "integrity": "sha512-cMFNX2AN6Gdj4RVIizI/7vWb+JYRu5na0rQSjybf7xGW5MSVdFVRcOg90VvqnDRsNfgFBbJzhpf7o4D7S3yFgg==" + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "6.28.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.28.6.tgz", + "integrity": "sha512-0VVB4jIG6ZTRtHusI5kO2jPcc1yFQ+iIcNKiTaaBHytsdGjTfhipje+W4vxo+nCdOKdrkOqB80GwykmKuNNXyA==", "dependencies": { - "safe-buffer": "^5.0.1" + "@ledgerhq/devices": "^8.0.5", + "@ledgerhq/errors": "^6.13.0", + "events": "^3.3.0" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/bip39": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.3.tgz", - "integrity": "sha512-P0dKrz4g0V0BjXfx7d9QNkJ/Txcz/k+hM9TnjqjUaXtuOfAvxXSw2rJw8DX0e3ZPwnK/IgDxoRqf0bvoVCqbMg==", + "node_modules/@ledgerhq/hw-transport-webusb": { + "version": "6.27.17", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.27.17.tgz", + "integrity": "sha512-HRh3PWwAHqfuibAif15H2X5ZbH8nNisDX49IxBoexBz/fM5ivP95kZZQsXLxzPxey5ima49B7AjWY3LyGBytqA==", "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" + "@ledgerhq/devices": "^8.0.5", + "@ledgerhq/errors": "^6.13.0", + "@ledgerhq/hw-transport": "^6.28.6", + "@ledgerhq/logs": "^6.10.1" } }, - "node_modules/@secretkeylabs/xverse-core/node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + "node_modules/@ledgerhq/logs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.10.1.tgz", + "integrity": "sha512-z+ILK8Q3y+nfUl43ctCPuR4Y2bIxk/ooCQFwZxhtci1EhAtMDzMAx2W25qx8G1PPL9UUOdnUax19+F0OjXoj4w==" }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dev": true, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dependencies": { - "type-detect": "4.0.8" + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/auth": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", - "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", - "dependencies": { - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", - "@stacks/profile": "^6.7.0", - "cross-fetch": "^3.1.5", - "jsontokens": "^4.0.1" + "node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/auth/node_modules/@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", "funding": [ { "type": "individual", @@ -2452,328 +3166,289 @@ } ] }, - "node_modules/@stacks/auth/node_modules/@scure/bip39": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", - "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { - "@noble/hashes": "~1.1.1", - "@scure/base": "~1.1.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@stacks/auth/node_modules/@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", - "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", - "@types/node": "^18.0.4", - "base64-js": "^1.5.1", - "bs58": "^5.0.0", - "ripemd160-min": "^0.0.6", - "varuint-bitcoin": "^1.1.2" + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" } }, - "node_modules/@stacks/common": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.5.tgz", - "integrity": "sha512-6v2AVHTTryvl1Govu5rmBXLywAyen2fU3doMCx/7Lk/tFLc4OjMEx4uf1wzpPx1zw/fwJnvoz74OrT/RSALDYw==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "node_modules/@stacks/connect": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/@stacks/connect/-/connect-6.10.2.tgz", - "integrity": "sha512-rixsMWhSIMGS8ClUgfNKA7PLV4ikr7SpjFUcVuKCmEsrRMnDdcvuhiY87hLPiatD0W6qMWZVR+BaIbHIgvp9aQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "dependencies": { - "@stacks/auth": "4.3.2", - "@stacks/connect-ui": "5.5.4", - "@stacks/network": "4.3.2", - "@stacks/prettier-config": "0.0.8", - "@stacks/transactions": "4.3.2", - "bn.js": "^5.2.0", - "buffer": "6.0.3", - "jsontokens": "3.1.1", - "readable-stream": "^3.6.0", - "url": "^0.11.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@stacks/connect-ui": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/@stacks/connect-ui/-/connect-ui-5.5.4.tgz", - "integrity": "sha512-xstC05PoxpPeA2HWytkJp/NJBtDEPDUoHuUyyvpuqS7f95rsHyx/tLFWv9ElxWiIbeMPPDEQipoy6S1qnZb8jw==", - "dependencies": { - "@stencil/core": "^2.17.1" + "node_modules/@phosphor-icons/react": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.0.10.tgz", + "integrity": "sha512-q5ITPNFhmEiYZLZOvEhjo2phlfxoOmit7vE1tBYMxcMqnZX2vdbMw3deDE7wCegpBKM/q/p39BJmhhoPcjZyCg==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">= 16.8", + "react-dom": ">= 16.8" } }, - "node_modules/@stacks/connect/node_modules/@stacks/auth": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-4.3.2.tgz", - "integrity": "sha512-8Ttq5dMmgVNUyaYR2q5pr3cIIiNHtD8HiVyB+Sui25T047twuWRKC5ZsxN6W28SPlLTGXKu/AFuDKoZDC6sAvQ==", + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", + "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "dev": true, "dependencies": { - "@stacks/common": "^4.3.2", - "@stacks/encryption": "^4.3.2", - "@stacks/network": "^4.3.2", - "@stacks/profile": "^4.3.2", - "cross-fetch": "^3.1.5", - "jsontokens": "^3.1.1", - "query-string": "^6.13.1" + "ansi-html-community": "^0.0.8", + "common-path-prefix": "^3.0.0", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "find-up": "^5.0.0", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^3.0.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <4.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } } }, - "node_modules/@stacks/connect/node_modules/@stacks/common": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", - "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4", - "buffer": "^6.0.3" + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/@stacks/connect/node_modules/@stacks/network": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.2.tgz", - "integrity": "sha512-8QgsGjAHwRwCDIzbE+nmqD2Kk589svmDLHNm1PJWL5EGpZyJK5su/y36ZgmTMVDvQwNfr9/8GFoaAbBlArvZyw==", + "node_modules/@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", "dependencies": { - "@stacks/common": "^4.3.2", - "cross-fetch": "^3.1.5" + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@stacks/connect/node_modules/@stacks/profile": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-4.3.8.tgz", - "integrity": "sha512-aXe/O9u2O0aAslzlcERc+JV3ZAQ75/FSO3l/5TGz+le0vZ6gqoflP6lCI1t3kPy0l6vnZjIUnwUDFR6JOmAHrQ==", + "node_modules/@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", "dependencies": { - "@stacks/common": "^4.3.5", - "@stacks/network": "^4.3.5", - "@stacks/transactions": "^4.3.8", - "jsontokens": "^3.1.1", - "schema-inspector": "2.0.1", - "zone-file": "^2.0.0-beta.3" + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@stacks/connect/node_modules/@stacks/profile/node_modules/@stacks/network": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", - "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", + "node_modules/@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", "dependencies": { - "@stacks/common": "^4.3.5", - "cross-fetch": "^3.1.5" + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@stacks/connect/node_modules/@stacks/profile/node_modules/@stacks/transactions": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", - "integrity": "sha512-5xYYv2TdXXM9PVixB79Pr99symQ8fhbVATjempGUxtL23/XUiRiLvJZohDxIE4VQ2EzbB4g4j8Y7oqPjj0h09Q==", - "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@stacks/common": "^4.3.5", - "@stacks/network": "^4.3.5", - "@types/node": "^18.0.4", - "@types/sha.js": "^2.4.0", - "c32check": "^1.1.3", - "lodash.clonedeep": "^4.5.0", - "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "smart-buffer": "^4.1.0" - } + "node_modules/@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" }, - "node_modules/@stacks/connect/node_modules/@stacks/transactions": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.2.tgz", - "integrity": "sha512-DzTVVCC4GQNI58asdshatv8f5zAuNKRtNbWEjs75HAmaD7x6qz73pC+BDaZwJHBBH1A3Hp8d5HC2LKlv7ymDlQ==", + "node_modules/@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@stacks/common": "^4.3.2", - "@stacks/network": "^4.3.2", - "@types/node": "^14.14.43", - "@types/sha.js": "^2.4.0", - "c32check": "^1.1.3", - "lodash.clonedeep": "^4.5.0", - "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "smart-buffer": "^4.1.0" + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@stacks/connect/node_modules/@stacks/transactions/node_modules/@types/node": { - "version": "14.18.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", - "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" - }, - "node_modules/@stacks/connect/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" + "node_modules/@remix-run/router": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", + "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==", + "engines": { + "node": ">=14" } }, - "node_modules/@stacks/connect/node_modules/c32check": { + "node_modules/@scure/base": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", - "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.6.0", - "cross-sha256": "^1.2.0" - }, - "engines": { - "node": ">=8" + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", + "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/connect/node_modules/c32check/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/@stacks/connect/node_modules/jsontokens": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/jsontokens/-/jsontokens-3.1.1.tgz", - "integrity": "sha512-qABuRXXrDP1XQrUm0/59h3kEBWtbyk/lS24t98iHvuAq7gyNA2lxqSQgATsbx8DzbMfOJmkmfjwLodd96lD/kw==", - "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "base64url": "^3.0.1", - "ecdsa-sig-formatter": "^1.0.11" - } - }, - "node_modules/@stacks/connect/node_modules/schema-inspector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.1.tgz", - "integrity": "sha512-lqR4tOVfoqf9Z8cgX/zvXuWPnTWCqrc4WSgeSPDDc1bWbMABaqdSTY98xj7iRKHOIRtKjc4M8EWCgUu5ASlHkg==", - "dependencies": { - "async": "~2.6.3" - } - }, - "node_modules/@stacks/encryption": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-4.3.5.tgz", - "integrity": "sha512-s7fPwGLHQc/4SMFq7W75wt5xNqUJcciDkyxSEA30I+ukFSjLlZnmxI91ElWD15MRq/oKNHBlS0URF0N37dEe1A==", - "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@scure/bip39": "^1.1.0", - "@stacks/common": "^4.3.5", - "@types/node": "^18.0.4", - "bs58": "^5.0.0", - "ripemd160-min": "^0.0.6", - "varuint-bitcoin": "^1.1.2" - } - }, - "node_modules/@stacks/encryption/node_modules/@stacks/common": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", - "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "node_modules/@scure/bip32": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4", - "buffer": "^6.0.3" + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/network": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.5.tgz", - "integrity": "sha512-lw7+g6UhOpvWasMeRYMb2OGRKm9ptYkGt27Usg3Eo0z/pu20jZxvHXLBMdDQqxNQOOmwiG4FadICnwTlmnHaqw==", - "dependencies": { - "@stacks/common": "^6.5.5", - "cross-fetch": "^3.1.5" + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/prettier-config": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.8.tgz", - "integrity": "sha512-WpxCIB2wPk2TT0Zs9oABNQ7Y2wBx2sSqEeFtgJ1lBNY6bKT5B82l/CkbaHPmnUj0KOwauXaSv0rXnxomTNj9xA==", + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", "dependencies": { - "prettier": "^2.3.0" + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/profile": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", - "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", + "node_modules/@scure/btc-signer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.1.0.tgz", + "integrity": "sha512-kCX7WaaTJr0VZIXDvaY0wNZfzZoZuLnPz4G0qmKXN8bnNx5M86wb1cce9XrZcfzb0jrVAbZJqNpxmE1e7Ka2hA==", "dependencies": { - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", - "@stacks/transactions": "^6.7.0", - "jsontokens": "^4.0.1", - "schema-inspector": "^2.0.2", - "zone-file": "^2.0.0-beta.3" + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.3", + "micro-packed": "~0.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@stacks/profile/node_modules/@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@stacks/profile/node_modules/@stacks/transactions": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", - "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", + "node_modules/@secretkeylabs/xverse-core": { + "version": "2.3.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/2.3.0/024dea2b4f44fb6cc84c7125b8adf381f8f2791d", + "integrity": "sha512-zE/C/e1ri551rVLJTNnJRDfLcXujOtdfTnW6nanIrEAjmNQxXH1DAploudDkRMDnG9JQBHrFnuW9JpeAGR4Y+g==", + "license": "ISC", "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", + "@bitcoinerlab/secp256k1": "^1.0.2", + "@noble/secp256k1": "^1.7.1", + "@scure/base": "^1.1.1", + "@scure/btc-signer": "1.1.0", + "@stacks/auth": "^6.5.1", + "@stacks/encryption": "6.1.1", + "@stacks/network": "4.3.5", + "@stacks/storage": "^6.0.0", + "@stacks/transactions": "4.3.5", + "@stacks/wallet-sdk": "^5.0.2", + "@zondax/ledger-stacks": "^1.0.4", + "axios": "0.27.2", + "base64url": "^3.0.1", + "bip32": "^4.0.0", + "bip39": "3.0.3", + "bitcoin-address-validation": "^2.2.1", + "bitcoinjs-lib": "^6.1.3", + "bitcoinjs-message": "^2.2.0", + "bn.js": "^5.1.3", + "bs58check": "^3.0.1", + "buffer": "6.0.3", "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" - } - }, - "node_modules/@stacks/stacks-blockchain-api-types": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-6.3.4.tgz", - "integrity": "sha512-zrjKPGJN4p1azzmh8j0Yj+ZjQ0L9F01qJjAxOtBpapmFbGr1NUuPT1GthIg76y+dobdjSDPN39LpoJG/FbWFLw==" - }, - "node_modules/@stacks/storage": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", - "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", - "dependencies": { - "@stacks/auth": "^6.7.0", - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", - "base64-js": "^1.5.1", - "jsontokens": "^4.0.1" + "ecdsa-sig-formatter": "^1.0.11", + "ecpair": "^2.1.0", + "jsontokens": "^4.0.1", + "ledger-bitcoin": "^0.2.1", + "process": "^0.11.10", + "util": "^0.12.4", + "uuidv4": "^6.2.13", + "varuint-bitcoin": "^1.1.2" + }, + "peerDependencies": { + "bignumber.js": "^9.0.0", + "react": ">18.0.0" } }, - "node_modules/@stacks/storage/node_modules/@noble/hashes": { + "node_modules/@secretkeylabs/xverse-core/node_modules/@noble/hashes": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", @@ -2784,7 +3459,7 @@ } ] }, - "node_modules/@stacks/storage/node_modules/@scure/bip39": { + "node_modules/@secretkeylabs/xverse-core/node_modules/@scure/bip39": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", @@ -2799,15 +3474,15 @@ "@scure/base": "~1.1.0" } }, - "node_modules/@stacks/storage/node_modules/@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/encryption": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.1.1.tgz", + "integrity": "sha512-tS0Foo83h1ixwxCAbFh3uX0Hty3b3EFcqOb62udgBFlDmsjBD9Pld8t+ApKLTwiad6YhRu6rW+hDAJmhYQToMw==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.0.0", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", @@ -2815,10 +3490,29 @@ "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@stacks/transactions": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", - "integrity": "sha512-5xYYv2TdXXM9PVixB79Pr99symQ8fhbVATjempGUxtL23/XUiRiLvJZohDxIE4VQ2EzbB4g4j8Y7oqPjj0h09Q==", + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/network": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", + "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", + "dependencies": { + "@stacks/common": "^4.3.5", + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/network/node_modules/@stacks/common": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", + "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4", + "buffer": "^6.0.3" + } + }, + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.5.tgz", + "integrity": "sha512-tTkuVlIfpD6QKF0vHoJvUZ2h3Ua82l4HhxzzVs3ZKr5M9WYULZQo1RMaMloJLgUMxsexDZ1Mib6ADiXgBefrBQ==", "dependencies": { "@noble/hashes": "^1.0.0", "@noble/secp256k1": "^1.5.5", @@ -2833,7 +3527,7 @@ "smart-buffer": "^4.1.0" } }, - "node_modules/@stacks/transactions/node_modules/@stacks/common": { + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/@stacks/common": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", @@ -2843,37 +3537,20 @@ "buffer": "^6.0.3" } }, - "node_modules/@stacks/transactions/node_modules/@stacks/network": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", - "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/c32check": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", + "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", "dependencies": { - "@stacks/common": "^4.3.5", - "cross-fetch": "^3.1.5" + "base-x": "^3.0.8", + "buffer": "^5.6.0", + "cross-sha256": "^1.2.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@stacks/transactions/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/@stacks/transactions/node_modules/c32check": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", - "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.6.0", - "cross-sha256": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@stacks/transactions/node_modules/c32check/node_modules/buffer": { + "node_modules/@secretkeylabs/xverse-core/node_modules/@stacks/transactions/node_modules/c32check/node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", @@ -2896,60 +3573,105 @@ "ieee754": "^1.1.13" } }, - "node_modules/@stacks/wallet-sdk": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/wallet-sdk/-/wallet-sdk-5.0.3.tgz", - "integrity": "sha512-9Alqqer8cauLLEuhSA3ryPTfCw3XZiZkZBbyed9+oNsha3beIBly5lspU2GHdz2alnsJ5jisjDUZeuDYVRFEuA==", + "node_modules/@secretkeylabs/xverse-core/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { - "@scure/bip32": "^1.1.0", - "@scure/bip39": "^1.1.0", - "@stacks/auth": "^5.0.3", - "@stacks/common": "^5.0.3", - "@stacks/encryption": "^5.0.3", - "@stacks/network": "^5.0.3", - "@stacks/profile": "^5.0.3", - "@stacks/storage": "^5.0.3", - "@stacks/transactions": "^5.0.3", - "bitcoinjs-lib": "^5.2.0", - "buffer": "^6.0.3", - "c32check": "^2.0.0", - "jsontokens": "^4.0.1", - "triplesec": "^4.0.3", - "zone-file": "^2.0.0-beta.3" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/auth": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-5.0.3.tgz", - "integrity": "sha512-bFP/H1IFAxU2FUu3KR0meUgXdmagkpjV9wAC7b5UDCVHWanU3c/GfCh0CIw10FbXov2aYlQJpCEFMBxweATVjg==", + "node_modules/@secretkeylabs/xverse-core/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dependencies": { - "@stacks/common": "^5.0.3", - "@stacks/encryption": "^5.0.3", - "@stacks/network": "^5.0.3", - "@stacks/profile": "^5.0.3", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@secretkeylabs/xverse-core/node_modules/bip39": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.3.tgz", + "integrity": "sha512-P0dKrz4g0V0BjXfx7d9QNkJ/Txcz/k+hM9TnjqjUaXtuOfAvxXSw2rJw8DX0e3ZPwnK/IgDxoRqf0bvoVCqbMg==", + "dependencies": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } + }, + "node_modules/@secretkeylabs/xverse-core/node_modules/bip39/node_modules/@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@stacks/auth": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", + "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", + "dependencies": { + "@stacks/common": "^6.5.5", + "@stacks/encryption": "^6.7.0", + "@stacks/network": "^6.5.5", + "@stacks/profile": "^6.7.0", "cross-fetch": "^3.1.5", - "jsontokens": "^4.0.1", - "query-string": "^6.13.1" + "jsontokens": "^4.0.1" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/common": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-5.0.3.tgz", - "integrity": "sha512-0c1L1xQAFI4p0oB8BrwU1ic3q91plceztzT6ZQizxWfAJFnELdYyO/nJlq9a3yIVV90iaLYgvYBTPW3b7LWrdg==", + "node_modules/@stacks/auth/node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@stacks/auth/node_modules/@scure/bip39": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", + "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" + "@noble/hashes": "~1.1.1", + "@scure/base": "~1.1.0" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/encryption": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-5.0.3.tgz", - "integrity": "sha512-wM5wE2ldssJWF5zrE5MbGlBSqI6ZMDSWGtvg2AOqOG2ChoBPxcuVOdyj4ziBbX4vtdu61jjr7LLP+90/0MLcpQ==", + "node_modules/@stacks/auth/node_modules/@stacks/encryption": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@scure/bip39": "^1.1.0", - "@stacks/common": "^5.0.3", + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@scure/bip39": "1.1.0", + "@stacks/common": "^6.5.5", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", @@ -2957,2943 +3679,2769 @@ "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/network": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-5.0.3.tgz", - "integrity": "sha512-9ZSKktElpgDst1SVI5K4ocmsrIKrIHVQMRTfLkVarNqMnk9zliLMXrmXef6Z3rszU7JbUWGbb8+F3ubhpfqZxg==", + "node_modules/@stacks/common": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.5.tgz", + "integrity": "sha512-6v2AVHTTryvl1Govu5rmBXLywAyen2fU3doMCx/7Lk/tFLc4OjMEx4uf1wzpPx1zw/fwJnvoz74OrT/RSALDYw==", "dependencies": { - "@stacks/common": "^5.0.3", - "cross-fetch": "^3.1.5" + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/profile": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-5.0.3.tgz", - "integrity": "sha512-B+gAMK8svDrgFWGJu2EkokkgjkXUEJG+zsZuK3P1Aq2qCS2EiO+O0gLhUi8p38BiKEpkUVY4mI34QCzMn9zWiA==", + "node_modules/@stacks/connect": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@stacks/connect/-/connect-6.10.2.tgz", + "integrity": "sha512-rixsMWhSIMGS8ClUgfNKA7PLV4ikr7SpjFUcVuKCmEsrRMnDdcvuhiY87hLPiatD0W6qMWZVR+BaIbHIgvp9aQ==", "dependencies": { - "@stacks/common": "^5.0.3", - "@stacks/network": "^5.0.3", - "@stacks/transactions": "^5.0.3", - "jsontokens": "^4.0.1", - "schema-inspector": "2.0.1", - "zone-file": "^2.0.0-beta.3" + "@stacks/auth": "4.3.2", + "@stacks/connect-ui": "5.5.4", + "@stacks/network": "4.3.2", + "@stacks/prettier-config": "0.0.8", + "@stacks/transactions": "4.3.2", + "bn.js": "^5.2.0", + "buffer": "6.0.3", + "jsontokens": "3.1.1", + "readable-stream": "^3.6.0", + "url": "^0.11.0" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/storage": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-5.0.3.tgz", - "integrity": "sha512-5JuQ5rUjXNtx3hhiUGWp5KTuGg4pvxXmYnro6u+3Bl6kN8Q5ZMwf0b5fWwCoRvxIPSPuMTsp9P+tlb9N/cWNVA==", + "node_modules/@stacks/connect-ui": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/@stacks/connect-ui/-/connect-ui-5.5.4.tgz", + "integrity": "sha512-xstC05PoxpPeA2HWytkJp/NJBtDEPDUoHuUyyvpuqS7f95rsHyx/tLFWv9ElxWiIbeMPPDEQipoy6S1qnZb8jw==", "dependencies": { - "@stacks/auth": "^5.0.3", - "@stacks/common": "^5.0.3", - "@stacks/encryption": "^5.0.3", - "@stacks/network": "^5.0.3", - "base64-js": "^1.5.1", - "jsontokens": "^4.0.1" + "@stencil/core": "^2.17.1" } }, - "node_modules/@stacks/wallet-sdk/node_modules/@stacks/transactions": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-5.0.3.tgz", - "integrity": "sha512-rLe7QYU+tzTs1Yudo82zh7oiWAwGxGiunFehgIZ6VgLgo/Oarf8+DWmmaAxSZpCsecxl4cuQxE3bDWwJZAA9rg==", + "node_modules/@stacks/connect/node_modules/@stacks/auth": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-4.3.2.tgz", + "integrity": "sha512-8Ttq5dMmgVNUyaYR2q5pr3cIIiNHtD8HiVyB+Sui25T047twuWRKC5ZsxN6W28SPlLTGXKu/AFuDKoZDC6sAvQ==", "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@stacks/common": "^5.0.3", - "@stacks/network": "^5.0.3", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" + "@stacks/common": "^4.3.2", + "@stacks/encryption": "^4.3.2", + "@stacks/network": "^4.3.2", + "@stacks/profile": "^4.3.2", + "cross-fetch": "^3.1.5", + "jsontokens": "^3.1.1", + "query-string": "^6.13.1" } }, - "node_modules/@stacks/wallet-sdk/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/@stacks/connect/node_modules/@stacks/common": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", + "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", "dependencies": { - "safe-buffer": "^5.0.1" + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4", + "buffer": "^6.0.3" } }, - "node_modules/@stacks/wallet-sdk/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@stacks/wallet-sdk/node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "node_modules/@stacks/connect/node_modules/@stacks/network": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.2.tgz", + "integrity": "sha512-8QgsGjAHwRwCDIzbE+nmqD2Kk589svmDLHNm1PJWL5EGpZyJK5su/y36ZgmTMVDvQwNfr9/8GFoaAbBlArvZyw==", "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" + "@stacks/common": "^4.3.2", + "cross-fetch": "^3.1.5" } }, - "node_modules/@stacks/wallet-sdk/node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + "node_modules/@stacks/connect/node_modules/@stacks/profile": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-4.3.8.tgz", + "integrity": "sha512-aXe/O9u2O0aAslzlcERc+JV3ZAQ75/FSO3l/5TGz+le0vZ6gqoflP6lCI1t3kPy0l6vnZjIUnwUDFR6JOmAHrQ==", + "dependencies": { + "@stacks/common": "^4.3.5", + "@stacks/network": "^4.3.5", + "@stacks/transactions": "^4.3.8", + "jsontokens": "^3.1.1", + "schema-inspector": "2.0.1", + "zone-file": "^2.0.0-beta.3" + } }, - "node_modules/@stacks/wallet-sdk/node_modules/bitcoinjs-lib": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz", - "integrity": "sha512-5DcLxGUDejgNBYcieMIUfjORtUeNWl828VWLHJGVKZCb4zIS1oOySTUr0LGmcqJBQgTBz3bGbRQla4FgrdQEIQ==", + "node_modules/@stacks/connect/node_modules/@stacks/profile/node_modules/@stacks/network": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", + "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", "dependencies": { - "bech32": "^1.1.2", - "bip174": "^2.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" - }, - "engines": { - "node": ">=8.0.0" + "@stacks/common": "^4.3.5", + "cross-fetch": "^3.1.5" } }, - "node_modules/@stacks/wallet-sdk/node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "node_modules/@stacks/connect/node_modules/@stacks/profile/node_modules/@stacks/transactions": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", + "integrity": "sha512-5xYYv2TdXXM9PVixB79Pr99symQ8fhbVATjempGUxtL23/XUiRiLvJZohDxIE4VQ2EzbB4g4j8Y7oqPjj0h09Q==", "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@stacks/common": "^4.3.5", + "@stacks/network": "^4.3.5", + "@types/node": "^18.0.4", + "@types/sha.js": "^2.4.0", + "c32check": "^1.1.3", + "lodash.clonedeep": "^4.5.0", + "ripemd160-min": "^0.0.6", + "sha.js": "^2.4.11", + "smart-buffer": "^4.1.0" } }, - "node_modules/@stacks/wallet-sdk/node_modules/bs58check/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "node_modules/@stacks/connect/node_modules/@stacks/transactions": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.2.tgz", + "integrity": "sha512-DzTVVCC4GQNI58asdshatv8f5zAuNKRtNbWEjs75HAmaD7x6qz73pC+BDaZwJHBBH1A3Hp8d5HC2LKlv7ymDlQ==", "dependencies": { - "base-x": "^3.0.2" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@stacks/common": "^4.3.2", + "@stacks/network": "^4.3.2", + "@types/node": "^14.14.43", + "@types/sha.js": "^2.4.0", + "c32check": "^1.1.3", + "lodash.clonedeep": "^4.5.0", + "ripemd160-min": "^0.0.6", + "sha.js": "^2.4.11", + "smart-buffer": "^4.1.0" } }, - "node_modules/@stacks/wallet-sdk/node_modules/schema-inspector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.1.tgz", - "integrity": "sha512-lqR4tOVfoqf9Z8cgX/zvXuWPnTWCqrc4WSgeSPDDc1bWbMABaqdSTY98xj7iRKHOIRtKjc4M8EWCgUu5ASlHkg==", + "node_modules/@stacks/connect/node_modules/@stacks/transactions/node_modules/@types/node": { + "version": "14.18.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz", + "integrity": "sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==" + }, + "node_modules/@stacks/connect/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dependencies": { - "async": "~2.6.3" + "safe-buffer": "^5.0.1" } }, - "node_modules/@stencil/core": { - "version": "2.22.3", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.22.3.tgz", - "integrity": "sha512-kmVA0M/HojwsfkeHsifvHVIYe4l5tin7J5+DLgtl8h6WWfiMClND5K3ifCXXI2ETDNKiEk21p6jql3Fx9o2rng==", - "bin": { - "stencil": "bin/stencil" + "node_modules/@stacks/connect/node_modules/c32check": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", + "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.6.0", + "cross-sha256": "^1.2.0" }, "engines": { - "node": ">=12.10.0", - "npm": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@tanstack/eslint-plugin-query": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-4.32.1.tgz", - "integrity": "sha512-29oveq5n7momN+/d0SheNccnp1qws4JRG/PdeiPHwWAVQ9HxwtZTFxhFJxvMzVk7UsY3LsQB0keIajC+K9ZJ7w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "node_modules/@stacks/connect/node_modules/c32check/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/@tanstack/match-sorter-utils": { - "version": "8.8.4", - "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz", - "integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==", + "node_modules/@stacks/connect/node_modules/jsontokens": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/jsontokens/-/jsontokens-3.1.1.tgz", + "integrity": "sha512-qABuRXXrDP1XQrUm0/59h3kEBWtbyk/lS24t98iHvuAq7gyNA2lxqSQgATsbx8DzbMfOJmkmfjwLodd96lD/kw==", "dependencies": { - "remove-accents": "0.4.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kentcdodds" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "base64url": "^3.0.1", + "ecdsa-sig-formatter": "^1.0.11" } }, - "node_modules/@tanstack/query-core": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.32.1.tgz", - "integrity": "sha512-VEAGHboOFWN/bvf/7cCoeLQfld0AA8n0V/kfc77W+FvxnnSwJufEh6gfjqpX5bRE/DEYfYDYdNtuL3KM+lIs8Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "node_modules/@stacks/connect/node_modules/schema-inspector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.1.tgz", + "integrity": "sha512-lqR4tOVfoqf9Z8cgX/zvXuWPnTWCqrc4WSgeSPDDc1bWbMABaqdSTY98xj7iRKHOIRtKjc4M8EWCgUu5ASlHkg==", + "dependencies": { + "async": "~2.6.3" } }, - "node_modules/@tanstack/query-persist-client-core": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.32.1.tgz", - "integrity": "sha512-KgnkNigmOMi2aikxdhCRe0MaAh1Dq94/nNjmcSxfflj9L3v4F9tEQAig/F7m2+jethP1AiIYBax5nN4aqm7NFg==", + "node_modules/@stacks/encryption": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-4.3.5.tgz", + "integrity": "sha512-s7fPwGLHQc/4SMFq7W75wt5xNqUJcciDkyxSEA30I+ukFSjLlZnmxI91ElWD15MRq/oKNHBlS0URF0N37dEe1A==", "dependencies": { - "@tanstack/query-core": "4.32.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@scure/bip39": "^1.1.0", + "@stacks/common": "^4.3.5", + "@types/node": "^18.0.4", + "bs58": "^5.0.0", + "ripemd160-min": "^0.0.6", + "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@tanstack/query-sync-storage-persister": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-4.32.1.tgz", - "integrity": "sha512-kqE+L0uSzVMuPpY8iKtnyZexsZ5IxsJbgiI4s+m+FB8Dzn+5go3snpZIYMQu36S+sWy0N90P2xNR57EOaFMlsg==", + "node_modules/@stacks/encryption/node_modules/@stacks/common": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", + "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", "dependencies": { - "@tanstack/query-persist-client-core": "4.32.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4", + "buffer": "^6.0.3" } }, - "node_modules/@tanstack/react-query": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.32.1.tgz", - "integrity": "sha512-lPTfOq6bR6DorPaS018gTMd3zs8r06tlERiVY6BRP9SnDkkl4ckqeANava/jPLWrSZP+EA15loQUTmvZs6k2GA==", + "node_modules/@stacks/network": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.5.tgz", + "integrity": "sha512-lw7+g6UhOpvWasMeRYMb2OGRKm9ptYkGt27Usg3Eo0z/pu20jZxvHXLBMdDQqxNQOOmwiG4FadICnwTlmnHaqw==", "dependencies": { - "@tanstack/query-core": "4.32.1", - "use-sync-external-store": "^1.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-native": "*" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "@stacks/common": "^6.5.5", + "cross-fetch": "^3.1.5" } }, - "node_modules/@tanstack/react-query-devtools": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.32.1.tgz", - "integrity": "sha512-/ZgxCfGXLIXUvaIRzrNCP+C4iv1bIleNzXCjGKFZ4qKEifnv5A/SpWE2dG4SBjqXVlIkMAP82lesfoHcsOm+zg==", + "node_modules/@stacks/prettier-config": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.8.tgz", + "integrity": "sha512-WpxCIB2wPk2TT0Zs9oABNQ7Y2wBx2sSqEeFtgJ1lBNY6bKT5B82l/CkbaHPmnUj0KOwauXaSv0rXnxomTNj9xA==", "dependencies": { - "@tanstack/match-sorter-utils": "^8.7.0", - "superjson": "^1.10.0", - "use-sync-external-store": "^1.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "@tanstack/react-query": "4.32.1", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "prettier": "^2.3.0" } }, - "node_modules/@tanstack/react-query-persist-client": { - "version": "4.32.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.32.1.tgz", - "integrity": "sha512-HtfhSOyMSjdASpPXWBWv9JquUk5b8HjOwbFVmtA8xIDFQm9qS35PikXO2YbBXhuz/LEknRhct/M3PMI/XkRQSg==", + "node_modules/@stacks/profile": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", + "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", "dependencies": { - "@tanstack/query-persist-client-core": "4.32.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "@tanstack/react-query": "4.32.1" + "@stacks/common": "^6.5.5", + "@stacks/network": "^6.5.5", + "@stacks/transactions": "^6.7.0", + "jsontokens": "^4.0.1", + "schema-inspector": "^2.0.2", + "zone-file": "^2.0.0-beta.3" } }, - "node_modules/@testing-library/dom": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", - "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", - "peer": true, + "node_modules/@stacks/profile/node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@stacks/profile/node_modules/@stacks/transactions": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", + "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@stacks/common": "^6.5.5", + "@stacks/network": "^6.5.5", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" } }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, + "node_modules/@stacks/stacks-blockchain-api-types": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-6.1.1.tgz", + "integrity": "sha512-Mw5dBPx3DySPupwaq0iBdm1WdEVXIfhjUVaTjI2iSyzWz4Fgs3U7JCaAezLbgNu7Q69c/ZN4JUDWuo9FVjy7oA==" + }, + "node_modules/@stacks/storage": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", + "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@stacks/auth": "^6.7.0", + "@stacks/common": "^6.5.5", + "@stacks/encryption": "^6.7.0", + "@stacks/network": "^6.5.5", + "base64-js": "^1.5.1", + "jsontokens": "^4.0.1" } }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, + "node_modules/@stacks/storage/node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@stacks/storage/node_modules/@scure/bip39": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", + "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@noble/hashes": "~1.1.1", + "@scure/base": "~1.1.0" } }, - "node_modules/@testing-library/dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, + "node_modules/@stacks/storage/node_modules/@stacks/encryption": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", + "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@scure/bip39": "1.1.0", + "@stacks/common": "^6.5.5", + "@types/node": "^18.0.4", + "base64-js": "^1.5.1", + "bs58": "^5.0.0", + "ripemd160-min": "^0.0.6", + "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@testing-library/dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true + "node_modules/@stacks/transactions": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", + "integrity": "sha512-5xYYv2TdXXM9PVixB79Pr99symQ8fhbVATjempGUxtL23/XUiRiLvJZohDxIE4VQ2EzbB4g4j8Y7oqPjj0h09Q==", + "dependencies": { + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@stacks/common": "^4.3.5", + "@stacks/network": "^4.3.5", + "@types/node": "^18.0.4", + "@types/sha.js": "^2.4.0", + "c32check": "^1.1.3", + "lodash.clonedeep": "^4.5.0", + "ripemd160-min": "^0.0.6", + "sha.js": "^2.4.11", + "smart-buffer": "^4.1.0" + } }, - "node_modules/@testing-library/dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, - "engines": { - "node": ">=8" + "node_modules/@stacks/transactions/node_modules/@stacks/common": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-4.3.5.tgz", + "integrity": "sha512-UuViiQ7fn3vdtTe3739aRzbl+wbukekeQuXgqt8d7nB2HC2HodD7GcHhpUga165cO35CD6lQUtj3vXxJb5Ga+A==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4", + "buffer": "^6.0.3" } }, - "node_modules/@testing-library/dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, + "node_modules/@stacks/transactions/node_modules/@stacks/network": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-4.3.5.tgz", + "integrity": "sha512-TC4+AkuT6qi3MoEGxTftA+4BNp99QvGnI+qtKQkoA1m0KDr8b9hSBUhugJHRhQbWuo7D6q0+JagYEGxLID29Kw==", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@stacks/common": "^4.3.5", + "cross-fetch": "^3.1.5" } }, - "node_modules/@testing-library/jest-dom": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", - "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "node_modules/@stacks/transactions/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=8", - "npm": ">=6", - "yarn": ">=1" + "safe-buffer": "^5.0.1" } }, - "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@stacks/transactions/node_modules/c32check": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", + "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", "dependencies": { - "color-convert": "^2.0.1" + "base-x": "^3.0.8", + "buffer": "^5.6.0", + "cross-sha256": "^1.2.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" + "node_modules/@stacks/transactions/node_modules/c32check/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/@testing-library/jest-dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@stacks/wallet-sdk": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/wallet-sdk/-/wallet-sdk-5.0.3.tgz", + "integrity": "sha512-9Alqqer8cauLLEuhSA3ryPTfCw3XZiZkZBbyed9+oNsha3beIBly5lspU2GHdz2alnsJ5jisjDUZeuDYVRFEuA==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@scure/bip32": "^1.1.0", + "@scure/bip39": "^1.1.0", + "@stacks/auth": "^5.0.3", + "@stacks/common": "^5.0.3", + "@stacks/encryption": "^5.0.3", + "@stacks/network": "^5.0.3", + "@stacks/profile": "^5.0.3", + "@stacks/storage": "^5.0.3", + "@stacks/transactions": "^5.0.3", + "bitcoinjs-lib": "^5.2.0", + "buffer": "^6.0.3", + "c32check": "^2.0.0", + "jsontokens": "^4.0.1", + "triplesec": "^4.0.3", + "zone-file": "^2.0.0-beta.3" } }, - "node_modules/@testing-library/jest-dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/auth": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-5.0.3.tgz", + "integrity": "sha512-bFP/H1IFAxU2FUu3KR0meUgXdmagkpjV9wAC7b5UDCVHWanU3c/GfCh0CIw10FbXov2aYlQJpCEFMBxweATVjg==", + "dependencies": { + "@stacks/common": "^5.0.3", + "@stacks/encryption": "^5.0.3", + "@stacks/network": "^5.0.3", + "@stacks/profile": "^5.0.3", + "cross-fetch": "^3.1.5", + "jsontokens": "^4.0.1", + "query-string": "^6.13.1" + } }, - "node_modules/@testing-library/jest-dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/common": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-5.0.3.tgz", + "integrity": "sha512-0c1L1xQAFI4p0oB8BrwU1ic3q91plceztzT6ZQizxWfAJFnELdYyO/nJlq9a3yIVV90iaLYgvYBTPW3b7LWrdg==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" } }, - "node_modules/@testing-library/jest-dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/encryption": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-5.0.3.tgz", + "integrity": "sha512-wM5wE2ldssJWF5zrE5MbGlBSqI6ZMDSWGtvg2AOqOG2ChoBPxcuVOdyj4ziBbX4vtdu61jjr7LLP+90/0MLcpQ==", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@scure/bip39": "^1.1.0", + "@stacks/common": "^5.0.3", + "@types/node": "^18.0.4", + "base64-js": "^1.5.1", + "bs58": "^5.0.0", + "ripemd160-min": "^0.0.6", + "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@testing-library/react": { - "version": "13.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", - "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/network": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-5.0.3.tgz", + "integrity": "sha512-9ZSKktElpgDst1SVI5K4ocmsrIKrIHVQMRTfLkVarNqMnk9zliLMXrmXef6Z3rszU7JbUWGbb8+F3ubhpfqZxg==", "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.5.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@stacks/common": "^5.0.3", + "cross-fetch": "^3.1.5" } }, - "node_modules/@testing-library/react/node_modules/@testing-library/dom": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", - "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/profile": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-5.0.3.tgz", + "integrity": "sha512-B+gAMK8svDrgFWGJu2EkokkgjkXUEJG+zsZuK3P1Aq2qCS2EiO+O0gLhUi8p38BiKEpkUVY4mI34QCzMn9zWiA==", "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" + "@stacks/common": "^5.0.3", + "@stacks/network": "^5.0.3", + "@stacks/transactions": "^5.0.3", + "jsontokens": "^4.0.1", + "schema-inspector": "2.0.1", + "zone-file": "^2.0.0-beta.3" } }, - "node_modules/@testing-library/react/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/storage": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-5.0.3.tgz", + "integrity": "sha512-5JuQ5rUjXNtx3hhiUGWp5KTuGg4pvxXmYnro6u+3Bl6kN8Q5ZMwf0b5fWwCoRvxIPSPuMTsp9P+tlb9N/cWNVA==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@stacks/auth": "^5.0.3", + "@stacks/common": "^5.0.3", + "@stacks/encryption": "^5.0.3", + "@stacks/network": "^5.0.3", + "base64-js": "^1.5.1", + "jsontokens": "^4.0.1" } }, - "node_modules/@testing-library/react/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@stacks/wallet-sdk/node_modules/@stacks/transactions": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-5.0.3.tgz", + "integrity": "sha512-rLe7QYU+tzTs1Yudo82zh7oiWAwGxGiunFehgIZ6VgLgo/Oarf8+DWmmaAxSZpCsecxl4cuQxE3bDWwJZAA9rg==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@noble/hashes": "^1.0.0", + "@noble/secp256k1": "^1.5.5", + "@stacks/common": "^5.0.3", + "@stacks/network": "^5.0.3", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" } }, - "node_modules/@testing-library/react/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@stacks/wallet-sdk/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "safe-buffer": "^5.0.1" } }, - "node_modules/@testing-library/react/node_modules/color-name": { + "node_modules/@stacks/wallet-sdk/node_modules/bech32": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/@testing-library/react/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, - "node_modules/@testing-library/react/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@stacks/wallet-sdk/node_modules/bip32": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", + "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", "dependencies": { - "has-flag": "^4.0.0" + "@types/node": "10.12.18", + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "tiny-secp256k1": "^1.1.3", + "typeforce": "^1.11.5", + "wif": "^2.0.6" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/@testing-library/user-event": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", - "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } + "node_modules/@stacks/wallet-sdk/node_modules/bip32/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, + "node_modules/@stacks/wallet-sdk/node_modules/bitcoinjs-lib": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz", + "integrity": "sha512-5DcLxGUDejgNBYcieMIUfjORtUeNWl828VWLHJGVKZCb4zIS1oOySTUr0LGmcqJBQgTBz3bGbRQla4FgrdQEIQ==", + "dependencies": { + "bech32": "^1.1.2", + "bip174": "^2.0.1", + "bip32": "^2.0.4", + "bip66": "^1.1.0", + "bitcoin-ops": "^1.4.0", + "bs58check": "^2.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.3", + "merkle-lib": "^2.0.10", + "pushdata-bitcoin": "^1.0.1", + "randombytes": "^2.0.1", + "tiny-secp256k1": "^1.1.1", + "typeforce": "^1.11.3", + "varuint-bitcoin": "^1.0.4", + "wif": "^2.0.1" + }, "engines": { - "node": ">= 6" + "node": ">=8.0.0" } }, - "node_modules/@types/argon2-browser": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/@types/argon2-browser/-/argon2-browser-1.18.1.tgz", - "integrity": "sha512-PZffP/CqH9m2kovDSRQMfMMxUC3V98I7i7/caa0RB0/nvsXzYbL9bKyqZpNMFmLFGZslROlG1R60ONt7abrwlA==", - "dev": true - }, - "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" - }, - "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, + "node_modules/@stacks/wallet-sdk/node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, + "node_modules/@stacks/wallet-sdk/node_modules/bs58check/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", "dependencies": { - "@babel/types": "^7.0.0" + "base-x": "^3.0.2" } }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, + "node_modules/@stacks/wallet-sdk/node_modules/schema-inspector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.1.tgz", + "integrity": "sha512-lqR4tOVfoqf9Z8cgX/zvXuWPnTWCqrc4WSgeSPDDc1bWbMABaqdSTY98xj7iRKHOIRtKjc4M8EWCgUu5ASlHkg==", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "async": "~2.6.3" } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "node_modules/@stencil/core": { + "version": "2.22.3", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.22.3.tgz", + "integrity": "sha512-kmVA0M/HojwsfkeHsifvHVIYe4l5tin7J5+DLgtl8h6WWfiMClND5K3ifCXXI2ETDNKiEk21p6jql3Fx9o2rng==", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=12.10.0", + "npm": ">=6.0.0" + } + }, + "node_modules/@tanstack/eslint-plugin-query": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-4.32.1.tgz", + "integrity": "sha512-29oveq5n7momN+/d0SheNccnp1qws4JRG/PdeiPHwWAVQ9HxwtZTFxhFJxvMzVk7UsY3LsQB0keIajC+K9ZJ7w==", "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "node_modules/@tanstack/match-sorter-utils": { + "version": "8.8.4", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz", + "integrity": "sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==", "dependencies": { - "@types/node": "*" + "remove-accents": "0.4.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kentcdodds" } }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "node_modules/@tanstack/query-core": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.32.1.tgz", + "integrity": "sha512-VEAGHboOFWN/bvf/7cCoeLQfld0AA8n0V/kfc77W+FvxnnSwJufEh6gfjqpX5bRE/DEYfYDYdNtuL3KM+lIs8Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, + "node_modules/@tanstack/query-persist-client-core": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.32.1.tgz", + "integrity": "sha512-KgnkNigmOMi2aikxdhCRe0MaAh1Dq94/nNjmcSxfflj9L3v4F9tEQAig/F7m2+jethP1AiIYBax5nN4aqm7NFg==", "dependencies": { - "@types/node": "*" + "@tanstack/query-core": "4.32.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@types/chrome": { - "version": "0.0.237", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.237.tgz", - "integrity": "sha512-krsRmyfMlck5r+H1EapsrrucDRq6iRm0NAi5fapr93CgnpVMDdK+h2+z4x79GegdW7BNH9Vb//gkptORwwwVIQ==", - "dev": true, + "node_modules/@tanstack/query-sync-storage-persister": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-4.32.1.tgz", + "integrity": "sha512-kqE+L0uSzVMuPpY8iKtnyZexsZ5IxsJbgiI4s+m+FB8Dzn+5go3snpZIYMQu36S+sWy0N90P2xNR57EOaFMlsg==", "dependencies": { - "@types/filesystem": "*", - "@types/har-format": "*" + "@tanstack/query-persist-client-core": "4.32.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.32.1.tgz", + "integrity": "sha512-lPTfOq6bR6DorPaS018gTMd3zs8r06tlERiVY6BRP9SnDkkl4ckqeANava/jPLWrSZP+EA15loQUTmvZs6k2GA==", "dependencies": { - "@types/node": "*" + "@tanstack/query-core": "4.32.1", + "use-sync-external-store": "^1.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", - "dev": true, + "node_modules/@tanstack/react-query-devtools": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.32.1.tgz", + "integrity": "sha512-/ZgxCfGXLIXUvaIRzrNCP+C4iv1bIleNzXCjGKFZ4qKEifnv5A/SpWE2dG4SBjqXVlIkMAP82lesfoHcsOm+zg==", "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "@tanstack/match-sorter-utils": "^8.7.0", + "superjson": "^1.10.0", + "use-sync-external-store": "^1.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "4.32.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@types/eslint": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.1.tgz", - "integrity": "sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==", - "dev": true, + "node_modules/@tanstack/react-query-persist-client": { + "version": "4.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.32.1.tgz", + "integrity": "sha512-HtfhSOyMSjdASpPXWBWv9JquUk5b8HjOwbFVmtA8xIDFQm9qS35PikXO2YbBXhuz/LEknRhct/M3PMI/XkRQSg==", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@tanstack/query-persist-client-core": "4.32.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "4.32.1" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, + "node_modules/@testing-library/dom": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", + "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", + "peer": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/filesystem": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", - "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", - "dev": true, - "dependencies": { - "@types/filewriter": "*" - } - }, - "node_modules/@types/filewriter": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", - "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==", - "dev": true - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, "dependencies": { - "@types/node": "*" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/har-format": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.11.tgz", - "integrity": "sha512-T232/TneofqK30AD1LRrrf8KnjLvzrjWDp7eWST5KoiSzrBfRsLrWDPk4STQPW4NZG6v2MltnduBVmakbZOBIQ==", - "dev": true - }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { + "node_modules/@testing-library/dom/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.11", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", - "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "27.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", - "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.17.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", - "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==" + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true }, - "node_modules/@types/parse-json": { + "node_modules/@testing-library/dom/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz", - "integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.2.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", - "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", - "dependencies": { - "@types/react": "*" + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-modal": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz", - "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==", - "dev": true, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, "dependencies": { - "@types/react": "*" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-redux": { - "version": "7.1.25", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", - "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", "dependencies": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", - "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@types/react": "*" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/redux-state-sync": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/redux-state-sync/-/redux-state-sync-3.1.5.tgz", - "integrity": "sha512-NtcV94bmZNFMmcjgYzjK9WHN/0NVHyH4OO/a4sAd4WG1ywcVZA5vdczjPQZLC1IVMRBi693b3FWsWB7wELL+tg==", - "dev": true, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dependencies": { - "broadcast-channel": "^2.1.8", - "redux": "^4.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } }, - "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", - "dev": true, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", "dependencies": { - "@types/express": "*" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", - "dev": true, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", + "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/sha.js": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/sha.js/-/sha.js-2.4.1.tgz", - "integrity": "sha512-QHWKOJ4dkWB0OCfCoOFUZkhvpqUllcPs2WIhYFk7ugAprv3ts0z4nSuHtc0jlWBYLdPwfNRpVpv9pIpFSbYBYQ==", + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@types/node": "*" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, + "node_modules/@testing-library/react/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@types/node": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/stack-utils": { + "node_modules/@testing-library/react/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "node_modules/@types/styled-components": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", - "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", - "dev": true, + "node_modules/@testing-library/react/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@testing-library/react/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "@types/hoist-non-react-statics": "*", - "@types/react": "*", - "csstype": "^3.0.2" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.9", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", - "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "node_modules/@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", "dependencies": { - "@types/jest": "*" + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } }, - "node_modules/@types/webextension-polyfill": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.9.2.tgz", - "integrity": "sha512-op8YeoK60K6/GIx3snWs3JowBZ+/aeSnZzZuuwynA7VARWfzr3st9aQNk9RWfoBx5xqlNZjAsh2QttPUZnabCw==", + "node_modules/@types/argon2-browser": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@types/argon2-browser/-/argon2-browser-1.18.1.tgz", + "integrity": "sha512-PZffP/CqH9m2kovDSRQMfMMxUC3V98I7i7/caa0RB0/nvsXzYbL9bKyqZpNMFmLFGZslROlG1R60ONt7abrwlA==", "dev": true }, - "node_modules/@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "node_modules/@types/aria-query": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", + "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", "dev": true, "dependencies": { - "@types/node": "*" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "@babel/types": "^7.0.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@types/zxcvbn": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.1.tgz", - "integrity": "sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "node_modules/@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@babel/types": "^7.20.7" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "@types/node": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@types/node": "*" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "node_modules/@types/chrome": { + "version": "0.0.237", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.237.tgz", + "integrity": "sha512-krsRmyfMlck5r+H1EapsrrucDRq6iRm0NAi5fapr93CgnpVMDdK+h2+z4x79GegdW7BNH9Vb//gkptORwwwVIQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/filesystem": "*", + "@types/har-format": "*" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "dependencies": { + "@types/node": "*" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/express-serve-static-core": "*", + "@types/node": "*" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@types/eslint": { + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.1.tgz", + "integrity": "sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "@types/eslint": "*", + "@types/estree": "*" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", "dev": true }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@types/filesystem": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "@types/filewriter": "*" } }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@types/filewriter": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", + "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==", "dev": true }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@types/minimatch": "*", + "@types/node": "*" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@types/node": "*" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "node_modules/@types/har-format": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.11.tgz", + "integrity": "sha512-T232/TneofqK30AD1LRrrf8KnjLvzrjWDp7eWST5KoiSzrBfRsLrWDPk4STQPW4NZG6v2MltnduBVmakbZOBIQ==", "dev": true }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", "dev": true }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", "dev": true }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@types/node": "*" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@types/istanbul-lib-report": "*" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, + "node_modules/@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", "dependencies": { - "@xtuc/long": "4.2.2" + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", + "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz", + "integrity": "sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, + "node_modules/@types/react-dom": { + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", + "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@types/react": "*" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "node_modules/@types/react-modal": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz", + "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "@types/react": "*" } }, - "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", - "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", - "dev": true, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" + "node_modules/@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" } }, - "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", - "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", - "dev": true, + "node_modules/@types/react-transition-group": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz", + "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==", "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" + "@types/react": "*" } }, - "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", - "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", + "node_modules/@types/redux-state-sync": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/redux-state-sync/-/redux-state-sync-3.1.5.tgz", + "integrity": "sha512-NtcV94bmZNFMmcjgYzjK9WHN/0NVHyH4OO/a4sAd4WG1ywcVZA5vdczjPQZLC1IVMRBi693b3FWsWB7wELL+tg==", "dev": true, - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } + "dependencies": { + "broadcast-channel": "^2.1.8", + "redux": "^4.0.1" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, - "node_modules/@zondax/ledger-stacks": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@zondax/ledger-stacks/-/ledger-stacks-1.0.4.tgz", - "integrity": "sha512-R8CB0CZ2poTzpcG0jhzzXZvXF7axIsmZFhp06aHCUjgz+1df63YbC4tUzyzmseekwqNWnaebWFejQKJ99WiHZA==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "@ledgerhq/hw-transport": "^6.28.1", - "@stacks/transactions": "^4.1.0", - "varuint-bitcoin": "^1.1.2" - } + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", "dev": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "@types/express": "*" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", "dev": true, "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" } }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "node_modules/@types/sha.js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/sha.js/-/sha.js-2.4.1.tgz", + "integrity": "sha512-QHWKOJ4dkWB0OCfCoOFUZkhvpqUllcPs2WIhYFk7ugAprv3ts0z4nSuHtc0jlWBYLdPwfNRpVpv9pIpFSbYBYQ==", + "dependencies": { + "@types/node": "*" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", "dev": true, - "peerDependencies": { - "acorn": "^8" + "dependencies": { + "@types/node": "*" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/styled-components": { + "version": "5.1.26", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", + "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dependencies": { + "@types/jest": "*" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + }, + "node_modules/@types/webextension-polyfill": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.9.2.tgz", + "integrity": "sha512-op8YeoK60K6/GIx3snWs3JowBZ+/aeSnZzZuuwynA7VARWfzr3st9aQNk9RWfoBx5xqlNZjAsh2QttPUZnabCw==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", "dev": true, "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" + "@types/node": "*" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@types/yargs-parser": "*" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@types/zxcvbn": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.1.tgz", + "integrity": "sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "ajv": "^8.0.0" + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "ajv": { + "typescript": { "optional": true } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "yallist": "^4.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=10" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/alex-sdk": { - "version": "0.1.18", - "resolved": "https://registry.npmjs.org/alex-sdk/-/alex-sdk-0.1.18.tgz", - "integrity": "sha512-TEBlO9Xiw/LRBZMM98o6eUqZv6q/qlkDOHQACc0kFGCdqfspcVhE1X83vMVpZYbjKlXnko6mFW6bi+RyMx2L3g==", "dependencies": { - "clarity-codegen": "^0.2.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" - }, - "peerDependencies": { - "@stacks/network": "*", - "@stacks/transactions": "*" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, - "engines": { - "node": ">=4" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/argon2-browser": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz", - "integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", - "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "engines": { + "node": ">=10" } }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "dependencies": { - "dequal": "^2.0.3" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, - "node_modules/babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true }, - "node_modules/babel-code-frame/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true }, - "node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true }, - "node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" } }, - "node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, - "node_modules/babel-code-frame/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "engines": { - "node": ">=0.8.0" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, - "node_modules/babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "node_modules/babel-core/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "dependencies": { - "ms": "2.0.0" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/babel-core/node_modules/json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "@xtuc/long": "4.2.2" } }, - "node_modules/babel-core/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, - "node_modules/babel-core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, - "node_modules/babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "dependencies": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/babel-generator/node_modules/jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, - "node_modules/babel-generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, - "node_modules/babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "dependencies": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" } }, - "node_modules/babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha512-02I9jDjnVEuGy2BR3LRm9nPRb/+Ja0pvZVLr1eI5TYAA/dB0Xoc+WBo50+aDfhGDLhlBY1+QURjn9uvcFd8gzg==", + "node_modules/@webpack-cli/configtest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" } }, - "node_modules/babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==", + "node_modules/@webpack-cli/info": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", "dev": true, "dependencies": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" } }, - "node_modules/babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==", + "node_modules/@webpack-cli/serve": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } } }, - "node_modules/babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==", - "dev": true, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@zondax/ledger-stacks": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@zondax/ledger-stacks/-/ledger-stacks-1.0.4.tgz", + "integrity": "sha512-R8CB0CZ2poTzpcG0jhzzXZvXF7axIsmZFhp06aHCUjgz+1df63YbC4tUzyzmseekwqNWnaebWFejQKJ99WiHZA==", "dependencies": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "@babel/runtime": "^7.12.5", + "@ledgerhq/hw-transport": "^6.28.1", + "@stacks/transactions": "^4.1.0", + "varuint-bitcoin": "^1.1.2" } }, - "node_modules/babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==", + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "dependencies": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==", + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==", + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" } }, - "node_modules/babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==", + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==", + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==", + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true, - "dependencies": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==", + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "node": ">=8" } }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "ajv": "^8.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/babel-loader": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", - "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", - "dev": true, + "node_modules/alex-sdk": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/alex-sdk/-/alex-sdk-0.1.18.tgz", + "integrity": "sha512-TEBlO9Xiw/LRBZMM98o6eUqZv6q/qlkDOHQACc0kFGCdqfspcVhE1X83vMVpZYbjKlXnko6mFW6bi+RyMx2L3g==", "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "clarity-codegen": "^0.2.0" }, "engines": { - "node": ">= 8.9" + "node": ">=10" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" + "@stacks/network": "*", + "@stacks/transactions": "*" } }, - "node_modules/babel-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "type-fest": "^0.21.3" }, "engines": { - "node": ">= 8.9.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==", + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": ">=4" } }, - "node_modules/babel-plugin-styled-components": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", - "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "lodash": "^4.17.21", - "picomatch": "^2.3.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "peerDependencies": { - "styled-components": ">= 2" + "engines": { + "node": ">= 8" } }, - "node_modules/babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==", - "dev": true + "node_modules/argon2-browser": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz", + "integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==" }, - "node_modules/babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha512-HbTDIoG1A1op7Tl/wIFQPULIBA61tsJ8Ntq2FAhLwuijrzosM/92kAfgU1Q3Kc7DH/cprJg5vDfuTY4QUL4rDA==", - "dev": true + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dependencies": { + "deep-equal": "^2.0.5" + } }, - "node_modules/babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", - "dev": true + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==", + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, - "node_modules/babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==", + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "dependencies": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==", + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", "dev": true, "dependencies": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==", + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "dependencies": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" } }, - "node_modules/babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==", - "dev": true, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dependencies": { - "babel-runtime": "^6.22.0" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==", + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "dependencies": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==", - "dev": true, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { - "babel-runtime": "^6.22.0" + "lodash": "^4.17.14" } }, - "node_modules/babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==", - "dev": true, - "dependencies": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "node_modules/axe-core": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", + "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dependencies": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==", + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", "dev": true, "dependencies": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "dequal": "^2.0.3" } }, - "node_modules/babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==", + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", "dev": true, - "dependencies": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==", + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", "dev": true, "dependencies": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==", + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==", + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==", + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==", - "dev": true, - "dependencies": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==", + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==", + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==", + "node_modules/babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", "dev": true, "dependencies": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" } }, - "node_modules/babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==", + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "dependencies": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha512-TxIM0ZWNw9oYsoTthL3lvAK3+eTujzktoXJg4ubGvICGbVuXVYv5hHv0XXpz8fbqlJaGYY4q5SVzaSmsg3t4Fg==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha512-QLYkLiZeeED2PKd4LuXGg5y9fCgPB5ohF8olWUuETE2ryHNRqqnXlEVP7RPuef89+HTfd3syptMGVHeoAu0Wig==", + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.22.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha512-s+q/Y2u2OgDPHRuod3t6zyLoV8pUHc64i/O7ZNgIOEdYTq+ChPeybcKBi/xk9VI60VriILzFPW+dUxAEbTxh2w==", - "dev": true, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dependencies": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" } }, - "node_modules/babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha512-Y3ZHP1nunv0U1+ysTNwLK39pabHj6cPVsfN4TRC7BDBfbgbyF4RifP5kd6LnbuMV9wcfedQMe7hn1fyKc7IzTQ==", + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", "dev": true, "dependencies": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha512-pcDNDsZ9q/6LJmujQ/OhjeoIlp5Nl546HJ2yiFIJK3mYpgNXhI5/S9mXfVxu5yqWAi7HdI7e/q6a9xtzwL69Vw==", + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "dependencies": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==", + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", "dev": true, "dependencies": { - "regenerator-transform": "^0.10.0" + "@babel/helper-define-polyfill-provider": "^0.4.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==", - "dev": true, + "node_modules/babel-plugin-styled-components": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", + "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", "dependencies": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" + }, + "peerDependencies": { + "styled-components": ">= 2" } }, "node_modules/babel-preset-current-node-syntax": { @@ -5919,75 +6467,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "dependencies": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "node_modules/babel-preset-env/node_modules/browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - }, - "bin": { - "browserslist": "cli.js" - } - }, - "node_modules/babel-preset-env/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha512-PQZFJXnM3d80Vq4O67OE6EMVKIw2Vmzy8UXovqulNogCtblWU8rzP7Sm5YgHiCg4uejUxzCkHfNXQ4Z6GI+Dhw==", - "dev": true, - "dependencies": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, "node_modules/babel-preset-jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", @@ -6004,135 +6483,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha512-phQe3bElbgF887UM0Dhz55d22ob8czTL1kbhZFwpCE6+R/X9kHktfwmx9JZb+bBSVRGphP5tZ9oWhVhlgjrX3Q==", - "dev": true, - "dependencies": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } - }, - "node_modules/babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==", - "dev": true, - "dependencies": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "dev": true, - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "node_modules/babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "node_modules/babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "node_modules/babel-traverse/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/babel-traverse/node_modules/globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-traverse/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "node_modules/babel-types/node_modules/to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true, - "bin": { - "babylon": "bin/babylon.js" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6567,25 +6917,28 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" } }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "funding": [ { "type": "opencollective", @@ -6601,10 +6954,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -6762,9 +7115,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001519", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz", - "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==", + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", "funding": [ { "type": "opencollective", @@ -7348,13 +7701,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "node_modules/core-js-compat": { + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", + "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==", "dev": true, - "hasInstallScript": true + "dependencies": { + "browserslist": "^4.22.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, "node_modules/core-js-pure": { "version": "3.32.0", @@ -7922,18 +8280,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==", - "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8211,9 +8557,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.482", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.482.tgz", - "integrity": "sha512-h+UqpfmEr1Qkk0zp7ej/jid7CXoq4m4QzW6wNTb0ELJ/BZCpA4wgUylBIMGCe621tnr4l5VmoHjdoSx2lbnNJA==" + "version": "1.4.572", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.572.tgz", + "integrity": "sha512-RlFobl4D3ieetbnR+2EpxdzFl9h0RAJkPK3pfiwMug2nhBin2ZCsGIAJWdpNniLz43sgXam/CgipOmvTA+rUiA==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -9773,15 +10119,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/goober": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.13.tgz", @@ -9836,27 +10173,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -9985,19 +10301,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -10506,15 +10809,6 @@ "node": ">= 0.10" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/ipaddr.js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", @@ -10646,25 +10940,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-fullwidth-code-point": { @@ -11260,15 +11542,6 @@ "node": ">=8" } }, - "node_modules/jest-circus/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-circus/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -11544,15 +11817,6 @@ "node": ">=8" } }, - "node_modules/jest-config/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12077,15 +12341,6 @@ "node": ">=8" } }, - "node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-message-util/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12230,15 +12485,6 @@ "node": ">=8" } }, - "node_modules/jest-resolve/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-resolve/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12463,15 +12709,6 @@ "node": ">=8" } }, - "node_modules/jest-runtime/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-runtime/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -13299,104 +13536,325 @@ "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.19", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.8.0", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.11.5" } }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { - "path-key": "^4.0.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.9.0" } }, - "node_modules/lint-staged/node_modules/onetime": { + "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "mimic-fn": "^4.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "node_modules/listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==" + }, + "node_modules/lodash.trimstart": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz", + "integrity": "sha512-b/+D6La8tU76L/61/aN0jULWHkT0EeJCmVstPBn/K9MtD2qBW83AsBNrr63dKuWYwVMO7ucv13QNO/Ek/2RKaQ==" + }, + "node_modules/lodash.words": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-4.2.0.tgz", + "integrity": "sha512-mXxqd8Yx9BGPij3lZKFSdOsjOTbL4krbCCp9slEozaN4EMppA2dFmK/f8HeohodprY6W0vOdiQ5WFgPaTI75xQ==" + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", "dev": true, "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" }, "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "node": ">=10" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/ansi-styles": { + "node_modules/log-update/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -13411,23 +13869,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/color-convert": { + "node_modules/log-update/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -13439,19 +13881,19 @@ "node": ">=7.0.0" } }, - "node_modules/listr2/node_modules/color-name": { + "node_modules/log-update/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/listr2/node_modules/emoji-regex": { + "node_modules/log-update/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -13460,955 +13902,1156 @@ "node": ">=8" } }, - "node_modules/listr2/node_modules/p-map": { + "node_modules/log-update/node_modules/slice-ansi": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" + "tmpl": "1.0.5" } }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "engines": { - "node": ">=6.11.5" + "node": ">= 0.6" } }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "fs-monkey": "^1.0.4" }, "engines": { - "node": ">=8.9.0" + "node": ">= 4.0.0" } }, - "node_modules/locate-path": { + "node_modules/memoize-one": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "errno": "^0.1.3", + "readable-stream": "^2.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.3.0 <5.0.0 || >=5.10" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "node_modules/memory-fs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + "node_modules/memory-fs/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "node_modules/memory-fs/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "node_modules/memory-fs/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "node_modules/lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==" + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } }, - "node_modules/lodash.trimstart": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz", - "integrity": "sha512-b/+D6La8tU76L/61/aN0jULWHkT0EeJCmVstPBn/K9MtD2qBW83AsBNrr63dKuWYwVMO7ucv13QNO/Ek/2RKaQ==" + "node_modules/merkle-lib": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", + "integrity": "sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA==" }, - "node_modules/lodash.words": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-4.2.0.tgz", - "integrity": "sha512-mXxqd8Yx9BGPij3lZKFSdOsjOTbL4krbCCp9slEozaN4EMppA2dFmK/f8HeohodprY6W0vOdiQ5WFgPaTI75xQ==" + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/micro-packed": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.3.2.tgz", + "integrity": "sha512-D1Bq0/lVOzdxhnX5vylCxZpdw5LylH7Vd81py0DfRsKUP36XYpwvy8ZIsECVo3UfnoROn8pdKqkOzL7Cd82sGA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@scure/base": "~1.1.1" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=10" + "node": ">=8.6" + } + }, + "node_modules/microseconds": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.1.0.tgz", + "integrity": "sha512-yF2K4aHXKxO4OGhW7Ek2KLgKEAFbSblBLKlF6KzwQUhjK7+uAzatRr6fZ82bftdnuDQrkBHAJp5s8quj1ME3wA==", + "dev": true + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "color-convert": "^2.0.1" + "mime-db": "1.52.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 0.6" } }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "color-name": "~1.1.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/mixpanel-browser": { + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz", + "integrity": "sha512-Ldrva0fRBEIFWmEibBQO1PulfpJVF3pf28Guk09lDirDaSQqqU/xs9zQLwN2rL5VwVtsP1aD3JaCgaa98EjojQ==" }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, + "node_modules/more-entropy": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/more-entropy/-/more-entropy-0.0.7.tgz", + "integrity": "sha512-e0TxQtU1F6/ZA8WnEA2JLQwwDqBTtZFLJSW7rWgUsQou35wx1IOL0g2O7q7oGoMgIJto+jHMnNGHLfSiylHRrw==", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "iced-runtime": ">=0.0.1" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" }, - "engines": { - "node": ">=8" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + }, + "node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "big-integer": "^1.6.16" + } + }, + "node_modules/nanoid": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", + "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" }, "engines": { - "node": ">=8" + "node": "^14 || ^16 || >=18" } }, - "node_modules/loose-envify": { + "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dev": true, "dependencies": { + "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "dependencies": { - "yallist": "^3.0.2" + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "bin": { - "lz-string": "bin/bin.js" + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6.13.0" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "fs-monkey": "^1.0.4" + "path-key": "^3.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=8" } }, - "node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" - }, - "node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/memory-fs/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", "dev": true }, - "node_modules/memory-fs/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/memory-fs/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/memory-fs/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dependencies": { - "safe-buffer": "~5.1.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "engines": { - "node": ">= 8" + "node": ">= 0.4" } }, - "node_modules/merkle-lib": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA==" - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micro-packed": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.3.2.tgz", - "integrity": "sha512-D1Bq0/lVOzdxhnX5vylCxZpdw5LylH7Vd81py0DfRsKUP36XYpwvy8ZIsECVo3UfnoROn8pdKqkOzL7Cd82sGA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, "dependencies": { - "@scure/base": "~1.1.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", "dev": true, "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { - "node": ">=8.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/microseconds": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.1.0.tgz", - "integrity": "sha512-yF2K4aHXKxO4OGhW7Ek2KLgKEAFbSblBLKlF6KzwQUhjK7+uAzatRr6fZ82bftdnuDQrkBHAJp5s8quj1ME3wA==", - "dev": true + "node_modules/object.groupby": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", + "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "get-intrinsic": "^1.2.1" + } }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, - "bin": { - "miller-rabin": "bin/miller-rabin" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, - "bin": { - "mime": "cli.js" + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } + "node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "engines": { - "node": ">=4" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "mimic-fn": "^2.1.0" }, "engines": { - "node": "*" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mixpanel-browser": { - "version": "2.47.0", - "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz", - "integrity": "sha512-Ldrva0fRBEIFWmEibBQO1PulfpJVF3pf28Guk09lDirDaSQqqU/xs9zQLwN2rL5VwVtsP1aD3JaCgaa98EjojQ==" - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { - "minimist": "^1.2.6" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { - "node": "*" + "node": ">= 0.8.0" } }, - "node_modules/more-entropy": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/more-entropy/-/more-entropy-0.0.7.tgz", - "integrity": "sha512-e0TxQtU1F6/ZA8WnEA2JLQwwDqBTtZFLJSW7rWgUsQou35wx1IOL0g2O7q7oGoMgIJto+jHMnNGHLfSiylHRrw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { - "iced-runtime": ">=0.0.1" + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" + "p-limit": "^3.0.2" }, - "bin": { - "multicast-dns": "cli.js" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "node_modules/p-queue": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.3.4.tgz", + "integrity": "sha512-esox8CWt0j9EZECFvkFl2WNPat8LN4t7WWeXq73D9ha0V96qPRufApZi4ZhPwXAln1uVVal429HVVKPa2X0yQg==", "dependencies": { - "big-integer": "^1.6.16" + "eventemitter3": "^4.0.7", + "p-timeout": "^5.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nanoid": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz", - "integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.js" + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=8" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { + "node_modules/param-case": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", "dev": true, "dependencies": { - "lower-case": "^2.0.2", + "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dependencies": { - "whatwg-url": "^5.0.0" + "callsites": "^3.0.0" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=6" } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { - "node": ">= 6.13.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", "dev": true, "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", "dev": true, "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "process": "^0.11.1", + "util": "^0.10.3" } }, - "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/path/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "inherits": "2.0.3" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" }, "engines": { - "node": ">= 0.4" + "node": ">=0.12" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10" } }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/object.groupby": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", - "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "get-intrinsic": "^1.2.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "pinkie": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "node_modules/oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { - "ee-first": "1.1.1" + "find-up": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { - "wrappy": "1" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "p-try": "^2.0.0" }, "engines": { "node": ">=6" @@ -14417,2646 +15060,2586 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">= 0.8.0" + "node": "^10 || ^12 || >=14" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "icss-utils": "^5.0.0" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/p-queue": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.3.4.tgz", - "integrity": "sha512-esox8CWt0j9EZECFvkFl2WNPat8LN4t7WWeXq73D9ha0V96qPRufApZi4ZhPwXAln1uVVal429HVVKPa2X0yQg==", - "dependencies": { - "eventemitter3": "^4.0.7", - "p-timeout": "^5.0.2" + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "bin": { + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=12" + "node": ">=10.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.0.0" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/prettier-plugin-organize-imports": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", + "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", "dev": true, - "engines": { - "node": ">=6" + "peerDependencies": { + "@volar/vue-language-plugin-pug": "^1.0.4", + "@volar/vue-typescript": "^1.0.4", + "prettier": ">=2.0", + "typescript": ">=2.9" + }, + "peerDependenciesMeta": { + "@volar/vue-language-plugin-pug": { + "optional": true + }, + "@volar/vue-typescript": { + "optional": true + } } }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", "dev": true, "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "lodash": "^4.17.20", + "renderkid": "^3.0.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dependencies": { - "callsites": "^3.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">=6" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/parse-json": { + "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==", "engines": { - "node": ">= 0.8" + "node": ">=0.4.0" } }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "dependencies": { - "process": "^0.11.1", - "util": "^0.10.3" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/path-is-absolute": { + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/prr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/path/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/path/node_modules/util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, + "node_modules/pushdata-bitcoin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", + "integrity": "sha512-hw7rcYTJRAl4olM8Owe8x0fBuJJ+WGbMhQuLWOXEMN3PxPCKQHRkhfL+XG0+iXUmSHjkMmb3Ba55Mt21cZc9kQ==", "dependencies": { - "inherits": "2.0.3" + "bitcoin-ops": "^1.3.0" } }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "node_modules/qr-code-styling": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.5.0.tgz", + "integrity": "sha512-7C+1cZGsZWH0BIRtv24faKZJwkxdYlynXktP9dDxKNSik2bqaUZck3B3MpQod/wqm9i3l4q7QsPGkRGKvcuqZw==", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" + "qrcode-generator": "^1.4.3" } }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, + "node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { - "node": ">=8.6" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" + "node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dependencies": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "engines": { - "node": ">=0.10.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "dev": true, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "engines": { - "node": ">= 6" + "node": ">= 0.6" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dev": true, "dependencies": { - "find-up": "^4.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "node_modules/rc-dialog": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.1.0.tgz", + "integrity": "sha512-5ry+JABAWEbaKyYsmITtrJbZbJys8CtMyzV8Xn4LYuXMeUx5XVHNyJRoqLFE4AzBuXXzOWeaC49cg+XkxK6kHA==", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "node_modules/rc-image": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.18.1.tgz", + "integrity": "sha512-xdr5zHpSJ6sGdV5oIkHWbttc21LlGKZZjWXVXxSS0sNmqSn97WzOKQBNrTA85UP7oBPPThZAGGGNmGnTkx2qYQ==", "dependencies": { - "p-limit": "^2.2.0" + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.1.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.0.6" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/rc-motion": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.7.3.tgz", + "integrity": "sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.21.0" }, - "engines": { - "node": "^10 || ^12 || >=14" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" + "node_modules/rc-util": { + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.35.0.tgz", + "integrity": "sha512-MTXlixb3EoSTEchsOc7XWsVyoUQqoCsh2Z1a2IptwNgqleMF6ZgQeY52UzUbNj5CcVBg9YljOWjuOV07jSSm4Q==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, + "node_modules/rc-util/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" + "loose-envify": "^1.1.0" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=0.10.0" + } + }, + "node_modules/react-content-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/react-content-loader/-/react-content-loader-6.2.1.tgz", + "integrity": "sha512-6ONbFX+Hi3SHuP66JB8CPvJn372pj+qwltJV0J8z/8MFrq98I1cbFdZuhDWeQXu3CFxiiDTXJn7DFxx2ZvrO7g==", + "engines": { + "node": ">=10" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": ">=16.0.0" } }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": "^18.2.0" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", "dependencies": { - "icss-utils": "^5.0.0" + "goober": "^2.1.10" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=10" }, "peerDependencies": { - "postcss": "^8.1.0" + "react": ">=16", + "react-dom": ">=16" } }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, + "node_modules/react-i18next": { + "version": "11.18.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", + "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "@babel/runtime": "^7.14.5", + "html-parse-stringify": "^3.0.1" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "peerDependencies": { + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "peer": true }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "bin": { - "prettier": "bin-prettier.js" + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, + "node_modules/react-number-format": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.2.2.tgz", + "integrity": "sha512-wCh64Z1HCwXcO2dbgkeYIaB+Rmp/fcsH8kAeRtUkc46dv1pIrgDjie2WkOqKBw8YqyqhwNdYgNFNQuuY+iGJ/g==", "dependencies": { - "fast-diff": "^1.1.2" + "prop-types": "^15.7.2" }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/prettier-plugin-organize-imports": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz", - "integrity": "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==", - "dev": true, + "node_modules/react-qr-code": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.11.tgz", + "integrity": "sha512-P7mvVM5vk9NjGdHMt4Z0KWeeJYwRAtonHTghZT2r+AASinLUUKQ9wfsGH2lPKsT++gps7hXmaiMGRvwTDEL9OA==", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, "peerDependencies": { - "@volar/vue-language-plugin-pug": "^1.0.4", - "@volar/vue-typescript": "^1.0.4", - "prettier": ">=2.0", - "typescript": ">=2.9" + "react": "^16.x || ^17.x || ^18.x", + "react-native-svg": "*" }, "peerDependenciesMeta": { - "@volar/vue-language-plugin-pug": { - "optional": true - }, - "@volar/vue-typescript": { + "react-native-svg": { "optional": true } } }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/pretty-format/node_modules/react-is": { + "node_modules/react-redux/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", "dev": true, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==", - "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/react-refresh-typescript": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.9.tgz", + "integrity": "sha512-chAnOO4vpxm/3WkgOVmti+eN8yUtkJzeGkOigV6UA9eDFz12W34e/SsYe2H5+RwYJ3+sfSZkVbiXcG1chEBxlg==", "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "peerDependencies": { + "react-refresh": "0.10.x || 0.11.x || 0.12.x || 0.13.x || 0.14.x", + "typescript": "^4.8 || ^5.0" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, + "node_modules/react-router": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz", + "integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "@remix-run/router": "1.7.2" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "node_modules/react-router-dom": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz", + "integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==", "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, + "@remix-run/router": "1.7.2", + "react-router": "6.14.2" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha512-hw7rcYTJRAl4olM8Owe8x0fBuJJ+WGbMhQuLWOXEMN3PxPCKQHRkhfL+XG0+iXUmSHjkMmb3Ba55Mt21cZc9kQ==", - "dependencies": { - "bitcoin-ops": "^1.3.0" + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/qr-code-styling": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.5.0.tgz", - "integrity": "sha512-7C+1cZGsZWH0BIRtv24faKZJwkxdYlynXktP9dDxKNSik2bqaUZck3B3MpQod/wqm9i3l4q7QsPGkRGKvcuqZw==", + "node_modules/react-select": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.4.tgz", + "integrity": "sha512-NhuE56X+p9QDFh4BgeygHFIvJJszO1i1KSkg/JPcIJrbovyRtI+GuOEa4XzFCEpZRAEoEI8u/cAHK+jG/PgUzQ==", "dependencies": { - "qrcode-generator": "^1.4.3" + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/qr.js": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", - "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" - }, - "node_modules/qrcode-generator": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", - "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" - }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "node_modules/react-share": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-share/-/react-share-4.4.1.tgz", + "integrity": "sha512-AJ9m9RiJssqvYg7MoJUc9J0D7b/liWrsfQ99ndKc5vJ4oVHHd4Fy87jBlKEQPibT40oYA3AQ/a9/oQY6/yaigw==", "dependencies": { - "side-channel": "^1.0.4" + "classnames": "^2.3.2", + "jsonp": "^0.2.1" }, "engines": { - "node": ">=0.6" + "node": ">=6.9.0", + "npm": ">=5.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "react": "^16.3.0 || ^17 || ^18" } }, - "node_modules/query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "node_modules/react-spinners": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz", + "integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-switch": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz", + "integrity": "sha512-KkDeW+cozZXI6knDPyUt3KBN1rmhoVYgAdCJqAh7st7tk8YE6N0iR89zjCWO8T8dUTeJGTR0KU+5CHCRMRffiA==", "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" + "prop-types": "^15.7.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/react-tabs": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", + "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", + "dependencies": { + "clsx": "^2.0.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/react-tooltip": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz", + "integrity": "sha512-NSUk77GMpxYKHFKJVNHL++QQXRuH2QW1qDrXPtJnp2s/MJvUnU73N5TTADwDyrO2+xGlr0xHhjvQphkF60cMEA==", "dependencies": { - "safe-buffer": "^5.1.0" + "@floating-ui/dom": "^1.0.0", + "classnames": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">= 6" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 0.8" + "node": ">=8.10.0" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rc-dialog": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.1.0.tgz", - "integrity": "sha512-5ry+JABAWEbaKyYsmITtrJbZbJys8CtMyzV8Xn4LYuXMeUx5XVHNyJRoqLFE4AzBuXXzOWeaC49cg+XkxK6kHA==", + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/portal": "^1.0.0-8", - "classnames": "^2.2.6", - "rc-motion": "^2.3.0", - "rc-util": "^5.21.0" - }, + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-persist": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", + "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "redux": ">4.0.0" } }, - "node_modules/rc-image": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.18.1.tgz", - "integrity": "sha512-xdr5zHpSJ6sGdV5oIkHWbttc21LlGKZZjWXVXxSS0sNmqSn97WzOKQBNrTA85UP7oBPPThZAGGGNmGnTkx2qYQ==", + "node_modules/redux-state-sync": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/redux-state-sync/-/redux-state-sync-3.1.4.tgz", + "integrity": "sha512-nhJBzaXVXPXvUhQJ7m0LdoXBnrcw+cTYQ8bzW9DeJKdq6UNYynXwQWAlVUvsbT/hDV+vB6BC4DMLXkUVGpF2yQ==", "dependencies": { - "@babel/runtime": "^7.11.2", - "@rc-component/portal": "^1.0.2", - "classnames": "^2.2.6", - "rc-dialog": "~9.1.0", - "rc-motion": "^2.6.2", - "rc-util": "^5.0.6" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "broadcast-channel": "^3.1.0" } }, - "node_modules/rc-motion": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.7.3.tgz", - "integrity": "sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==", + "node_modules/redux-state-sync/node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.21.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" } }, - "node_modules/rc-util": { - "version": "5.35.0", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.35.0.tgz", - "integrity": "sha512-MTXlixb3EoSTEchsOc7XWsVyoUQqoCsh2Z1a2IptwNgqleMF6ZgQeY52UzUbNj5CcVBg9YljOWjuOV07jSSm4Q==", + "node_modules/redux-state-sync/node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "react-is": "^16.12.0" + "regenerate": "^1.4.2" }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "engines": { + "node": ">=4" } }, - "node_modules/rc-util/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dependencies": { - "loose-envify": "^1.1.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-content-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/react-content-loader/-/react-content-loader-6.2.1.tgz", - "integrity": "sha512-6ONbFX+Hi3SHuP66JB8CPvJn372pj+qwltJV0J8z/8MFrq98I1cbFdZuhDWeQXu3CFxiiDTXJn7DFxx2ZvrO7g==", + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=8" }, - "peerDependencies": { - "react": ">=16.0.0" + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" } }, - "node_modules/react-hot-toast": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", - "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "node_modules/remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, "dependencies": { - "goober": "^2.1.10" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": ">=16", - "react-dom": ">=16" + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" } }, - "node_modules/react-i18next": { - "version": "11.18.6", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz", - "integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==", - "dependencies": { - "@babel/runtime": "^7.14.5", - "html-parse-stringify": "^3.0.1" - }, - "peerDependencies": { - "i18next": ">= 19.0.0", - "react": ">= 16.8.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "peer": true + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, - "node_modules/react-modal": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", - "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "node_modules/resolve": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz", + "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==", "dependencies": { - "exenv": "^1.2.0", - "prop-types": "^15.7.2", - "react-lifecycles-compat": "^3.0.0", - "warning": "^4.0.3" + "is-core-module": "^2.12.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "resolve": "bin/resolve" }, - "peerDependencies": { - "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", - "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react-number-format": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.2.2.tgz", - "integrity": "sha512-wCh64Z1HCwXcO2dbgkeYIaB+Rmp/fcsH8kAeRtUkc46dv1pIrgDjie2WkOqKBw8YqyqhwNdYgNFNQuuY+iGJ/g==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "dependencies": { - "prop-types": "^15.7.2" + "resolve-from": "^5.0.0" }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/react-qr-code": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.11.tgz", - "integrity": "sha512-P7mvVM5vk9NjGdHMt4Z0KWeeJYwRAtonHTghZT2r+AASinLUUKQ9wfsGH2lPKsT++gps7hXmaiMGRvwTDEL9OA==", - "dependencies": { - "prop-types": "^15.8.1", - "qr.js": "0.0.0" - }, - "peerDependencies": { - "react": "^16.x || ^17.x || ^18.x", - "react-native-svg": "*" - }, - "peerDependenciesMeta": { - "react-native-svg": { - "optional": true - } + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/react-redux": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", - "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", - "dependencies": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" - }, - "peerDependencies": { - "react": "^16.8.3 || ^17 || ^18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" } }, - "node_modules/react-redux/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/react-refresh-typescript": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.9.tgz", - "integrity": "sha512-chAnOO4vpxm/3WkgOVmti+eN8yUtkJzeGkOigV6UA9eDFz12W34e/SsYe2H5+RwYJ3+sfSZkVbiXcG1chEBxlg==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, - "peerDependencies": { - "react-refresh": "0.10.x || 0.11.x || 0.12.x || 0.13.x || 0.14.x", - "typescript": "^4.8 || ^5.0" - } - }, - "node_modules/react-router": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz", - "integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==", "dependencies": { - "@remix-run/router": "1.7.2" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": ">=16.8" + "node": ">=8" } }, - "node_modules/react-router-dom": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz", - "integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==", - "dependencies": { - "@remix-run/router": "1.7.2", - "react-router": "6.14.2" - }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "node": ">= 4" } }, - "node_modules/react-select": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.7.4.tgz", - "integrity": "sha512-NhuE56X+p9QDFh4BgeygHFIvJJszO1i1KSkg/JPcIJrbovyRtI+GuOEa4XzFCEpZRAEoEI8u/cAHK+jG/PgUzQ==", - "dependencies": { - "@babel/runtime": "^7.12.0", - "@emotion/cache": "^11.4.0", - "@emotion/react": "^11.8.1", - "@floating-ui/dom": "^1.0.1", - "@types/react-transition-group": "^4.4.0", - "memoize-one": "^6.0.0", - "prop-types": "^15.6.0", - "react-transition-group": "^4.3.0", - "use-isomorphic-layout-effect": "^1.1.2" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/react-share": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/react-share/-/react-share-4.4.1.tgz", - "integrity": "sha512-AJ9m9RiJssqvYg7MoJUc9J0D7b/liWrsfQ99ndKc5vJ4oVHHd4Fy87jBlKEQPibT40oYA3AQ/a9/oQY6/yaigw==", + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rgb-hex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-3.0.0.tgz", + "integrity": "sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { - "classnames": "^2.3.2", - "jsonp": "^0.2.1" + "glob": "^7.1.3" }, - "engines": { - "node": ">=6.9.0", - "npm": ">=5.0.0" + "bin": { + "rimraf": "bin.js" }, - "peerDependencies": { - "react": "^16.3.0 || ^17 || ^18" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/react-spinners": { - "version": "0.13.8", - "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz", - "integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==", - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "node_modules/react-switch": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz", - "integrity": "sha512-KkDeW+cozZXI6knDPyUt3KBN1rmhoVYgAdCJqAh7st7tk8YE6N0iR89zjCWO8T8dUTeJGTR0KU+5CHCRMRffiA==", - "dependencies": { - "prop-types": "^15.7.2" - }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + "node_modules/ripemd160-min": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz", + "integrity": "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==", + "engines": { + "node": ">=8" } }, - "node_modules/react-tabs": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", - "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "clsx": "^2.0.0", - "prop-types": "^15.5.0" - }, - "peerDependencies": { - "react": "^18.0.0" + "queue-microtask": "^1.2.2" } }, - "node_modules/react-tooltip": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.19.0.tgz", - "integrity": "sha512-NSUk77GMpxYKHFKJVNHL++QQXRuH2QW1qDrXPtJnp2s/MJvUnU73N5TTADwDyrO2+xGlr0xHhjvQphkF60cMEA==", + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dependencies": { - "@floating-ui/dom": "^1.0.0", - "classnames": "^2.3.0" + "tslib": "^1.9.0" }, - "peerDependencies": { - "react": ">=16.14.0", - "react-dom": ">=16.14.0" + "engines": { + "npm": ">=2.0.0" } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sats-connect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.1.tgz", + "integrity": "sha512-cckwlFc0gnYNZsNUsH9xACcpIeD+XdbSvtYhkGZSRqNeqzbqgdVI50mD4mzxs1ILbUGLjdTCINohVP6WbbvhcA==", "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" + "jsontokens": "^4.0.1", + "process": "^0.11.10", + "util": "^0.12.4" } }, - "node_modules/rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, "dependencies": { - "resolve": "^1.9.0" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" + "loose-envify": "^1.1.0" } }, - "node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "node_modules/schema-inspector": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.3.tgz", + "integrity": "sha512-Q9mpYxrP3w6CpHRfnh3QLOE1urkGTLvnl7xgVH7fsu0HYJUZenUASUr4j/pf7bAxShh+4R3Ta8ZgVKak1b2wyA==", "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, - "node_modules/redux-persist": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz", - "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", - "peerDependencies": { - "redux": ">4.0.0" + "async": "~2.6.3" } }, - "node_modules/redux-state-sync": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/redux-state-sync/-/redux-state-sync-3.1.4.tgz", - "integrity": "sha512-nhJBzaXVXPXvUhQJ7m0LdoXBnrcw+cTYQ8bzW9DeJKdq6UNYynXwQWAlVUvsbT/hDV+vB6BC4DMLXkUVGpF2yQ==", + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { - "broadcast-channel": "^3.1.0" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/redux-state-sync/node_modules/broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "node_modules/secp256k1": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", + "hasInstallScript": true, "dependencies": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.5.2", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4.0.0" } }, - "node_modules/redux-state-sync/node_modules/microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", "dev": true }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", "dev": true, "dependencies": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "node-forge": "^1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "ms": "2.0.0" } }, - "node_modules/regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==", + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==", + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" + "randombytes": "^2.1.0" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "engines": { - "node": ">= 0.10" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "dependencies": { - "is-finite": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, - "node_modules/resolve": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz", - "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==", + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dependencies": { - "is-core-module": "^2.12.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" }, "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "sha.js": "bin.js" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/sha256-uint8array": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", + "integrity": "sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "dependencies": { - "resolve-from": "^5.0.0" + "kind-of": "^6.0.2" }, "engines": { "node": ">=8" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", - "dev": true, - "engines": { - "node": ">=10" - } + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rgb-hex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-3.0.0.tgz", - "integrity": "sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ripemd160-min": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz", - "integrity": "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==", - "engines": { - "node": ">=8" - } + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" - }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { - "npm": ">=2.0.0" + "node": ">=8" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sats-connect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.1.tgz", - "integrity": "sha512-cckwlFc0gnYNZsNUsH9xACcpIeD+XdbSvtYhkGZSRqNeqzbqgdVI50mD4mzxs1ILbUGLjdTCINohVP6WbbvhcA==", - "dependencies": { - "jsontokens": "^4.0.1", - "process": "^0.11.10", - "util": "^0.12.4" + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" } }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" } }, - "node_modules/schema-inspector": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.3.tgz", - "integrity": "sha512-Q9mpYxrP3w6CpHRfnh3QLOE1urkGTLvnl7xgVH7fsu0HYJUZenUASUr4j/pf7bAxShh+4R3Ta8ZgVKak1b2wyA==", - "dependencies": { - "async": "~2.6.3" + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 14.15.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" - } - }, - "node_modules/secp256k1": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", - "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.5.2", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dev": true, - "dependencies": { - "node-forge": "^1" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "webpack": "^5.72.1" } }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.0.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" } }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "internal-slot": "^1.0.4" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } }, - "node_modules/serve-index/node_modules/ms": { + "node_modules/strict-uri-encode": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.6.19" } }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "node_modules/string-to-color": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/string-to-color/-/string-to-color-2.2.2.tgz", + "integrity": "sha512-XeA2goP7PNsSlz8RRn6KhYswnMf5Tl+38ajfy8n4oZJyMGC4qqKgHNHsZ/3qwvr42NRIjf9eSr721SyetDeMkA==", + "dependencies": { + "colornames": "^1.1.1", + "hex-rgb": "^4.1.0", + "lodash.padend": "^4.6.1", + "lodash.trimstart": "^4.5.1", + "lodash.words": "^4.2.0", + "rgb-hex": "^3.0.0" + } }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, - "bin": { - "sha.js": "bin.js" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sha256-uint8array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", - "integrity": "sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==" + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">=6" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { - "node": ">= 8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "node_modules/style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "node_modules/source-map-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", - "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", - "dev": true, + "node_modules/styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", "dependencies": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" }, "engines": { - "node": ">= 14.15.0" + "node": ">=10" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://opencollective.com/styled-components" }, "peerDependencies": { - "webpack": "^5.72.1" + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" } }, - "node_modules/source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "dependencies": { - "source-map": "^0.5.6" - } + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, + "node_modules/superjson": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-1.13.1.tgz", + "integrity": "sha512-AVH2eknm9DEd3qvxM4Sq+LTCkSXE2ssfh1t11MHMXyYXFQyQ1HLgVvV+guLTsaQnJU3gnaVo34TohHPulY/wLg==", "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "copy-anything": "^3.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "has-flag": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "dependencies": { - "escape-string-regexp": "^2.0.0" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, "engines": { "node": ">=8" } }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "dev": true - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "internal-slot": "^1.0.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" + "node": ">=8" } }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">=0.6.19" + "node": ">=6" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", "dev": true, "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-to-color": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/string-to-color/-/string-to-color-2.2.2.tgz", - "integrity": "sha512-XeA2goP7PNsSlz8RRn6KhYswnMf5Tl+38ajfy8n4oZJyMGC4qqKgHNHsZ/3qwvr42NRIjf9eSr721SyetDeMkA==", + "node_modules/terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dev": true, "dependencies": { - "colornames": "^1.1.1", - "hex-rgb": "^4.1.0", - "lodash.padend": "^4.6.1", - "lodash.trimstart": "^4.5.1", - "lodash.words": "^4.2.0", - "rgb-hex": "^3.0.0" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { - "node": ">=12" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tiny-secp256k1": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", + "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "hasInstallScript": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" + "bindings": "^1.3.0", + "bn.js": "^4.11.8", + "create-hmac": "^1.1.7", + "elliptic": "^6.4.0", + "nan": "^2.13.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "node_modules/tiny-secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "is-number": "^7.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.6" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "punycode": "^2.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/triplesec": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/triplesec/-/triplesec-4.0.3.tgz", + "integrity": "sha512-fug70e1nJoCMxsXQJlETisAALohm84vl++IiTTHEqM7Lgqwz62jrlwqOC/gJEAJjO/ByN127sEcioB56HW3wIw==", + "dependencies": { + "iced-error": ">=0.0.9", + "iced-lock": "^1.0.1", + "iced-runtime": "^1.0.2", + "more-entropy": ">=0.0.7", + "progress": "~1.1.2", + "uglify-js": "^3.1.9" + } + }, + "node_modules/ts-jest": { + "version": "27.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", + "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, "engines": { - "node": ">=8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@types/jest": "^27.0.0", + "babel-jest": ">=27.0.0 <28", + "jest": "^27.0.0", + "typescript": ">=3.8 <5.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/ts-jest/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "dependencies": { - "min-indent": "^1.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/ts-jest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/ts-loader": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", + "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, "engines": { - "node": ">=8" + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "typescript": "*", + "webpack": "*" } }, - "node_modules/style-loader": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", - "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 12.13.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/styled-components": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", - "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^1.1.0", - "@emotion/stylis": "^0.8.4", - "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1.12.0", - "css-to-react-native": "^3.0.0", - "hoist-non-react-statics": "^3.0.0", - "shallowequal": "^1.1.0", - "supports-color": "^5.5.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0", - "react-is": ">= 16.8.0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/styled-components/node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/superjson": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-1.13.1.tgz", - "integrity": "sha512-AVH2eknm9DEd3qvxM4Sq+LTCkSXE2ssfh1t11MHMXyYXFQyQ1HLgVvV+guLTsaQnJU3gnaVo34TohHPulY/wLg==", + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "copy-anything": "^3.0.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/ts-loader/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/ts-loader/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { + "node_modules/ts-loader/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -17068,2153 +17651,2363 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" + "node_modules/ts-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/tsc-files": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/tsc-files/-/tsc-files-1.1.4.tgz", + "integrity": "sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==", + "dev": true, + "bin": { + "tsc-files": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "typescript": ">=3" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^4.1.2" + }, "engines": { - "node": ">=6" + "node": ">=10.13.0" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/terser": { - "version": "5.19.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", - "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "node": ">=7.0.0" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "engines": { + "node": ">=8" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" + "minimist": "^1.2.0" }, - "engines": { - "node": ">=6.0.0" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/tiny-secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, "engines": { - "node": ">=4" + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "is-number": "^7.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=8.0" + "node": ">= 0.8.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { - "node": ">=0.6" + "node": ">=4" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, "engines": { - "node": ">=6" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "dependencies": { - "punycode": "^2.1.1" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/triplesec": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/triplesec/-/triplesec-4.0.3.tgz", - "integrity": "sha512-fug70e1nJoCMxsXQJlETisAALohm84vl++IiTTHEqM7Lgqwz62jrlwqOC/gJEAJjO/ByN127sEcioB56HW3wIw==", + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, "dependencies": { - "iced-error": ">=0.0.9", - "iced-lock": "^1.0.1", - "iced-runtime": "^1.0.2", - "more-entropy": ">=0.0.7", - "progress": "~1.1.2", - "uglify-js": "^3.1.9" + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ts-jest": { - "version": "27.1.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", - "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", "dev": true, "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - }, - "bin": { - "ts-jest": "cli.js" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ts-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, "bin": { - "semver": "bin/semver.js" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=10" + "node": ">=4.2.0" } }, - "node_modules/ts-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/ts-loader": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz", - "integrity": "sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^4.0.0", - "loader-utils": "^2.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "*" + "node": ">=0.8.0" } }, - "node_modules/ts-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ts-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" } }, - "node_modules/ts-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/ts-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/ts-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/ts-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">= 4.0.0" } }, - "node_modules/ts-loader/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "lru-cache": "^6.0.0" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, "bin": { - "semver": "bin/semver.js" + "update-browserslist-db": "cli.js" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/ts-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "punycode": "^2.1.0" } }, - "node_modules/ts-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, + "node_modules/url": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.1.tgz", + "integrity": "sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA==", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "punycode": "^1.4.1", + "qs": "^6.11.0" } }, - "node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", - "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.7.0", - "tsconfig-paths": "^4.1.2" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4.0" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uuidv4": { + "version": "6.2.13", + "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", + "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "dependencies": { + "@types/uuid": "8.3.4", + "uuid": "8.3.2" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=10.12.0" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, + "node_modules/varuint-bitcoin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", + "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "safe-buffer": "^5.1.1" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", "dev": true, "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" + "browser-process-hrtime": "^1.0.0" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "makeerror": "1.0.12" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "loose-envify": "^1.0.0" } }, - "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": ">=6" + "node": ">=10.13.0" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "minimalistic-assert": "^1.0.0" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/webextension-polyfill": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==" + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=10.4" } }, - "node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", "dev": true, "dependencies": { - "tslib": "^1.8.1" + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/webpack-cli": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "cross-spawn": "^7.0.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 10" } }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, "engines": { - "node": ">=12.20" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 0.6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "fast-deep-equal": "^3.1.3" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/typed-array-byte-length": { + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 0.4" + "node": ">= 12.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "dependencies": { - "is-typedarray": "^1.0.0" + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=4.2.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + }, + "node_modules/webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "dependencies": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" + "node": ">=10.13.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/webpack/node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10.13.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, - "dependencies": { - "punycode": "^2.1.0" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/url": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.1.tgz", - "integrity": "sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA==", + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.0" + "iconv-lite": "0.4.24" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, "engines": { - "node": ">= 0.4.0" + "node": ">=10" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, "bin": { - "uuid": "dist/bin/uuid" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/uuidv4": { - "version": "6.2.13", - "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", - "integrity": "sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==", + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dependencies": { - "@types/uuid": "8.3.4", - "uuid": "8.3.2" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, - "engines": { - "node": ">=10.12.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/valid-url": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", - "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" - }, - "node_modules/varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", + "node_modules/wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", "dependencies": { - "safe-buffer": "^5.1.1" + "bs58check": "<3.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" + "node_modules/wif/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" } }, - "node_modules/void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", - "engines": { - "node": ">=0.10.0" + "node_modules/wif/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dev": true, + "node_modules/wif/node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", "dependencies": { - "browser-process-hrtime": "^1.0.0" + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" } }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { - "xml-name-validator": "^3.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "loose-envify": "^1.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10.13.0" + "node": ">=7.0.0" } }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/webextension-polyfill": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", - "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==" + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=10.4" + "node": ">=8" } }, - "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "node": ">=8" } }, - "node_modules/webpack-cli": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", - "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=8.3.0" }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { "optional": true }, - "webpack-dev-server": { + "utf-8-validate": { "optional": true } } }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">= 14" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=12" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "engines": { + "node": ">=10" } }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=8" } }, - "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "node": ">=8" } }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yqueue": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/yqueue/-/yqueue-1.0.1.tgz", + "integrity": "sha512-DBxJZBRafFLA/tCc5uO8ZTGFr+sQgn1FRJkZ4cVrIQIk6bv2bInraE3mbpLAJw9z93JGrLkqDoyTLrrZaCNq5w==" + }, + "node_modules/zone-file": { + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/zone-file/-/zone-file-2.0.0-beta.3.tgz", + "integrity": "sha512-6tE3PSRcpN5lbTTLlkLez40WkNPc9vw/u1J2j6DBiy0jcVX48nCkWrx2EC+bWHqC2SLp069Xw4AdnYn/qp/W5g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/zxcvbn": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz", + "integrity": "sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==" + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@adobe/css-tools": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", + "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==" + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" } }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "@babel/compat-data": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==" }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" } }, - "node_modules/webpack-merge": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", - "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "requires": { + "@babel/types": "^7.22.5" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "dev": true, - "engines": { - "node": ">=10.13.0" + "requires": { + "@babel/types": "^7.22.15" } }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "@babel/helper-create-class-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dev": true, - "engines": { - "node": ">=0.8.0" + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } } }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "@babel/helper-define-polyfill-provider": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" } }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" + "requires": { + "@babel/types": "^7.23.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "requires": { + "@babel/types": "^7.22.15" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" } }, - "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" } }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "dependencies": { - "bs58check": "<3.0.0" + "@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" } }, - "node_modules/wif/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" } }, - "node_modules/wif/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" } }, - "node_modules/wif/node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@babel/helpers": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.15" } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "requires": {} + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" } }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" + "@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "engines": { - "node": ">= 14" + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "engines": { - "node": ">=10" + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" } }, - "node_modules/yqueue": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/yqueue/-/yqueue-1.0.1.tgz", - "integrity": "sha512-DBxJZBRafFLA/tCc5uO8ZTGFr+sQgn1FRJkZ4cVrIQIk6bv2bInraE3mbpLAJw9z93JGrLkqDoyTLrrZaCNq5w==" + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } }, - "node_modules/zone-file": { - "version": "2.0.0-beta.3", - "resolved": "https://registry.npmjs.org/zone-file/-/zone-file-2.0.0-beta.3.tgz", - "integrity": "sha512-6tE3PSRcpN5lbTTLlkLez40WkNPc9vw/u1J2j6DBiy0jcVX48nCkWrx2EC+bWHqC2SLp069Xw4AdnYn/qp/W5g==", - "engines": { - "node": ">=10" + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" } }, - "node_modules/zxcvbn": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz", - "integrity": "sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==" - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } }, - "@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==" + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } }, - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, - "@babel/code-frame": { + "@babel/plugin-transform-arrow-functions": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, "requires": { - "@babel/highlight": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==" - }, - "@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "@babel/plugin-transform-async-generator-functions": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "dev": true, "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.1" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" } }, - "@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, "requires": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" } }, - "@babel/helper-annotate-as-pure": { + "@babel/plugin-transform-block-scoped-functions": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "@babel/plugin-transform-block-scoping": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "dev": true, "requires": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/helper-environment-visitor": { + "@babel/plugin-transform-class-properties": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } }, - "@babel/helper-function-name": { + "@babel/plugin-transform-computed-properties": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" } }, - "@babel/helper-hoist-variables": { + "@babel/plugin-transform-destructuring": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/helper-module-imports": { + "@babel/plugin-transform-duplicate-keys": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "@babel/plugin-transform-dynamic-import": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, - "@babel/helper-plugin-utils": { + "@babel/plugin-transform-exponentiation-operator": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "@babel/plugin-transform-export-namespace-from": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "@babel/plugin-transform-for-of": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/helper-string-parser": { + "@babel/plugin-transform-function-name": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } }, - "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + "@babel/plugin-transform-json-strings": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } }, - "@babel/helper-validator-option": { + "@babel/plugin-transform-literals": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==" + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } }, - "@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, - "@babel/highlight": { + "@babel/plugin-transform-member-expression-literals": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==" - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "@babel/plugin-transform-modules-amd": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "@babel/plugin-transform-modules-commonjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" } }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "@babel/plugin-transform-modules-systemjs": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" } }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-syntax-jsx": { + "@babel/plugin-transform-new-target": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "@babel/plugin-transform-numeric-separator": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "@babel/plugin-transform-object-rest-spread": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.15" } }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" } }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "@babel/plugin-transform-optional-chaining": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "@babel/plugin-transform-parameters": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-syntax-typescript": { + "@babel/plugin-transform-private-methods": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.22.5" @@ -19244,23 +20037,237 @@ }, "@babel/plugin-transform-react-jsx-development": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", - "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "dependencies": { + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + } + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", "dev": true, "requires": { - "@babel/plugin-transform-react-jsx": "^7.22.5" + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" } }, - "@babel/plugin-transform-react-pure-annotations": { + "@babel/plugin-transform-unicode-sets-regex": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", - "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" } }, + "@babel/preset-env": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.2", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.11", + "@babel/plugin-transform-classes": "^7.22.15", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.23.0", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.11", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-for-of": "^7.22.15", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.11", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-numeric-separator": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.22.15", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.10", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.10", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, "@babel/preset-react": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz", @@ -19275,6 +20282,12 @@ "@babel/plugin-transform-react-pure-annotations": "^7.22.5" } }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "@babel/runtime": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", @@ -19284,39 +20297,39 @@ } }, "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", - "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "requires": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -19710,12 +20723,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -19803,12 +20810,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -19930,12 +20931,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -20059,12 +21054,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -20443,9 +21432,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "1.9.1", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/1.9.1/ea80ed9482e6a537cf26af36718dbcd56d55010c", - "integrity": "sha512-zAyst55gv5CrY9cWfMQYRIjDJn91Se89CgMPPOGjThoCQVOI7h/oX9JvVAZMVNEPZJwJvVpIdwpJ6kuPhc7U9Q==", + "version": "2.3.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/2.3.0/024dea2b4f44fb6cc84c7125b8adf381f8f2791d", + "integrity": "sha512-zE/C/e1ri551rVLJTNnJRDfLcXujOtdfTnW6nanIrEAjmNQxXH1DAploudDkRMDnG9JQBHrFnuW9JpeAGR4Y+g==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -20943,9 +21932,9 @@ } }, "@stacks/stacks-blockchain-api-types": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-6.3.4.tgz", - "integrity": "sha512-zrjKPGJN4p1azzmh8j0Yj+ZjQ0L9F01qJjAxOtBpapmFbGr1NUuPT1GthIg76y+dobdjSDPN39LpoJG/FbWFLw==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-6.1.1.tgz", + "integrity": "sha512-Mw5dBPx3DySPupwaq0iBdm1WdEVXIfhjUVaTjI2iSyzWz4Fgs3U7JCaAezLbgNu7Q69c/ZN4JUDWuo9FVjy7oA==" }, "@stacks/storage": { "version": "6.7.0", @@ -21546,9 +22535,9 @@ "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" }, "@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", "dev": true, "requires": { "@babel/parser": "^7.20.7", @@ -21559,18 +22548,18 @@ } }, "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", "dev": true, "requires": { "@babel/types": "^7.0.0" } }, "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -22681,401 +23670,115 @@ "call-bind": "^1.0.2", "define-properties": "^1.1.4", "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - } - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - } - } - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "requires": { - "lodash": "^4.17.14" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true - }, - "axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, - "requires": { - "dequal": "^2.0.3" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true - } - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha512-02I9jDjnVEuGy2BR3LRm9nPRb/+Ja0pvZVLr1eI5TYAA/dB0Xoc+WBo50+aDfhGDLhlBY1+QURjn9uvcFd8gzg==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "es-shim-unscopables": "^1.0.0" } }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==", + "array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", "dev": true, "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" } }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==", + "arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" } }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==", - "dev": true, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==", - "dev": true, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "lodash": "^4.17.14" } }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==", - "dev": true, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "axe-core": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", + "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", + "dev": true + }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==", + "axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "dequal": "^2.0.3" } }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==", + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "requires": {} }, "babel-jest": { "version": "27.5.1", @@ -23133,12 +23836,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -23175,424 +23872,81 @@ } } }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "requires": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - } - }, - "babel-plugin-styled-components": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", - "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "lodash": "^4.17.21", - "picomatch": "^2.3.1" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha512-HbTDIoG1A1op7Tl/wIFQPULIBA61tsJ8Ntq2FAhLwuijrzosM/92kAfgU1Q3Kc7DH/cprJg5vDfuTY4QUL4rDA==", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==", - "dev": true - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha512-TxIM0ZWNw9oYsoTthL3lvAK3+eTujzktoXJg4ubGvICGbVuXVYv5hHv0XXpz8fbqlJaGYY4q5SVzaSmsg3t4Fg==", + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" } }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha512-QLYkLiZeeED2PKd4LuXGg5y9fCgPB5ohF8olWUuETE2ryHNRqqnXlEVP7RPuef89+HTfd3syptMGVHeoAu0Wig==", + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", "dev": true, "requires": { - "babel-runtime": "^6.22.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" } }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha512-s+q/Y2u2OgDPHRuod3t6zyLoV8pUHc64i/O7ZNgIOEdYTq+ChPeybcKBi/xk9VI60VriILzFPW+dUxAEbTxh2w==", - "dev": true, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" } }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha512-Y3ZHP1nunv0U1+ysTNwLK39pabHj6cPVsfN4TRC7BDBfbgbyF4RifP5kd6LnbuMV9wcfedQMe7hn1fyKc7IzTQ==", + "babel-plugin-polyfill-corejs2": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", "dev": true, "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.3", + "semver": "^6.3.1" } }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha512-pcDNDsZ9q/6LJmujQ/OhjeoIlp5Nl546HJ2yiFIJK3mYpgNXhI5/S9mXfVxu5yqWAi7HdI7e/q6a9xtzwL69Vw==", + "babel-plugin-polyfill-corejs3": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" } }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==", + "babel-plugin-polyfill-regenerator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", "dev": true, "requires": { - "regenerator-transform": "^0.10.0" + "@babel/helper-define-polyfill-provider": "^0.4.3" } }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==", - "dev": true, + "babel-plugin-styled-components": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", + "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==", "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" } }, "babel-preset-current-node-syntax": { @@ -23615,71 +23969,6 @@ "@babel/plugin-syntax-top-level-await": "^7.8.3" } }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - }, - "dependencies": { - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha512-PQZFJXnM3d80Vq4O67OE6EMVKIw2Vmzy8UXovqulNogCtblWU8rzP7Sm5YgHiCg4uejUxzCkHfNXQ4Z6GI+Dhw==", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, "babel-preset-jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", @@ -23690,132 +23979,6 @@ "babel-preset-current-node-syntax": "^1.0.0" } }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha512-phQe3bElbgF887UM0Dhz55d22ob8czTL1kbhZFwpCE6+R/X9kHktfwmx9JZb+bBSVRGphP5tZ9oWhVhlgjrX3Q==", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", - "dev": true - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -24187,30 +24350,30 @@ } }, "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" } }, "browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "requires": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "update-browserslist-db": "^1.0.13" } }, "bs-logger": { @@ -24324,9 +24487,9 @@ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" }, "caniuse-lite": { - "version": "1.0.30001519", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz", - "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==" + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==" }, "chalk": { "version": "2.4.2", @@ -24761,11 +24924,14 @@ } } }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true + "core-js-compat": { + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", + "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==", + "dev": true, + "requires": { + "browserslist": "^4.22.1" + } }, "core-js-pure": { "version": "3.32.0", @@ -25209,15 +25375,6 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -25444,9 +25601,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.482", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.482.tgz", - "integrity": "sha512-h+UqpfmEr1Qkk0zp7ej/jid7CXoq4m4QzW6wNTb0ELJ/BZCpA4wgUylBIMGCe621tnr4l5VmoHjdoSx2lbnNJA==" + "version": "1.4.572", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.572.tgz", + "integrity": "sha512-RlFobl4D3ieetbnR+2EpxdzFl9h0RAJkPK3pfiwMug2nhBin2ZCsGIAJWdpNniLz43sgXam/CgipOmvTA+rUiA==" }, "elliptic": { "version": "6.5.4", @@ -26622,14 +26779,6 @@ "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" - }, - "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - } } }, "goober": { @@ -26678,23 +26827,6 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - } - } - }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -26786,16 +26918,6 @@ } } }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -27151,15 +27273,6 @@ "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, "ipaddr.js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", @@ -27249,12 +27362,6 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, "is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", @@ -27664,12 +27771,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -27873,12 +27974,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -28273,12 +28368,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -28371,12 +28460,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -28565,12 +28648,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -29387,6 +29464,12 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -29763,15 +29846,6 @@ "resolved": "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.47.0.tgz", "integrity": "sha512-Ldrva0fRBEIFWmEibBQO1PulfpJVF3pf28Guk09lDirDaSQqqU/xs9zQLwN2rL5VwVtsP1aD3JaCgaa98EjojQ==" }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -30086,18 +30160,6 @@ "type-check": "^0.4.0" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -30516,12 +30578,6 @@ } } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -31070,22 +31126,20 @@ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true }, + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, "regexp.prototype.flags": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", @@ -31102,40 +31156,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -31160,15 +31180,6 @@ "strip-ansi": "^6.0.1" } }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -31637,9 +31648,9 @@ "dev": true }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "slice-ansi": { @@ -31699,23 +31710,6 @@ "source-map-js": "^1.0.2" } }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, "spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -32209,12 +32203,6 @@ "punycode": "^2.1.1" } }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", - "dev": true - }, "triplesec": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/triplesec/-/triplesec-4.0.3.tgz", @@ -32358,6 +32346,13 @@ } } }, + "tsc-files": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/tsc-files/-/tsc-files-1.1.4.tgz", + "integrity": "sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==", + "dev": true, + "requires": {} + }, "tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -32614,6 +32609,34 @@ "which-boxed-primitive": "^1.0.2" } }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true + }, "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", @@ -32636,9 +32659,9 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" diff --git a/package.json b/package.json index cf9d28fcf..1afd69db9 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,20 @@ { "name": "xverse-web-extension", "description": "A Bitcoin wallet for Web3", - "version": "0.21.0", + "version": "0.22.1", "private": true, + "engines": { + "node": "^18.18.2" + }, "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "1.9.1", + "@secretkeylabs/xverse-core": "2.3.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", - "@stacks/stacks-blockchain-api-types": "^6.1.1", - "@stacks/transactions": "^4.3.8", + "@stacks/stacks-blockchain-api-types": "6.1.1", + "@stacks/transactions": "4.3.8", "@tanstack/query-sync-storage-persister": "^4.29.1", "@tanstack/react-query": "^4.29.3", "@tanstack/react-query-devtools": "^4.29.3", @@ -86,14 +89,17 @@ "lint-staged": { "*.{ts,tsx}": [ "prettier --write", - "eslint" + "eslint", + "tsc-files --noEmit src/styled.d.ts src/react-app-env.d.ts" ], "*.json": [ "prettier --write" ] }, "devDependencies": { - "@babel/preset-react": "^7.18.6", + "@babel/core": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-react": "^7.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@tanstack/eslint-plugin-query": "^4.29.4", "@types/argon2-browser": "^1.18.1", @@ -108,11 +114,10 @@ "@types/zxcvbn": "^4.4.1", "@typescript-eslint/eslint-plugin": "^5.37.0", "@typescript-eslint/parser": "^5.37.0", - "babel-core": "^6.26.3", + "babel-core": "^7.0.0-bridge.0", + "babel-jest": "^27.5.1", "babel-loader": "^8.2.5", "babel-plugin-styled-components": "^2.0.7", - "babel-preset-env": "^1.7.0", - "babel-preset-react": "^6.24.1", "base64-loader": "^1.0.0", "clean-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^11.0.0", @@ -145,6 +150,7 @@ "terser-webpack-plugin": "^5.3.6", "ts-jest": "^27.0.5", "ts-loader": "^8.4.0", + "tsc-files": "^1.1.4", "tsconfig-paths-webpack-plugin": "^4.0.0", "type-fest": "^2.19.0", "typescript": "^4.8.2", diff --git a/src/app/components/accountHeader/index.tsx b/src/app/components/accountHeader/index.tsx index 9a5751d23..2291c6ed3 100644 --- a/src/app/components/accountHeader/index.tsx +++ b/src/app/components/accountHeader/index.tsx @@ -9,6 +9,7 @@ import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import OptionsDialog, { OPTIONS_DIALOG_WIDTH } from '@components/optionsDialog/optionsDialog'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; const SelectedAccountContainer = styled.div<{ showBorderBottom?: boolean }>((props) => ({ @@ -55,13 +56,13 @@ const ButtonRow = styled.button` padding-top: 11px; padding-bottom: 11px; font: ${(props) => props.theme.body_medium_m}; - color: ${(props) => props.theme.colors.white['0']}; + color: ${(props) => props.theme.colors.white_0}; transition: background-color 0.2s ease; :hover { - background-color: ${(props) => props.theme.colors.background.elevation3}; + background-color: ${(props) => props.theme.colors.elevation3}; } :active { - background-color: ${(props) => props.theme.colors.background.elevation3}; + background-color: ${(props) => props.theme.colors.elevation3}; } `; @@ -91,23 +92,19 @@ function AccountHeaderComponent({ const [showResetWalletPrompt, setShowResetWalletPrompt] = useState(false); const [showResetWalletDisplay, setShowResetWalletDisplay] = useState(false); const [password, setPassword] = useState(''); - const { unlockWallet, lockWallet, resetWallet } = useWalletReducer(); + const { lockWallet, resetWallet } = useWalletReducer(); + const { unlockVault } = useSeedVault(); const [error, setError] = useState(''); const [optionsDialogIndents, setOptionsDialogIndents] = useState< { top: string; left: string } | undefined >(); - const handleResetWallet = () => { - resetWallet(); - navigate('/'); - }; - const handlePasswordNextClick = async () => { try { - await unlockWallet(password); + await unlockVault(password); setPassword(''); setError(''); - handleResetWallet(); + await resetWallet(); } catch (e) { setError(t('INCORRECT_PASSWORD_ERROR')); } @@ -151,6 +148,10 @@ function AccountHeaderComponent({ setShowOptionsDialog(false); }; + const handleLockWallet = async () => { + await lockWallet(); + }; + return ( <> {showResetWalletDisplay && ( @@ -187,7 +188,7 @@ function AccountHeaderComponent({ {optionsDialogTranslation('SWITCH_ACCOUNT')} - {optionsDialogTranslation('LOCK')} + {optionsDialogTranslation('LOCK')} {optionsDialogTranslation('RESET_WALLET')} diff --git a/src/app/components/accountRow/index.tsx b/src/app/components/accountRow/index.tsx index c7a12bd3a..b1d0f4058 100644 --- a/src/app/components/accountRow/index.tsx +++ b/src/app/components/accountRow/index.tsx @@ -59,13 +59,13 @@ const CurrentAccountTextContainer = styled.div((props) => ({ const CurrentSelectedAccountText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'start', })); const CurrentUnSelectedAccountText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'start', })); @@ -101,7 +101,7 @@ const ModalContent = styled.div((props) => ({ const ModalDescription = styled.div((props) => ({ fontSize: '0.875rem', - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(16), })); @@ -126,13 +126,13 @@ const ButtonRow = styled.button` padding-top: 11px; padding-bottom: 11px; font: ${(props) => props.theme.body_medium_m}; - color: ${(props) => props.theme.colors.white['0']}; + color: ${(props) => props.theme.colors.white_0}; transition: background-color 0.2s ease; :hover { - background-color: ${(props) => props.theme.colors.background.elevation3}; + background-color: ${(props) => props.theme.colors.elevation3}; } :active { - background-color: ${(props) => props.theme.colors.background.elevation3}; + background-color: ${(props) => props.theme.colors.elevation3}; } `; diff --git a/src/app/components/alertMessage/index.tsx b/src/app/components/alertMessage/index.tsx index d3c68613c..79f28bdef 100644 --- a/src/app/components/alertMessage/index.tsx +++ b/src/app/components/alertMessage/index.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components'; import Cross from '@assets/img/dashboard/X.svg'; import ActionButton from '@components/button'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -12,7 +12,7 @@ const Container = styled.div((props) => ({ width: 312, borderRadius: 12, zIndex: 16000, - background: props.theme.colors.background.elevation3, + background: props.theme.colors.elevation3, filter: 'drop-shadow(0px 16px 36px rgba(0, 0, 0, 0.5))', })); @@ -24,7 +24,7 @@ const HeaderText = styled.h1((props) => ({ const DescriptionText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, margin: 16, fontSize: 16, })); @@ -34,7 +34,7 @@ const RowContainer = styled.div((props) => ({ flexDirection: 'row', padding: '20px 16px 16px 16px', alignItems: 'space-between', - borderBottom: `1px solid ${props.theme.colors.background.elevation6}`, + borderBottom: `1px solid ${props.theme.colors.elevation6}`, })); const TickMarkButtonContainer = styled.div((props) => ({ @@ -48,7 +48,7 @@ const TickMarkButtonContainer = styled.div((props) => ({ const TickMarkButtonText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(4.25), })); @@ -101,7 +101,7 @@ const OuterContainer = styled.div((props) => ({ bottom: 0, right: 0, position: 'fixed', - backgroundColor: props.theme.colors.background.elevation0, + backgroundColor: props.theme.colors.elevation0, zIndex: 1000, opacity: 0.6, })); diff --git a/src/app/components/backHeader/index.tsx b/src/app/components/backHeader/index.tsx deleted file mode 100644 index cda8f5c52..000000000 --- a/src/app/components/backHeader/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import styled from 'styled-components'; -import ArrowLeft from '@assets/img/arrow_left.svg'; - -const Container = styled.div(() => ({ - display: 'flex', - height: 62, - alignItems: 'center', - justifyContent: 'space-between', -})); - -const HeaderContent = styled.div({ - display: 'flex', - flex: 1, - alignItems: 'center', - justifyContent: 'space-between', -}); - -const HeaderTitle = styled.h1((props) => ({ - ...props.theme.body_bold_m, - textAlign: 'center', -})); - -const Filler = styled.div({ - display: 'flex', - flex: 0.5, -}); - -interface BackHeaderProps { - headerText: string; - onPressBack: () => void; -} - -function BackHeader(props: BackHeaderProps): JSX.Element { - const { headerText, onPressBack } = props; - return ( - - - - {headerText} - - - - ); -} -export default BackHeader; diff --git a/src/app/components/bottomModal/index.tsx b/src/app/components/bottomModal/index.tsx index 720e1d974..f26cd9bf7 100644 --- a/src/app/components/bottomModal/index.tsx +++ b/src/app/components/bottomModal/index.tsx @@ -61,7 +61,7 @@ function BottomModal({ maxWidth: 360, maxHeight: '90%', border: 'transparent', - background: theme.colors.background.elevation2, + background: theme.colors.elevation2, margin: 0, padding: 0, borderTopLeftRadius: isGalleryOpen ? 12 : 20, diff --git a/src/app/components/button/index.tsx b/src/app/components/button/index.tsx index a5d656900..2aa6735b4 100644 --- a/src/app/components/button/index.tsx +++ b/src/app/components/button/index.tsx @@ -31,17 +31,17 @@ const Button = styled.button((props) => ({ })); const TransparentButton = styled(Button)((props) => ({ - border: `1px solid ${props.theme.colors.background.elevation6}`, + border: `1px solid ${props.theme.colors.elevation6}`, backgroundColor: 'transparent', ':disabled': { cursor: 'not-allowed', opacity: 0.4, }, ':hover:enabled': { - backgroundColor: props.theme.colors.background.elevation6_800, + backgroundColor: props.theme.colors.elevation6_800, }, ':active:enabled': { - backgroundColor: props.theme.colors.background.elevation6_600, + backgroundColor: props.theme.colors.elevation6_600, }, })); @@ -52,16 +52,14 @@ interface TextProps { const ButtonText = styled.h1((props) => ({ ...props.theme.body_xs, fontWeight: 700, - color: `${ - props.warning ? props.theme.colors.white[0] : props.theme.colors.background.elevation0 - }`, + color: `${props.warning ? props.theme.colors.white_0 : props.theme.colors.elevation0}`, textAlign: 'center', })); const AnimatedButtonText = styled.div((props) => ({ ...props.theme.body_xs, fontWeight: 700, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textAlign: 'center', })); diff --git a/src/app/components/checkBox/index.tsx b/src/app/components/checkBox/index.tsx index 01d9d7f78..f3caac4c3 100644 --- a/src/app/components/checkBox/index.tsx +++ b/src/app/components/checkBox/index.tsx @@ -9,7 +9,7 @@ interface CheckBoxProps { const CheckBoxWrapper = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, label: { marginLeft: props.theme.spacing(5), }, diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index c4226f9af..551364017 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -1,20 +1,23 @@ import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; import AssetIcon from '@assets/img/transactions/Assets.svg'; import ActionButton from '@components/button'; +import InfoContainer from '@components/infoContainer'; import RecipientComponent from '@components/recipientComponent'; import TopRow from '@components/topRow'; import TransactionSettingAlert from '@components/transactionSetting'; import TransferFeeView from '@components/transferFeeView'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; +import useSeedVault from '@hooks/useSeedVault'; +import useWalletSelector from '@hooks/useWalletSelector'; import { BtcUtxoDataResponse, ErrorCodes, - ResponseError, - UTXO, getBtcFiatEquivalent, + ResponseError, satsToBtc, + signBtcTransaction, + UTXO, } from '@secretkeylabs/xverse-core'; -import { signBtcTransaction } from '@secretkeylabs/xverse-core/transactions'; import { Recipient, SignedBtcTx, @@ -22,16 +25,14 @@ import { signOrdinalSendTransaction, } from '@secretkeylabs/xverse-core/transactions/btc'; import { useMutation } from '@tanstack/react-query'; +import Callout from '@ui-library/callout'; import { CurrencyTypes } from '@utils/constants'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; -import InfoContainer from '@components/infoContainer'; -import useWalletSelector from '@hooks/useWalletSelector'; import TransactionDetailComponent from '../transactionDetailComponent'; -import Callout from '@ui-library/callout'; const OuterContainer = styled.div` display: flex; @@ -81,8 +82,8 @@ const Button = styled.button((props) => ({ })); const ButtonText = styled.div((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -99,16 +100,16 @@ const ErrorContainer = styled.div((props) => ({ })); const ErrorText = styled.h1((props) => ({ - ...props.theme.body_xs, - color: props.theme.colors.feedback.error, + ...props.theme.typography.body_s, + color: props.theme.colors.danger_medium, })); interface ReviewTransactionTitleProps { isOridnalTx: boolean; } const ReviewTransactionText = styled.h1((props) => ({ - ...props.theme.headline_s, - color: props.theme.colors.white[0], + ...props.theme.typography.headline_s, + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(16), textAlign: props.isOridnalTx ? 'center' : 'left', })); @@ -166,8 +167,8 @@ function ConfirmBtcTransactionComponent({ const { t } = useTranslation('translation'); const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const [loading, setLoading] = useState(false); - const { btcAddress, selectedAccount, seedPhrase, network, btcFiatRate, feeMultipliers } = - useWalletSelector(); + const { btcAddress, selectedAccount, network, btcFiatRate, feeMultipliers } = useWalletSelector(); + const { getSeed } = useSeedVault(); const [showFeeSettings, setShowFeeSettings] = useState(false); const [error, setError] = useState(''); const [signedTx, setSignedTx] = useState(signedTxHex); @@ -182,11 +183,12 @@ function ConfirmBtcTransactionComponent({ SignedBtcTx, ResponseError, { - recipients: Recipient[]; + txRecipients: Recipient[]; txFee: string; + seedPhrase: string; } >({ - mutationFn: async ({ recipients: newRecipients, txFee }) => + mutationFn: async ({ txRecipients: newRecipients, txFee, seedPhrase }) => signBtcTransaction( newRecipients, btcAddress, @@ -197,13 +199,23 @@ function ConfirmBtcTransactionComponent({ ), }); + if (typeof feePerVByte !== 'string' && !BigNumber.isBigNumber(feePerVByte)) { + Object.setPrototypeOf(feePerVByte, BigNumber.prototype); + } + + recipients.forEach((recipient) => { + if (typeof recipient.amountSats !== 'string' && !BigNumber.isBigNumber(recipient.amountSats)) { + Object.setPrototypeOf(recipient.amountSats, BigNumber.prototype); + } + }); + const { isLoading: isLoadingNonOrdinalBtcSend, error: errorSigningNonOrdial, data: signedNonOrdinalBtcSend, mutate: mutateSignNonOrdinalBtcTransaction, - } = useMutation({ - mutationFn: async (txFee) => { + } = useMutation({ + mutationFn: async ({ txFee, seedPhrase }) => { const signedNonOrdinalBtcTx = await signNonOrdinalBtcSendTransaction( btcAddress, nonOrdinalUtxos!, @@ -223,8 +235,8 @@ function ConfirmBtcTransactionComponent({ data: ordinalData, error: ordinalError, mutate: ordinalMutate, - } = useMutation({ - mutationFn: async (txFee) => { + } = useMutation({ + mutationFn: async ({ txFee, seedPhrase }) => { const ordinalsUtxos = ordinals!.map((ord) => ord.utxo); const newSignedTx = await signOrdinalSendTransaction( @@ -259,10 +271,9 @@ function ConfirmBtcTransactionComponent({ useEffect(() => { let sum: BigNumber = new BigNumber(0); - if (recipients) { - recipients.map((recipient) => { + if (recipients?.length) { + recipients.forEach((recipient) => { sum = sum.plus(recipient.amountSats); - return sum; }); sum = sum?.plus(currentFee); } @@ -296,7 +307,7 @@ function ConfirmBtcTransactionComponent({ setShowFeeSettings(false); }; - const onApplyClick = ({ + const onApplyClick = async ({ fee: modifiedFee, feeRate, }: { @@ -305,14 +316,14 @@ function ConfirmBtcTransactionComponent({ nonce?: string; }) => { const newFee = new BigNumber(modifiedFee); - setCurrentFee(newFee); - setCurrentFeeRate(new BigNumber(feeRate)); - if (ordinalTxUtxo) ordinalMutate(modifiedFee); + const seed = await getSeed(); + setCurrentFeeRate(new BigNumber(feeRate ?? '')); + if (ordinalTxUtxo) ordinalMutate({ txFee: modifiedFee, seedPhrase: seed }); else if (isRestoreFundFlow) { - mutateSignNonOrdinalBtcTransaction(modifiedFee); + mutateSignNonOrdinalBtcTransaction({ txFee: modifiedFee, seedPhrase: seed }); } else { - mutate({ recipients, txFee: modifiedFee }); + mutate({ txRecipients: recipients, txFee: modifiedFee, seedPhrase: seed }); } setLoading(true); }; @@ -397,12 +408,13 @@ function ConfirmBtcTransactionComponent({ value={assetDetail!} valueDetail={assetDetailValue} icon={AssetIcon} - currencyType={currencyType ? currencyType : 'Ordinal'} + currencyType={currencyType || 'Ordinal'} title={t('CONFIRM_TRANSACTION.ASSET')} /> ) : ( recipients?.map((recipient, index) => ( ({ display: 'flex', flexDirection: 'column', justifyContent: 'center', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, overflowY: 'auto', padding: props.theme.spacing(6), @@ -31,32 +31,32 @@ const TransferDetailContainer = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const OutputTitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(6), })); const SubValueText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const TxIdText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(2), })); const YourAddressText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginRight: props.theme.spacing(2), })); diff --git a/src/app/components/confirmStxTransactionComponent/index.tsx b/src/app/components/confirmStxTransactionComponent/index.tsx index adadb12d2..67b4498bc 100644 --- a/src/app/components/confirmStxTransactionComponent/index.tsx +++ b/src/app/components/confirmStxTransactionComponent/index.tsx @@ -1,31 +1,32 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import { ReactNode, useEffect, useState } from 'react'; -import BigNumber from 'bignumber.js'; -import ActionButton from '@components/button'; import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; +import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg'; +import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; +import { ledgerDelay } from '@common/utils/ledger'; +import BottomModal from '@components/bottomModal'; +import ActionButton from '@components/button'; +import InfoContainer from '@components/infoContainer'; +import LedgerConnectionView from '@components/ledger/connectLedgerView'; import TransactionSettingAlert from '@components/transactionSetting'; -import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; -import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; import TransferFeeView from '@components/transferFeeView'; +import useNetworkSelector from '@hooks/useNetwork'; +import useSeedVault from '@hooks/useSeedVault'; +import useWalletSelector from '@hooks/useWalletSelector'; +import Transport from '@ledgerhq/hw-transport-webusb'; import { + getNonce, setFee, setNonce, - getNonce, + signLedgerStxTransaction, signMultiStxTransactions, signTransaction, - signLedgerStxTransaction, } from '@secretkeylabs/xverse-core'; -import useWalletSelector from '@hooks/useWalletSelector'; -import useNetworkSelector from '@hooks/useNetwork'; -import Transport from '@ledgerhq/hw-transport-webusb'; -import BottomModal from '@components/bottomModal'; -import LedgerConnectionView from '@components/ledger/connectLedgerView'; -import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg'; -import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; -import { ledgerDelay } from '@common/utils/ledger'; +import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; +import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; import { isHardwareAccount } from '@utils/helper'; -import InfoContainer from '@components/infoContainer'; +import BigNumber from 'bignumber.js'; +import { ReactNode, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Container = styled.div` display: flex; @@ -69,7 +70,7 @@ const Button = styled.button((props) => ({ const ButtonText = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -81,7 +82,7 @@ const ButtonImage = styled.img((props) => ({ const SponsoredInfoText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const SuccessActionsContainer = styled.div((props) => ({ @@ -97,13 +98,13 @@ const SuccessActionsContainer = styled.div((props) => ({ const ReviewTransactionText = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textAlign: 'left', })); const RequestedByText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(4), textAlign: 'left', })); @@ -146,8 +147,9 @@ function ConfirmStxTransationComponent({ keyPrefix: 'SIGNATURE_REQUEST', }); const selectedNetwork = useNetworkSelector(); + const { getSeed } = useSeedVault(); const [showFeeSettings, setShowFeeSettings] = useState(false); - const { selectedAccount, seedPhrase, feeMultipliers } = useWalletSelector(); + const { selectedAccount, feeMultipliers } = useWalletSelector(); const [openTransactionSettingModal, setOpenTransactionSettingModal] = useState(false); const [buttonLoading, setButtonLoading] = useState(loading); const [isModalVisible, setIsModalVisible] = useState(false); @@ -206,11 +208,12 @@ function ConfirmStxTransationComponent({ return; } + const seed = await getSeed(); let signedTxs: StacksTransaction[] = []; if (initialStxTransactions.length === 1) { const signedContractCall = await signTransaction( initialStxTransactions[0], - seedPhrase, + seed, selectedAccount?.id ?? 0, selectedNetwork, ); @@ -220,7 +223,7 @@ function ConfirmStxTransationComponent({ initialStxTransactions, selectedAccount?.id ?? 0, selectedNetwork, - seedPhrase, + seed, ); } onConfirmClick(signedTxs); diff --git a/src/app/components/confirmStxTransactionComponent/transferMemoView/index.tsx b/src/app/components/confirmStxTransactionComponent/transferMemoView/index.tsx index a083e49f3..4ad4ff979 100644 --- a/src/app/components/confirmStxTransactionComponent/transferMemoView/index.tsx +++ b/src/app/components/confirmStxTransactionComponent/transferMemoView/index.tsx @@ -1,10 +1,10 @@ -import styled from 'styled-components'; import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -13,13 +13,13 @@ const Container = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const DescriptionText = styled.h1((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(2), - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const RowContainer = styled.div({ diff --git a/src/app/components/confirmTransactionScreen/index.tsx b/src/app/components/confirmTransactionScreen/index.tsx deleted file mode 100644 index 7ae5fbca6..000000000 --- a/src/app/components/confirmTransactionScreen/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import ConfirmScreen from '@components/confirmScreen'; -import SwapImage from '@assets/img/swap-illustration.svg'; -import BNSImage from '@assets/img/bns-illustration.svg'; -import NFTImage from '@assets/img/nft-illustration.svg'; -import styled from 'styled-components'; -import { ReactNode } from 'react'; -import { useTranslation } from 'react-i18next'; - -const headerImageMapping = { - 'purchase-asset': NFTImage, - 'buy-item': NFTImage, - 'buy-in-ustx': NFTImage, - 'name-preorder': BNSImage, - 'swap-x-for-y': SwapImage, - 'swap-helper': SwapImage, -}; - -const AdvanceSettingsButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'flex-end', - backgroundColor: '#00000000', - width: 150, - height: 20, - marginLeft: 16, - color: props.theme.colors.white['0'], -})); - -const FeesContainer = styled.div(() => ({})); - -type Props = { children: ReactNode; onConfirm: () => void; onCancel: () => void }; - -function ConfirmTransaction({ children, onConfirm, onCancel }: Props) { - const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION_SCREEN' }); - - return ( - - <> - {children} - - {/* - - */} - - Advance settings - - - ); -} - -export default ConfirmTransaction; diff --git a/src/app/components/copyButton/index.tsx b/src/app/components/copyButton/index.tsx index 0e582abfa..5bed584c6 100644 --- a/src/app/components/copyButton/index.tsx +++ b/src/app/components/copyButton/index.tsx @@ -1,9 +1,9 @@ -import styled from 'styled-components'; import Copy from '@assets/img/nftDashboard/Copy.svg'; import Tick from '@assets/img/tick.svg'; import { useEffect, useState } from 'react'; -import { Tooltip } from 'react-tooltip'; import { useTranslation } from 'react-i18next'; +import { Tooltip } from 'react-tooltip'; +import styled from 'styled-components'; const Button = styled.button((props) => ({ display: 'flex', @@ -13,7 +13,7 @@ const Button = styled.button((props) => ({ marginLeft: props.theme.spacing(3), padding: 3, ':hover': { - background: props.theme.colors.white[900], + background: props.theme.colors.white_900, borderRadius: 24, }, })); diff --git a/src/app/components/extendedScreenContainer/index.tsx b/src/app/components/extendedScreenContainer/index.tsx index a4402e7d3..a0898e4b2 100644 --- a/src/app/components/extendedScreenContainer/index.tsx +++ b/src/app/components/extendedScreenContainer/index.tsx @@ -1,6 +1,5 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { useTranslation } from 'react-i18next'; -import { useDispatch } from 'react-redux'; import { Outlet } from 'react-router-dom'; import styled from 'styled-components'; @@ -9,8 +8,8 @@ const ExtendedScreenRouteContainer = styled.div((props) => ({ flexDirection: 'column', height: '100vh', width: '100vw', - backgroundColor: props.theme.colors.background.elevation0, - border: `1px solid ${props.theme.colors.background.elevation2}`, + backgroundColor: props.theme.colors.elevation0, + border: `1px solid ${props.theme.colors.elevation2}`, boxShadow: '0px 8px 28px rgba(0, 0, 0, 0.35)', })); @@ -18,7 +17,7 @@ const TestnetContainer = styled.div((props) => ({ display: 'flex', alignItems: 'center', justifyContent: 'center', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, paddingTop: props.theme.spacing(3), paddingBottom: props.theme.spacing(3), })); @@ -26,7 +25,7 @@ const TestnetContainer = styled.div((props) => ({ const TestnetText = styled.h1((props) => ({ ...props.theme.body_xs, textAlign: 'center', - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); function ExtendedScreenContainer(): JSX.Element { diff --git a/src/app/components/guards/auth.tsx b/src/app/components/guards/auth.tsx index 177cb4780..839848b77 100644 --- a/src/app/components/guards/auth.tsx +++ b/src/app/components/guards/auth.tsx @@ -1,20 +1,47 @@ -import useHasStateRehydrated from '@hooks/stores/useHasRehydrated'; +import { PropsWithChildren, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; -import { Navigate } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; +import { setWalletUnlockedAction } from '@stores/wallet/actions/actionCreators'; -function AuthGuard({ children }: React.PropsWithChildren) { - const { encryptedSeed, seedPhrase } = useWalletSelector(); - const hydrated = useHasStateRehydrated(); +function AuthGuard({ children }: PropsWithChildren) { + const navigate = useNavigate(); + const { masterPubKey, encryptedSeed, isUnlocked } = useWalletSelector(); + const { getSeed, hasSeed } = useSeedVault(); + const dispatch = useDispatch(); - if (hydrated && encryptedSeed && !seedPhrase) { - return ; - } + const tryAuthenticating = async () => { + try { + await getSeed(); + dispatch(setWalletUnlockedAction(true)); + } catch (error) { + navigate('/login'); + } + }; - if (hydrated && !encryptedSeed) { - return ; - } + const restoreSession = async () => { + if (encryptedSeed) { + navigate('/login'); + return; + } + const hasSeedPhrase = await hasSeed(); + if (!hasSeedPhrase || !masterPubKey) { + navigate('/landing'); + return; + } + await tryAuthenticating(); + }; - // fragment is required here + useEffect(() => { + restoreSession(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isUnlocked]); + + if (!isUnlocked) { + return null; + } + // fragment is required here because without it, the router thinks there could be more than 1 child node // eslint-disable-next-line react/jsx-no-useless-fragment return <>{children}; } diff --git a/src/app/components/guards/onboarding/index.tsx b/src/app/components/guards/onboarding/index.tsx index b9c70973c..df2ed38e0 100644 --- a/src/app/components/guards/onboarding/index.tsx +++ b/src/app/components/guards/onboarding/index.tsx @@ -1,10 +1,9 @@ -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Navigate } from 'react-router-dom'; - import { useSingleTabGuard } from '@components/guards/singleTab'; import useHasStateRehydrated from '@hooks/stores/useHasRehydrated'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; - import { WalletExistsContext, WalletExistsContextProps, @@ -23,18 +22,26 @@ function OnboardingGuard({ children }: WalletExistsGuardProps): React.ReactEleme useSingleTabGuard('onboarding'); const [walletExistsGuardEnabled, setWalletExistsGuardEnabled] = useState(true); - + const [isWalletInitialized, setIsWalletInitialized] = useState(false); + const { masterPubKey } = useWalletSelector(); + const { hasSeed } = useSeedVault(); const contextValue: WalletExistsContextProps = useMemo( () => ({ disableWalletExistsGuard: () => setWalletExistsGuardEnabled(false), }), [], ); + useEffect(() => { + (async () => { + const hasSeedPhrase = await hasSeed(); + setIsWalletInitialized(hasSeedPhrase); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - const { encryptedSeed } = useWalletSelector(); const hydrated = useHasStateRehydrated(); - if (walletExistsGuardEnabled && hydrated && encryptedSeed) { + if (walletExistsGuardEnabled && hydrated && isWalletInitialized && masterPubKey) { return ; } diff --git a/src/app/components/infoContainer/index.tsx b/src/app/components/infoContainer/index.tsx index 653a4f9ed..6c2d7654a 100644 --- a/src/app/components/infoContainer/index.tsx +++ b/src/app/components/infoContainer/index.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components'; import InfoIcon from '@assets/img/info.svg'; import WarningIcon from '@assets/img/Warning.svg'; +import styled from 'styled-components'; interface ContainerProps { type: 'Info' | 'Warning' | undefined; @@ -27,29 +27,29 @@ const TextContainer = styled.div((props) => ({ const BoldText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const RedirectText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const SubText = styled.h1((props) => ({ ...props.theme.body_xs, marginTop: props.theme.spacing(2), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const Text = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, lineHeight: 1.4, })); const RedirectButton = styled.button((props) => ({ backgroundColor: 'transparent', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, display: 'flex', marginTop: 4, justifyContent: 'flex-start', diff --git a/src/app/components/ledger/connectLedgerView/index.tsx b/src/app/components/ledger/connectLedgerView/index.tsx index baf5e6d3f..1efd937fa 100644 --- a/src/app/components/ledger/connectLedgerView/index.tsx +++ b/src/app/components/ledger/connectLedgerView/index.tsx @@ -23,7 +23,7 @@ export const ConnectLedgerTitle = styled.h1((props) => ({ export const ConnectLedgerText = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, textAlign: 'center', marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(4), diff --git a/src/app/components/ledger/failLedgerView/index.tsx b/src/app/components/ledger/failLedgerView/index.tsx index 070564211..7f6db6e46 100644 --- a/src/app/components/ledger/failLedgerView/index.tsx +++ b/src/app/components/ledger/failLedgerView/index.tsx @@ -22,7 +22,7 @@ const Title = styled.h1((props) => ({ const Text = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, textAlign: 'center', })); diff --git a/src/app/components/ledger/fullScreenHeader/index.tsx b/src/app/components/ledger/fullScreenHeader/index.tsx index ca738e657..fc1255f94 100644 --- a/src/app/components/ledger/fullScreenHeader/index.tsx +++ b/src/app/components/ledger/fullScreenHeader/index.tsx @@ -23,7 +23,7 @@ const XverseLogo = styled.img((props) => ({ const VersionText = styled.p((props) => ({ ...props.theme.body_xs, fontSize: '18px', - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); function FullScreenHeader() { diff --git a/src/app/components/ledger/ledgerAddressComponent/index.tsx b/src/app/components/ledger/ledgerAddressComponent/index.tsx index 2ae66a6cc..3d94f7f0e 100644 --- a/src/app/components/ledger/ledgerAddressComponent/index.tsx +++ b/src/app/components/ledger/ledgerAddressComponent/index.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components'; -import { Tooltip } from 'react-tooltip'; import { useState } from 'react'; +import { Tooltip } from 'react-tooltip'; +import styled from 'styled-components'; import copyIcon from '@assets/img/Copy.svg'; @@ -17,7 +17,7 @@ const AddressComponent = styled.p({ const AddressComponentTitle = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(2), })); diff --git a/src/app/components/ledger/ledgerAssetSelectCard/index.tsx b/src/app/components/ledger/ledgerAssetSelectCard/index.tsx index fd0af4a3b..2339b25a3 100644 --- a/src/app/components/ledger/ledgerAssetSelectCard/index.tsx +++ b/src/app/components/ledger/ledgerAssetSelectCard/index.tsx @@ -14,7 +14,7 @@ const CardContainer = styled.label((props) => ({ props.className === 'checked' ? props.theme.colors.background.selectBackground : 'transparent', borderRadius: props.theme.radius(2), border: `1px solid ${ - props.className === 'checked' ? props.theme.colors.border.select : props.theme.colors.white[900] + props.className === 'checked' ? props.theme.colors.border.select : props.theme.colors.white_900 }`, userSelect: 'none', })); @@ -36,7 +36,7 @@ const CardTitle = styled.h3((props) => ({ const CardText = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); interface Props { diff --git a/src/app/components/ledger/ledgerInput/index.tsx b/src/app/components/ledger/ledgerInput/index.tsx index e773f814a..be76d61bc 100644 --- a/src/app/components/ledger/ledgerInput/index.tsx +++ b/src/app/components/ledger/ledgerInput/index.tsx @@ -16,11 +16,11 @@ interface LedgerInputFieldProps { } const LedgerInputField = styled.input((props) => ({ ...props.theme.body_medium_m, - background: props.theme.colors.background.elevation_1, + background: props.theme.colors.elevation_n1, border: `1px solid ${props.error ? props.theme.colors.feedback.error : '#303354'}`, borderRadius: '8px', padding: '10px 16px', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, transition: 'border 0.2s ease', })); diff --git a/src/app/components/loadingTransactionStatus/circularSvgAnimation.tsx b/src/app/components/loadingTransactionStatus/circularSvgAnimation.tsx index 3175f2ef8..34594f0ad 100644 --- a/src/app/components/loadingTransactionStatus/circularSvgAnimation.tsx +++ b/src/app/components/loadingTransactionStatus/circularSvgAnimation.tsx @@ -1,7 +1,7 @@ -import className from 'classnames'; -import styled from 'styled-components'; import { animated, easings, useSpring } from '@react-spring/web'; +import className from 'classnames'; import { useEffect, useState } from 'react'; +import styled from 'styled-components'; import Theme from 'theme'; const svgSize = 88; @@ -13,8 +13,8 @@ export type ConfirmationStatus = 'LOADING' | 'SUCCESS' | 'FAILURE'; const getStrokeColorByStatus = (status: ConfirmationStatus) => ({ LOADING: Theme.colors.white_0, - SUCCESS: Theme.colors.success, - FAILURE: Theme.colors.error, + SUCCESS: Theme.colors.success_medium, + FAILURE: Theme.colors.danger_dark_600, }[status]); const StyledSvg = styled.svg<{ status: ConfirmationStatus; loadingPercentage: number }>` diff --git a/src/app/components/optionsDialog/optionsDialog.tsx b/src/app/components/optionsDialog/optionsDialog.tsx index 341725e30..084d8cbf9 100644 --- a/src/app/components/optionsDialog/optionsDialog.tsx +++ b/src/app/components/optionsDialog/optionsDialog.tsx @@ -12,7 +12,7 @@ const Container = styled.div((props) => ({ paddingTop: 11, paddingBottom: 11, width: OPTIONS_DIALOG_WIDTH, - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, userSelect: 'none', })); diff --git a/src/app/components/passwordInput/index.tsx b/src/app/components/passwordInput/index.tsx index 3a9ea133d..81c86763a 100644 --- a/src/app/components/passwordInput/index.tsx +++ b/src/app/components/passwordInput/index.tsx @@ -1,11 +1,11 @@ -import { useTranslation } from 'react-i18next'; -import styled, { useTheme } from 'styled-components'; import Eye from '@assets/img/createPassword/Eye.svg'; import EyeSlash from '@assets/img/createPassword/EyeSlash.svg'; import PasswordIcon from '@assets/img/createPassword/Password.svg'; -import { useEffect, useState } from 'react'; import ActionButton from '@components/button'; import { animated, useTransition } from '@react-spring/web'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled, { useTheme } from 'styled-components'; import zxcvbn from 'zxcvbn'; interface PasswordInputProps { @@ -53,10 +53,8 @@ const PasswordInputContainer = styled.div((props) = display: 'flex', alignItems: 'center', width: '100%', - border: `1px solid ${ - props.hasError ? 'rgba(211, 60, 60, 0.3)' : props.theme.colors.background.elevation3 - }`, - backgroundColor: props.theme.colors.background.elevation_1, + border: `1px solid ${props.hasError ? 'rgba(211, 60, 60, 0.3)' : props.theme.colors.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: props.theme.radius(1), paddingLeft: props.theme.spacing(4), paddingRight: props.theme.spacing(4), @@ -73,8 +71,8 @@ const PasswordInputLabel = styled.h2((props) => ({ const Input = styled.input((props) => ({ ...props.theme.body_medium_m, height: 44, - backgroundColor: props.theme.colors.background.elevation_1, - color: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.elevation_n1, + color: props.theme.colors.white_0, width: '100%', border: 'none', })); @@ -121,7 +119,7 @@ const StrengthBar = styled(animated.div)((props) => ({ display: 'flex', flex: '1 0', alignItems: 'center', - backgroundColor: props.theme.colors.white[600], + backgroundColor: props.theme.colors.white_600, marginLeft: props.theme.spacing(6), marginRight: props.theme.spacing(9), borderRadius: props.theme.radius(1), @@ -284,7 +282,7 @@ function PasswordInput(props: PasswordInputProps): JSX.Element { return ( {t('PASSWORD_STRENGTH_LABEL')} - + {transition((style) => ( ))} diff --git a/src/app/components/receiveCardComponent/index.tsx b/src/app/components/receiveCardComponent/index.tsx index 15f3e00de..2308ca67d 100644 --- a/src/app/components/receiveCardComponent/index.tsx +++ b/src/app/components/receiveCardComponent/index.tsx @@ -50,13 +50,13 @@ const ButtonIcon = styled.img({ const TitleText = styled.h1((props) => ({ ...props.theme.body_bold_m, marginTop: props.theme.spacing(3), - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const AddressText = styled.h1((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(1), - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const StyledTooltip = styled(Tooltip)` diff --git a/src/app/components/recipientAddressView/index.tsx b/src/app/components/recipientAddressView/index.tsx index bc897a607..cdc3d5d75 100644 --- a/src/app/components/recipientAddressView/index.tsx +++ b/src/app/components/recipientAddressView/index.tsx @@ -1,9 +1,9 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; -import { getExplorerUrl } from '@utils/helper'; import { useBnsName } from '@hooks/queries/useBnsName'; import useNetworkSelector from '@hooks/useNetwork'; +import { getExplorerUrl } from '@utils/helper'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const InfoContainer = styled.div((props) => ({ display: 'flex', @@ -23,7 +23,7 @@ const AddressContainer = styled.div({ const TitleText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textTransform: 'uppercase', })); @@ -37,7 +37,7 @@ const AssociatedAddressText = styled.h1((props) => ({ ...props.theme.body_m, marginTop: props.theme.spacing(2), wordBreak: 'break-all', - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const ButtonImage = styled.img((props) => ({ diff --git a/src/app/components/recipientComponent/index.tsx b/src/app/components/recipientComponent/index.tsx index 075d12757..222bf0d8b 100644 --- a/src/app/components/recipientComponent/index.tsx +++ b/src/app/components/recipientComponent/index.tsx @@ -1,24 +1,24 @@ -import TransferDetailView from '@components/transferDetailView'; -import OutputIcon from '@assets/img/transactions/output.svg'; import ArrowIcon from '@assets/img/transactions/ArrowDown.svg'; +import OutputIcon from '@assets/img/transactions/output.svg'; import WalletIcon from '@assets/img/transactions/wallet.svg'; +import TokenImage from '@components/tokenImage'; +import TransferDetailView from '@components/transferDetailView'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { CubeTransparent } from '@phosphor-icons/react'; +import { FungibleToken, getFiatEquivalent } from '@secretkeylabs/xverse-core'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; +import { CurrencyTypes } from '@utils/constants'; +import { getTicker } from '@utils/helper'; import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; -import { FungibleToken, getFiatEquivalent } from '@secretkeylabs/xverse-core'; -import TokenImage from '@components/tokenImage'; -import { CurrencyTypes } from '@utils/constants'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { useEffect, useState } from 'react'; -import { getTicker } from '@utils/helper'; -import { CubeTransparent } from '@phosphor-icons/react'; const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '16px 16px', justifyContent: 'center', @@ -27,7 +27,7 @@ const Container = styled.div((props) => ({ const RecipientTitleText = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: 16, })); @@ -59,20 +59,20 @@ const DownArrowIcon = styled.img((props) => ({ const TitleText = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, textAlign: 'center', marginTop: 5, })); const ValueText = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const SubValueText = styled.p((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const ColumnContainer = styled.div({ diff --git a/src/app/components/resetWallet/index.tsx b/src/app/components/resetWallet/index.tsx index 67b60c9ca..da1f389cc 100644 --- a/src/app/components/resetWallet/index.tsx +++ b/src/app/components/resetWallet/index.tsx @@ -5,7 +5,7 @@ import styled from 'styled-components'; const ResetWalletText = styled.h1((props) => ({ ...props.theme.body_l, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, paddingLeft: props.theme.spacing(8), paddingRight: props.theme.spacing(8), paddingTop: props.theme.spacing(12), diff --git a/src/app/components/screenContainer/index.tsx b/src/app/components/screenContainer/index.tsx index e6405001d..a41c64877 100644 --- a/src/app/components/screenContainer/index.tsx +++ b/src/app/components/screenContainer/index.tsx @@ -1,4 +1,5 @@ import useWalletSelector from '@hooks/useWalletSelector'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Outlet } from 'react-router-dom'; import styled from 'styled-components'; @@ -9,7 +10,7 @@ const RouteContainer = styled.div((props) => ({ height: '100%', width: 360, margin: 'auto', - backgroundColor: props.theme.colors.background.elevation0, + backgroundColor: props.theme.colors.elevation0, border: '1px solid rgba(126, 137,171,0.2)', boxShadow: '0px 8px 28px rgba(0, 0, 0, 0.35)', })); @@ -18,7 +19,7 @@ const TestnetContainer = styled.div((props) => ({ display: 'flex', alignItems: 'center', justifyContent: 'center', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, paddingTop: props.theme.spacing(3), paddingBottom: props.theme.spacing(3), })); @@ -26,13 +27,21 @@ const TestnetContainer = styled.div((props) => ({ const TestnetText = styled.h1((props) => ({ ...props.theme.body_xs, textAlign: 'center', - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); function ScreenContainer(): JSX.Element { const { network } = useWalletSelector(); const { t } = useTranslation('translation'); + // We need to set the max height of the app container after the layout is rendered + // to prevent the app from being too tall on smaller screens + // If we set it directly in the css, it will lock the popup to a tiny height before it has a chance to render + useEffect(() => { + const container = document.getElementById('app'); + container!.style.maxHeight = '100vh'; + }, []); + return ( {network.type === 'Testnet' && ( diff --git a/src/app/components/seedPhraseInput/index.tsx b/src/app/components/seedPhraseInput/index.tsx index 8ed926c30..8d51315fb 100644 --- a/src/app/components/seedPhraseInput/index.tsx +++ b/src/app/components/seedPhraseInput/index.tsx @@ -1,7 +1,7 @@ +import { Eye, EyeSlash } from '@phosphor-icons/react'; import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { Eye, EyeSlash } from '@phosphor-icons/react'; const Label = styled.label` ${(props) => props.theme.body_medium_m}; @@ -17,15 +17,15 @@ const Input = styled.input` ${(props) => props.theme.body_medium_m}; max-width: 144px; min-height: ${(props) => props.theme.spacing(22)}px; - background-color: ${(props) => props.theme.colors.background.elevation0}; - color: ${(props) => props.theme.colors.white['0']}; - border: 1px solid ${(props) => props.theme.colors.background.elevation3}; + background-color: ${(props) => props.theme.colors.elevation0}; + color: ${(props) => props.theme.colors.white_0}; + border: 1px solid ${(props) => props.theme.colors.elevation3}; border-radius: ${(props) => props.theme.radius(1)}px; padding: ${(props) => props.theme.spacing(8)}px ${(props) => props.theme.spacing(6)}px; padding-right: ${(props) => props.theme.spacing(26)}px; - caret-color: ${(props) => props.theme.colors.background.elevation6}; + caret-color: ${(props) => props.theme.colors.elevation6}; :focus-within { - border: 1px solid ${(props) => props.theme.colors.background.elevation6}; + border: 1px solid ${(props) => props.theme.colors.elevation6}; } `; @@ -33,7 +33,7 @@ const Icon = styled.i` position: absolute; vertical-align: middle; background-color: transparent; - color: ${(props) => props.theme.colors.white['0']}; + color: ${(props) => props.theme.colors.white_0}; border: none; height: 100%; right: 0; @@ -120,7 +120,7 @@ const TransparentButton = styled.button` ${(props) => props.theme.body_m}; background-color: transparent; border: none; - color: ${(props) => props.theme.colors.white['200']}; + color: ${(props) => props.theme.colors.white_200}; text-decoration: underline; `; diff --git a/src/app/components/seedPhraseView/index.tsx b/src/app/components/seedPhraseView/index.tsx index ca1133c7a..814ca4073 100644 --- a/src/app/components/seedPhraseView/index.tsx +++ b/src/app/components/seedPhraseView/index.tsx @@ -30,16 +30,16 @@ const SeedContainer = styled.div((props) => ({ })); const OuterSeedContainer = styled.div((props) => ({ - backgroundColor: props.theme.colors.background.elevation_1, - border: `1px solid ${props.theme.colors.background.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, + border: `1px solid ${props.theme.colors.elevation3}`, borderRadius: props.theme.radius(1), })); const ShowSeedButton = styled.button((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[0], - backgroundColor: props.theme.colors.white[900], - border: `1px solid ${props.theme.colors.white[600]}`, + color: props.theme.colors.white_0, + backgroundColor: props.theme.colors.white_900, + border: `1px solid ${props.theme.colors.white_600}`, height: 36, width: 110, borderRadius: 48, @@ -54,18 +54,18 @@ const ShowSeedButton = styled.button((props) => ({ marginRight: props.theme.spacing(4), }, ':hover': { - backgroundColor: props.theme.colors.white[850], - border: `1px solid ${props.theme.colors.white[800]}`, + backgroundColor: props.theme.colors.white_850, + border: `1px solid ${props.theme.colors.white_800}`, }, ':focus': { - backgroundColor: props.theme.colors.white[600], - border: `1px solid ${props.theme.colors.white[800]}`, + backgroundColor: props.theme.colors.white_600, + border: `1px solid ${props.theme.colors.white_800}`, }, })); export default function SeedphraseView(props: SeedPhraseViewProps) { const { seedPhrase, isVisible, setIsVisible } = props; - const seedPhraseWords = useMemo(() => seedPhrase?.split(' '), [seedPhrase]); + const seedPhraseWords = seedPhrase?.split(' '); const handleToggleVisibility = () => { setIsVisible(!isVisible); diff --git a/src/app/components/seedPhraseView/word.tsx b/src/app/components/seedPhraseView/word.tsx index 531a672a0..7c100c3da 100644 --- a/src/app/components/seedPhraseView/word.tsx +++ b/src/app/components/seedPhraseView/word.tsx @@ -10,7 +10,7 @@ const OrdinalNumber = styled.p((props) => ({ marginLeft: props.theme.spacing(7), marginRight: props.theme.spacing(1.5), marginTop: props.theme.spacing(16), - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const Container = styled.div({ diff --git a/src/app/components/sendForm/index.tsx b/src/app/components/sendForm/index.tsx index 2fd9310d8..38e4e060d 100644 --- a/src/app/components/sendForm/index.tsx +++ b/src/app/components/sendForm/index.tsx @@ -1,23 +1,25 @@ -import { CurrencyTypes } from '@utils/constants'; -import { FungibleToken } from '@secretkeylabs/xverse-core/types'; -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import { ReactNode, SetStateAction, useEffect, useState } from 'react'; -import { getTicker } from '@utils/helper'; import ActionButton from '@components/button'; -import { useNavigate } from 'react-router-dom'; -import { useBnsName, useBNSResolver } from '@hooks/queries/useBnsName'; -import { getFiatEquivalent } from '@secretkeylabs/xverse-core/transactions'; import InfoContainer from '@components/infoContainer'; -import useNetworkSelector from '@hooks/useNetwork'; import TokenImage from '@components/tokenImage'; -import { getBtcEquivalent, getStxTokenEquivalent } from '@secretkeylabs/xverse-core'; -import BigNumber from 'bignumber.js'; -import { getCurrencyFlag } from '@utils/currency'; +import { useBnsName, useBNSResolver } from '@hooks/queries/useBnsName'; import useDebounce from '@hooks/useDebounce'; +import useNetworkSelector from '@hooks/useNetwork'; import useWalletSelector from '@hooks/useWalletSelector'; -import useClearFormOnAccountSwitch from './useClearFormOnAccountSwitch'; +import { getBtcEquivalent, getStxTokenEquivalent } from '@secretkeylabs/xverse-core'; +import { getFiatEquivalent } from '@secretkeylabs/xverse-core/transactions'; +import { FungibleToken } from '@secretkeylabs/xverse-core/types'; +import InputFeedback from '@ui-library/inputFeedback'; +import { CurrencyTypes } from '@utils/constants'; +import { getCurrencyFlag } from '@utils/currency'; +import { getTicker } from '@utils/helper'; +import BigNumber from 'bignumber.js'; +import { ReactNode, SetStateAction, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import { FiatRow } from './fiatRow'; +import useClearFormOnAccountSwitch from './useClearFormOnAccountSwitch'; interface ContainerProps { error: boolean; @@ -57,10 +59,6 @@ const OrdinalInfoContainer = styled.div((props) => ({ marginTop: props.theme.spacing(6), })); -const ErrorContainer = styled.div((props) => ({ - marginTop: props.theme.spacing(3), -})); - const MemoContainer = styled.div((props) => ({ marginTop: props.theme.spacing(3), marginBottom: props.theme.spacing(6), @@ -89,7 +87,7 @@ const SubText = styled.h1((props) => ({ ...props.theme.body_xs, display: 'flex', flex: 1, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const AssociatedText = styled.h1((props) => ({ @@ -99,14 +97,14 @@ const AssociatedText = styled.h1((props) => ({ const BalanceText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginRight: props.theme.spacing(2), })); const InputField = styled.input((props) => ({ ...props.theme.body_m, - backgroundColor: props.theme.colors.background.elevation_1, - color: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.elevation_n1, + color: props.theme.colors.white_0, width: '100%', border: 'transparent', })); @@ -119,14 +117,14 @@ const AmountInputContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(4), border: props.error ? '1px solid rgba(211, 60, 60, 0.3)' - : `1px solid ${props.theme.colors.background.elevation3}`, - backgroundColor: props.theme.colors.background.elevation_1, - borderRadius: 8, + : `1px solid ${props.theme.colors.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, + borderRadius: props.theme.radius(1), paddingLeft: props.theme.spacing(5), paddingRight: props.theme.spacing(5), height: 44, ':focus-within': { - border: `1px solid ${props.theme.colors.background.elevation6}`, + border: `1px solid ${props.theme.colors.elevation6}`, }, })); @@ -137,26 +135,21 @@ const MemoInputContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(4), border: props.error ? '1px solid rgba(211, 60, 60, 0.3)' - : `1px solid ${props.theme.colors.background.elevation3}`, - backgroundColor: props.theme.colors.background.elevation_1, - borderRadius: 8, + : `1px solid ${props.theme.colors.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, + borderRadius: props.theme.radius(1), padding: props.theme.spacing(7), height: 76, ':focus-within': { - border: `1px solid ${props.theme.colors.background.elevation6}`, + border: `1px solid ${props.theme.colors.elevation6}`, }, })); -interface ButtonProps { - enabled: boolean; -} - -const SendButtonContainer = styled.div((props) => ({ +const SendButtonContainer = styled.div((props) => ({ paddingBottom: props.theme.spacing(12), paddingTop: props.theme.spacing(4), marginLeft: '5%', marginRight: '5%', - opacity: props.enabled ? 1 : 0.6, })); const CurrencyFlag = styled.img((props) => ({ @@ -170,6 +163,10 @@ const TokenContainer = styled.div((props) => ({ marginTop: props.theme.spacing(8), })); +const StyledInputFeedback = styled(InputFeedback)((props) => ({ + marginBottom: props.theme.spacing(4), +})); + interface Props { onPressSend: (recipientID: string, amount: string, memo?: string) => void; currencyType: CurrencyTypes; @@ -181,6 +178,7 @@ interface Props { balance?: number; hideMemo?: boolean; hideTokenImage?: boolean; + hideDefaultWarning?: boolean; buttonText?: string; processing?: boolean; children?: ReactNode; @@ -189,6 +187,7 @@ interface Props { stxMemo?: string; onAddressInputChange?: (recipientAddress: string) => void; warning?: string; + info?: string; } function SendForm({ @@ -202,6 +201,7 @@ function SendForm({ balance, hideMemo = false, hideTokenImage = false, + hideDefaultWarning = false, buttonText, processing, children, @@ -210,6 +210,7 @@ function SendForm({ stxMemo, onAddressInputChange, warning, + info, }: Props) { const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); // TODO tim: use context instead of duplicated local state and parent state (as props) @@ -334,7 +335,12 @@ function SendForm({ {t('AMOUNT')} {t('BALANCE')}: - {balance} + {value}} + /> @@ -430,10 +436,10 @@ function SendForm({ let displayedWarning = ''; if (warning) { displayedWarning = warning; - } else { + } else if (!hideDefaultWarning) { switch (currencyType) { case 'Ordinal': - displayedWarning = t('SEND_ORDINAL_WALLET_WARNING'); + displayedWarning = t('MAKE_SURE_THE_RECIPIENT'); break; case 'brc20-Ordinal': displayedWarning = t('SEND_BRC20_ORDINAL_WALLET_WARNING'); @@ -460,15 +466,12 @@ function SendForm({ )} {!disableAmountInput && renderEnterAmountSection} - - {amountError} - + {amountError && } {buyCryptoMessage} {children} {renderEnterRecipientSection} - - {addressError} - + {addressError && } + {info && } {currencyType !== 'BTC' && currencyType !== 'NFT' && currencyType !== 'Ordinal' && @@ -502,10 +505,11 @@ function SendForm({ )} - + diff --git a/src/app/components/shareNft/index.tsx b/src/app/components/shareNft/index.tsx index 8a23bd4b3..d1e694f4b 100644 --- a/src/app/components/shareNft/index.tsx +++ b/src/app/components/shareNft/index.tsx @@ -1,11 +1,11 @@ -import styled, { useTheme } from 'styled-components'; -import { FacebookShareButton, TwitterShareButton, EmailShareButton } from 'react-share'; -import { useTranslation } from 'react-i18next'; -import FBIcon from '@assets/img/nftDashboard/shareNft/facebook-f.svg'; +import Cross from '@assets/img/dashboard/X.svg'; import EmailIcon from '@assets/img/nftDashboard/shareNft/Envelope.svg'; +import FBIcon from '@assets/img/nftDashboard/shareNft/facebook-f.svg'; import LinkIcon from '@assets/img/nftDashboard/shareNft/Link.svg'; import TwitterIcon from '@assets/img/nftDashboard/shareNft/Vector.svg'; -import Cross from '@assets/img/dashboard/X.svg'; +import { useTranslation } from 'react-i18next'; +import { EmailShareButton, FacebookShareButton, TwitterShareButton } from 'react-share'; +import styled, { useTheme } from 'styled-components'; import ShareLinkRow from './shareLinkRow'; const Container = styled.button((props) => ({ @@ -18,7 +18,7 @@ const Container = styled.button((props) => ({ paddingBottom: props.theme.spacing(4), borderRadius: 12, width: 220, - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, })); const CrossContainer = styled.button(() => ({ @@ -59,7 +59,7 @@ function ShareDialog({ url, onCrossClick }: Props) { diff --git a/src/app/components/shareNft/shareLinkRow.tsx b/src/app/components/shareNft/shareLinkRow.tsx index bfaf1be51..cbe598070 100644 --- a/src/app/components/shareNft/shareLinkRow.tsx +++ b/src/app/components/shareNft/shareLinkRow.tsx @@ -34,7 +34,7 @@ const ImgContainer = styled.div((props) => ({ const Text = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(6), })); diff --git a/src/app/components/smallActionButton/index.tsx b/src/app/components/smallActionButton/index.tsx index 06763c8a9..257f833a7 100644 --- a/src/app/components/smallActionButton/index.tsx +++ b/src/app/components/smallActionButton/index.tsx @@ -10,14 +10,14 @@ const Button = styled.div((props) => ({ justifyContent: 'center', borderRadius: 16, backgroundColor: props.isOpaque - ? props.theme.colors.background.elevation2 + ? props.theme.colors.elevation2 : props.theme.colors.action.classic, width: 48, height: 48, transition: 'background-color 0.2s ease, opacity 0.2s ease', ':hover': { backgroundColor: props.isOpaque - ? props.theme.colors.background.elevation2 + ? props.theme.colors.elevation2 : props.theme.colors.action.classicLight, opacity: props.isOpaque ? 0.85 : 0.6, }, @@ -25,12 +25,12 @@ const Button = styled.div((props) => ({ const TransparentButton = styled(Button)` background-color: transparent; - border: ${(props) => `1px solid ${props.theme.colors.background.elevation6}`}; + border: ${(props) => `1px solid ${props.theme.colors.elevation6}`}; `; const AnimatedTransparentButton = styled(TransparentButton)` :hover { - background: ${(props) => props.theme.colors.background.elevation6_800}; + background: ${(props) => props.theme.colors.elevation6_800}; } `; diff --git a/src/app/components/stepper/index.tsx b/src/app/components/stepper/index.tsx index c65c145ed..d73bdb191 100644 --- a/src/app/components/stepper/index.tsx +++ b/src/app/components/stepper/index.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import checkmarkIcon from '@assets/img/checkmarkIcon.svg'; +import styled from 'styled-components'; interface StepperProps { isActive?: boolean; @@ -17,13 +17,13 @@ const Title = styled.div((props) => ({ marginTop: props.theme.spacing(8), fontSize: '0.875rem', fontWeight: 500, - color: props.isActive ? props.theme.colors.white[0] : props.theme.colors.white[600], + color: props.isActive ? props.theme.colors.white_0 : props.theme.colors.white_600, transition: 'color 0.3s ease', })); const getBackgroundColor = (props) => { if (props.isCompleted) { - return props.theme.colors.feedback.success; + return props.theme.colors.success_medium; } if (props.isActive) { return '#4C525F'; @@ -36,12 +36,14 @@ const Dot = styled.div((props) => ({ width: 30, backgroundColor: getBackgroundColor(props), border: '2px solid', - borderColor: props.isCompleted ? props.theme.colors.feedback.success : '#4C525F', + borderColor: props.isCompleted + ? props.theme.colors.success_medium + : props.theme.colors.elevation6, borderRadius: '50%', display: 'flex', justifyContent: 'center', alignItems: 'center', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontWeight: 'bold', fontSize: '0.875rem', flex: '1 0 auto', @@ -53,15 +55,15 @@ const Dot = styled.div((props) => ({ width: 8, height: 8, borderRadius: '50%', - backgroundColor: props.theme.colors.white[0], + backgroundColor: props.theme.colors.white_0, }, })); const calculateColorStops = (props) => { - const successColor = props.theme.colors.feedback.success; + const successColor = props.theme.colors.success_medium; // Calculate the color stops - let startStop; + let startStop: string; if (props.step === 0) startStop = '0%'; if (props.step > 1) startStop = '100%'; else startStop = '50%'; @@ -70,7 +72,8 @@ const calculateColorStops = (props) => { return `${successColor} ${startStop}, #4C525F ${endStop}`; }; -const Line = styled.div((props) => ({ +type LineProps = { step: number }; +const Line = styled.div((props) => ({ height: 2, width: '100%', background: `linear-gradient(90deg, ${calculateColorStops(props)})`, @@ -86,7 +89,7 @@ export default function Stepper({ steps }: Props): JSX.Element { const currentStepIndex = steps.findIndex((step) => !step.isCompleted); const currentStep = currentStepIndex > -1 ? currentStepIndex : steps.length; - function getContentForDot(stepIndex, isCompleted, currentPosition) { + function getContentForDot(stepIndex: number, isCompleted: boolean, currentPosition: number) { if (isCompleted) { return Check Icon; } diff --git a/src/app/components/steps/index.tsx b/src/app/components/steps/index.tsx index 8e902079d..eb8d8ca76 100644 --- a/src/app/components/steps/index.tsx +++ b/src/app/components/steps/index.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import { nanoid } from 'nanoid'; +import styled from 'styled-components'; const StepsContainer = styled.div({ display: 'flex', @@ -11,9 +11,7 @@ const StepsDot = styled.div((props) => ({ width: 8, height: 8, borderRadius: 4, - backgroundColor: props.active - ? props.theme.colors.action.classic - : props.theme.colors.background.elevation3, + backgroundColor: props.active ? props.theme.colors.action.classic : props.theme.colors.elevation3, marginRight: props.theme.spacing(4), })); diff --git a/src/app/components/tabBar/index.tsx b/src/app/components/tabBar/index.tsx index 1c3cff69a..3bd6786fc 100644 --- a/src/app/components/tabBar/index.tsx +++ b/src/app/components/tabBar/index.tsx @@ -13,7 +13,7 @@ const RowContainer = styled.div((props) => ({ justifyContent: 'space-between', paddingLeft: props.theme.spacing(30), paddingRight: props.theme.spacing(30), - borderTop: `1px solid ${props.theme.colors.background.elevation3}`, + borderTop: `1px solid ${props.theme.colors.elevation3}`, })); const MovingDiv = styled(animated.div)((props) => ({ diff --git a/src/app/components/tokenImage/index.tsx b/src/app/components/tokenImage/index.tsx index 9503ff0f2..fc6fdf5fb 100644 --- a/src/app/components/tokenImage/index.tsx +++ b/src/app/components/tokenImage/index.tsx @@ -1,12 +1,12 @@ -import styled from 'styled-components'; import IconBitcoin from '@assets/img/dashboard/bitcoin_icon.svg'; import IconStacks from '@assets/img/dashboard/stack_icon.svg'; -import { useCallback } from 'react'; import BarLoader from '@components/barLoader'; -import stc from 'string-to-color'; +import { FungibleToken } from '@secretkeylabs/xverse-core'; import { LoaderSize } from '@utils/constants'; import { getTicker } from '@utils/helper'; -import { FungibleToken } from '@secretkeylabs/xverse-core'; +import { useCallback } from 'react'; +import stc from 'string-to-color'; +import styled from 'styled-components'; export interface TokenImageProps { token?: string; @@ -39,7 +39,7 @@ const TickerIconContainer = styled.div<{ size?: number; round?: boolean }>((prop const TickerIconText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', wordBreak: 'break-all', fontSize: 13, diff --git a/src/app/components/tokenTile/index.tsx b/src/app/components/tokenTile/index.tsx index 21715c80a..0ba643f25 100644 --- a/src/app/components/tokenTile/index.tsx +++ b/src/app/components/tokenTile/index.tsx @@ -1,16 +1,16 @@ -import BigNumber from 'bignumber.js'; -import styled from 'styled-components'; -import { NumericFormat } from 'react-number-format'; -import { CurrencyTypes, LoaderSize } from '@utils/constants'; -import BarLoader from '@components/barLoader'; -import { getTicker } from '@utils/helper'; -import stc from 'string-to-color'; +import { BetterBarLoader } from '@components/barLoader'; +import { microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core/currency'; import { FungibleToken } from '@secretkeylabs/xverse-core/types'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; import { StoreState } from '@stores/index'; -import { useSelector } from 'react-redux'; -import { microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core/currency'; +import { CurrencyTypes } from '@utils/constants'; +import { getTicker } from '@utils/helper'; import { getFtBalance, getFtTicker } from '@utils/tokens'; +import BigNumber from 'bignumber.js'; +import { NumericFormat } from 'react-number-format'; +import { useSelector } from 'react-redux'; +import stc from 'string-to-color'; +import styled from 'styled-components'; interface TileProps { margin?: number; @@ -54,14 +54,14 @@ const TickerIconContainer = styled.div((props) => ({ const TickerIconText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', wordBreak: 'break-all', fontSize: 10, })); const RowContainer = styled.div({ - flex: 1, + flex: '1 0 auto', display: 'flex', }); @@ -76,42 +76,45 @@ const AmountContainer = styled.div({ alignContent: 'flex-end', }); -const LoaderMainContainer = styled.div((props) => ({ - flex: 1, - maxWidth: 200, +const LoaderMainContainer = styled.div({ + flex: '1 1 auto', + display: 'flex', flexDirection: 'column', alignItems: 'flex-end', - justifyContent: 'flex-end', - marginLeft: props.theme.spacing(15), -})); - -const LoaderImageContainer = styled.div({ - flex: 0.5, - maxWidth: 40, }); +const LoaderImageContainer = styled.div((props) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + marginRight: props.theme.spacing(3), +})); + const CoinTickerText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const SubText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, fontSize: 12, textAlign: 'left', + maxWidth: 100, + overflow: 'hidden', + textOverflow: 'ellipsis', })); const FiatAmountText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, fontSize: 12, textAlign: 'end', })); const CoinBalanceText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'end', })); @@ -132,20 +135,29 @@ const ProtocolText = styled.p((props) => ({ fontWeight: '700', textTransform: 'uppercase', marginLeft: props.theme.spacing(5), - backgroundColor: props.theme.colors.white['400'], + backgroundColor: props.theme.colors.white_400, padding: '2px 6px 1px', borderRadius: props.theme.radius(2), whiteSpace: 'nowrap', })); +const StyledBarLoader = styled(BetterBarLoader)<{ + withMarginBottom?: boolean; +}>((props) => ({ + padding: 0, + borderRadius: props.theme.radius(1), + marginBottom: props.withMarginBottom ? props.theme.spacing(2) : 0, +})); + function TokenLoader() { return ( - - + + ); } + interface Props { title: string; icon?: string; @@ -320,7 +332,7 @@ function TokenTile({ } return ( - + ); } diff --git a/src/app/components/topRow/index.tsx b/src/app/components/topRow/index.tsx index 3feee8f44..ed4a6b966 100644 --- a/src/app/components/topRow/index.tsx +++ b/src/app/components/topRow/index.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; +import styled from 'styled-components'; const TopSectionContainer = styled.div((props) => ({ display: 'flex', @@ -29,11 +29,11 @@ const BackButton = styled.button({ const AnimatedBackButton = styled(BackButton)` :hover { - background: ${(props) => props.theme.colors.white[900]}; + background: ${(props) => props.theme.colors.white_900}; border-radius: 24px; } :focus { - background: ${(props) => props.theme.colors.white[850]}; + background: ${(props) => props.theme.colors.white_850}; border-radius: 24px; } `; @@ -42,11 +42,12 @@ interface Props { title: string; onClick: () => void; showBackButton?: boolean; + className?: string; } -function TopRow({ title, onClick, showBackButton = true }: Props) { +function TopRow({ title, onClick, showBackButton = true, className }: Props) { return ( - + {showBackButton && ( back button diff --git a/src/app/components/transactionDetailComponent/index.tsx b/src/app/components/transactionDetailComponent/index.tsx index b55874071..cfde311b3 100644 --- a/src/app/components/transactionDetailComponent/index.tsx +++ b/src/app/components/transactionDetailComponent/index.tsx @@ -1,14 +1,14 @@ -import styled from 'styled-components'; -import { NumericFormat } from 'react-number-format'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; -import { useSelector } from 'react-redux'; -import BigNumber from 'bignumber.js'; import { StoreState } from '@stores/index'; +import BigNumber from 'bignumber.js'; +import { NumericFormat } from 'react-number-format'; +import { useSelector } from 'react-redux'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -18,19 +18,19 @@ const Container = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const SubValueText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, textAlign: 'right', - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const ColumnContainer = styled.div({ diff --git a/src/app/components/transactionSetting/editFee.tsx b/src/app/components/transactionSetting/editFee.tsx index bc3a67b8e..bf51ea681 100644 --- a/src/app/components/transactionSetting/editFee.tsx +++ b/src/app/components/transactionSetting/editFee.tsx @@ -1,24 +1,24 @@ -import BigNumber from 'bignumber.js'; -import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; +import useDebounce from '@hooks/useDebounce'; +import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { BtcUtxoDataResponse, ErrorCodes, UTXO } from '@secretkeylabs/xverse-core'; import { getBtcFiatEquivalent, getStxFiatEquivalent, stxToMicrostacks, } from '@secretkeylabs/xverse-core/currency'; -import { useEffect, useMemo, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { NumericFormat } from 'react-number-format'; import { getBtcFees, getBtcFeesForNonOrdinalBtcSend, getBtcFeesForOrdinalSend, Recipient, } from '@secretkeylabs/xverse-core/transactions/btc'; -import { BtcUtxoDataResponse, ErrorCodes, UTXO } from '@secretkeylabs/xverse-core'; -import useDebounce from '@hooks/useDebounce'; -import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; +import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; +import BigNumber from 'bignumber.js'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -30,12 +30,12 @@ const Container = styled.div((props) => ({ const FiatAmountText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const DetailText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(8), })); @@ -54,9 +54,9 @@ const InputContainer = styled.div((props) => ({ marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(6), border: `1px solid ${ - props.withError ? props.theme.colors.feedback.error : props.theme.colors.background.elevation6 + props.withError ? props.theme.colors.feedback.error : props.theme.colors.elevation6 }`, - backgroundColor: props.theme.colors.background.elevation1, + backgroundColor: props.theme.colors.elevation1, borderRadius: props.theme.radius(1), paddingLeft: props.theme.spacing(5), paddingRight: props.theme.spacing(5), @@ -67,7 +67,7 @@ const InputContainer = styled.div((props) => ({ const InputField = styled.input((props) => ({ ...props.theme.body_m, backgroundColor: 'transparent', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, border: 'transparent', width: '50%', '&::-webkit-outer-spin-button': { @@ -85,12 +85,12 @@ const InputField = styled.input((props) => ({ const FeeText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const SubText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); interface ButtonProps { @@ -100,13 +100,9 @@ interface ButtonProps { } const FeeButton = styled.button((props) => ({ ...props.theme.body_medium_m, - color: `${ - props.isSelected ? props.theme.colors.background.elevation2 : props.theme.colors.white['400'] - }`, + color: `${props.isSelected ? props.theme.colors.elevation2 : props.theme.colors.white_400}`, background: `${props.isSelected ? props.theme.colors.white : 'transparent'}`, - border: `1px solid ${ - props.isSelected ? 'transparent' : props.theme.colors.background.elevation6 - }`, + border: `1px solid ${props.isSelected ? 'transparent' : props.theme.colors.elevation6}`, borderRadius: 40, width: props.isBtc ? 104 : 82, height: 40, @@ -233,7 +229,7 @@ function EditFee({ btcAddress, nonOrdinalUtxos!, ordinalsAddress, - 'Mainnet', + network.type, mode, ); setFeeRateInput(selectedFeeRate?.toString() || ''); @@ -292,7 +288,7 @@ function EditFee({ btcAddress, nonOrdinalUtxos!, ordinalsAddress, - 'Mainnet', + network.type, feeMode, feeRateInput, ); diff --git a/src/app/components/transactionSetting/editNonce.tsx b/src/app/components/transactionSetting/editNonce.tsx index 659dc868a..b51610ee9 100644 --- a/src/app/components/transactionSetting/editNonce.tsx +++ b/src/app/components/transactionSetting/editNonce.tsx @@ -12,7 +12,7 @@ const NonceContainer = styled.div((props) => ({ const DetailText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(8), })); @@ -27,8 +27,8 @@ const InputContainer = styled.div((props) => ({ alignItems: 'center', marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(6), - border: `1px solid ${props.theme.colors.background.elevation6}`, - backgroundColor: props.theme.colors.background.elevation1, + border: `1px solid ${props.theme.colors.elevation6}`, + backgroundColor: props.theme.colors.elevation1, borderRadius: 8, paddingLeft: props.theme.spacing(5), paddingRight: props.theme.spacing(5), @@ -38,8 +38,8 @@ const InputContainer = styled.div((props) => ({ const InputField = styled.input((props) => ({ ...props.theme.body_m, - backgroundColor: props.theme.colors.background.elevation1, - color: props.theme.colors.white['400'], + backgroundColor: props.theme.colors.elevation1, + color: props.theme.colors.white_400, width: '100%', border: 'transparent', })); diff --git a/src/app/components/transactionSetting/index.tsx b/src/app/components/transactionSetting/index.tsx index 674cc19db..42bf77098 100644 --- a/src/app/components/transactionSetting/index.tsx +++ b/src/app/components/transactionSetting/index.tsx @@ -1,17 +1,17 @@ /* eslint-disable no-nested-ternary */ +import ArrowIcon from '@assets/img/settings/arrow.svg'; import BottomModal from '@components/bottomModal'; +import ActionButton from '@components/button'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { BtcUtxoDataResponse, UTXO } from '@secretkeylabs/xverse-core'; +import { stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; +import { isCustomFeesAllowed, Recipient } from '@secretkeylabs/xverse-core/transactions/btc'; import BigNumber from 'bignumber.js'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import ArrowIcon from '@assets/img/settings/arrow.svg'; -import ActionButton from '@components/button'; -import { stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; -import { isCustomFeesAllowed, Recipient } from '@secretkeylabs/xverse-core/transactions/btc'; -import { BtcUtxoDataResponse, UTXO } from '@secretkeylabs/xverse-core'; -import useWalletSelector from '@hooks/useWalletSelector'; -import EditNonce from './editNonce'; import EditFee from './editFee'; +import EditNonce from './editNonce'; const ButtonContainer = styled.div((props) => ({ display: 'flex', @@ -24,7 +24,7 @@ const ButtonContainer = styled.div((props) => ({ const TransactionSettingOptionText = styled.h1((props) => ({ ...props.theme.body_medium_l, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const TransactionSettingOptionButton = styled.button((props) => ({ @@ -93,7 +93,7 @@ function TransactionSettingAlert({ const [selectedOption, setSelectedOption] = useState('standard'); const [showNonceSettings, setShowNonceSettings] = useState(false); const [isLoading, setIsLoading] = useState(loading); - const { btcBalance, stxAvailableBalance } = useWalletSelector(); + const { btcBalance, stxAvailableBalance, network } = useWalletSelector(); const applyClickForStx = () => { if (stxAvailableBalance) { @@ -129,7 +129,7 @@ function TransactionSettingAlert({ return; } if (selectedOption === 'custom' && feeRate) { - const response = await isCustomFeesAllowed(feeRate.toString()); + const response = await isCustomFeesAllowed(network.type, feeRate.toString()); if (!response) { setError(t('TRANSACTION_SETTING.LOWER_THAN_MINIMUM')); return; diff --git a/src/app/components/transactions/btcTransaction.tsx b/src/app/components/transactions/btcTransaction.tsx index c4e835d88..a22a1a9b5 100644 --- a/src/app/components/transactions/btcTransaction.tsx +++ b/src/app/components/transactions/btcTransaction.tsx @@ -22,10 +22,10 @@ const TransactionContainer = styled.button((props) => ({ paddingRight: props.theme.spacing(8), background: 'none', ':hover': { - background: props.theme.colors.white[900], + background: props.theme.colors.white_900, }, ':focus': { - background: props.theme.colors.white[850], + background: props.theme.colors.white_850, }, })); diff --git a/src/app/components/transactions/stxTransaction.tsx b/src/app/components/transactions/stxTransaction.tsx index 9f164b243..fe85a432b 100644 --- a/src/app/components/transactions/stxTransaction.tsx +++ b/src/app/components/transactions/stxTransaction.tsx @@ -1,13 +1,13 @@ -import { CurrencyTypes } from '@utils/constants'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { parseStxTransactionData } from '@secretkeylabs/xverse-core/api/helper'; import { AddressTransactionWithTransfers } from '@stacks/stacks-blockchain-api-types'; +import { CurrencyTypes } from '@utils/constants'; import { isAddressTransactionWithTransfers, Tx } from '@utils/transactions/transactions'; -import { parseStxTransactionData } from '@secretkeylabs/xverse-core/api/helper'; -import useWalletSelector from '@hooks/useWalletSelector'; // import IncreaseFeeIcon from '@assets/img/transactions/increaseFee.svg'; // import styled from 'styled-components'; // import { useTranslation } from 'react-i18next'; -import TxTransfers from './txTransfers'; import StxTransferTransaction from './stxTransferTransaction'; +import TxTransfers from './txTransfers'; // const IncreaseFeeButton = styled.button((props) => ({ // ...props.theme.body_xs, @@ -18,8 +18,8 @@ import StxTransferTransaction from './stxTransferTransaction'; // background: 'none', // paddingLeft: props.theme.spacing(8), // paddingRight: props.theme.spacing(8), -// color: props.theme.colors.white[0], -// border: `0.5px solid ${props.theme.colors.background.elevation3}`, +// color: props.theme.colors.white_0, +// border: `0.5px solid ${props.theme.colors.elevation3}`, // height: 34, // borderRadius: props.theme.radius(3), // img: { diff --git a/src/app/components/transactions/stxTransferTransaction.tsx b/src/app/components/transactions/stxTransferTransaction.tsx index 8d1d5d26f..51db9c995 100644 --- a/src/app/components/transactions/stxTransferTransaction.tsx +++ b/src/app/components/transactions/stxTransferTransaction.tsx @@ -1,12 +1,12 @@ -import styled from 'styled-components'; -import { StxTransactionData } from '@secretkeylabs/xverse-core'; -import { CurrencyTypes } from '@utils/constants'; -import TransactionStatusIcon from '@components/transactions/transactionStatusIcon'; -import TransactionTitle from '@components/transactions/transactionTitle'; import TransactionAmount from '@components/transactions/transactionAmount'; import TransactionRecipient from '@components/transactions/transactionRecipient'; -import { getStxTxStatusUrl } from '@utils/helper'; +import TransactionStatusIcon from '@components/transactions/transactionStatusIcon'; +import TransactionTitle from '@components/transactions/transactionTitle'; import useWalletSelector from '@hooks/useWalletSelector'; +import { StxTransactionData } from '@secretkeylabs/xverse-core'; +import { CurrencyTypes } from '@utils/constants'; +import { getStxTxStatusUrl } from '@utils/helper'; +import styled from 'styled-components'; const TransactionContainer = styled.button((props) => ({ display: 'flex', @@ -17,10 +17,10 @@ const TransactionContainer = styled.button((props) => ({ paddingRight: props.theme.spacing(8), background: 'none', ':hover': { - background: props.theme.colors.white[900], + background: props.theme.colors.white_900, }, ':focus': { - background: props.theme.colors.white[850], + background: props.theme.colors.white_850, }, })); diff --git a/src/app/components/transactions/transactionAmount.tsx b/src/app/components/transactions/transactionAmount.tsx index c9dc2338f..4449a4c09 100644 --- a/src/app/components/transactions/transactionAmount.tsx +++ b/src/app/components/transactions/transactionAmount.tsx @@ -20,7 +20,7 @@ interface TransactionAmountProps { const TransactionValue = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); export default function TransactionAmount(props: TransactionAmountProps): JSX.Element | null { diff --git a/src/app/components/transactions/transactionRecipient.tsx b/src/app/components/transactions/transactionRecipient.tsx index d3af568db..a79129e2f 100644 --- a/src/app/components/transactions/transactionRecipient.tsx +++ b/src/app/components/transactions/transactionRecipient.tsx @@ -8,7 +8,7 @@ import styled from 'styled-components'; const RecipientAddress = styled.p((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, textAlign: 'left', })); diff --git a/src/app/components/transactions/transactionTitle.tsx b/src/app/components/transactions/transactionTitle.tsx index ed277e063..74f11df41 100644 --- a/src/app/components/transactions/transactionTitle.tsx +++ b/src/app/components/transactions/transactionTitle.tsx @@ -15,7 +15,7 @@ interface TransactionTitleProps { const TransactionTitleText = styled.p((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textAlign: 'left', })); diff --git a/src/app/components/transactions/txTransfers.tsx b/src/app/components/transactions/txTransfers.tsx index 517870582..dab7adfcf 100644 --- a/src/app/components/transactions/txTransfers.tsx +++ b/src/app/components/transactions/txTransfers.tsx @@ -1,16 +1,16 @@ -import useWalletSelector from '@hooks/useWalletSelector'; -import { AddressTransactionWithTransfers } from '@stacks/stacks-blockchain-api-types'; import ReceiveIcon from '@assets/img/transactions/received.svg'; import SendIcon from '@assets/img/transactions/sent.svg'; -import { CurrencyTypes } from '@utils/constants'; -import styled from 'styled-components'; -import { nanoid } from 'nanoid'; -import { NumericFormat } from 'react-number-format'; +import useWalletSelector from '@hooks/useWalletSelector'; import { microstacksToStx } from '@secretkeylabs/xverse-core'; +import { AddressTransactionWithTransfers } from '@stacks/stacks-blockchain-api-types'; +import { CurrencyTypes } from '@utils/constants'; +import { ftDecimals } from '@utils/helper'; +import { getFtTicker } from '@utils/tokens'; import BigNumber from 'bignumber.js'; +import { nanoid } from 'nanoid'; import { useTranslation } from 'react-i18next'; -import { getFtTicker } from '@utils/tokens'; -import { ftDecimals } from '@utils/helper'; +import { NumericFormat } from 'react-number-format'; +import styled from 'styled-components'; const TransactionContainer = styled.div((props) => ({ display: 'flex', @@ -36,18 +36,18 @@ const TransactionRow = styled.div((props) => ({ const TransactionTitleText = styled.p((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const RecipientAddress = styled.p((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, textAlign: 'left', })); const TransactionValue = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); interface TxTransfersProps { diff --git a/src/app/components/transactionsRequests/ContractCallRequest.tsx b/src/app/components/transactionsRequests/ContractCallRequest.tsx index 240ab37e0..8c3a021dc 100644 --- a/src/app/components/transactionsRequests/ContractCallRequest.tsx +++ b/src/app/components/transactionsRequests/ContractCallRequest.tsx @@ -1,13 +1,21 @@ -import SwapImage from '@assets/img/webInteractions/swapCall.svg'; -import BNSImage from '@assets/img/webInteractions/bnsCall.svg'; -import NFTImage from '@assets/img/webInteractions/nftCall.svg'; -import ContractCall from '@assets/img/webInteractions/contractCall.svg'; -import { ContractCallPayload } from '@stacks/connect'; -import styled from 'styled-components'; +import AccountHeaderComponent from '@components/accountHeader'; import ConfirmStxTransationComponent from '@components/confirmStxTransactionComponent'; +import InfoContainer from '@components/infoContainer'; +import FtPostConditionCard from '@components/postCondition/ftPostConditionCard'; +import NftPostConditionCard from '@components/postCondition/nftPostConditionCard'; import StxPostConditionCard from '@components/postCondition/stxPostConditionCard'; -import { createContext, useState } from 'react'; -import { useTranslation } from 'react-i18next'; +import TransactionDetailComponent from '@components/transactionDetailComponent'; +import useNetworkSelector from '@hooks/useNetwork'; +import useOnOriginTabClose from '@hooks/useOnTabClosed'; +import { + addressToString, + Args, + broadcastSignedTransaction, + Coin, + ContractFunction, + extractFromPayload, +} from '@secretkeylabs/xverse-core'; +import { ContractCallPayload } from '@stacks/connect'; import { ClarityType, cvToJSON, @@ -16,21 +24,10 @@ import { SomeCV, StacksTransaction, } from '@stacks/transactions'; -import { - addressToString, - broadcastSignedTransaction, - Coin, - extractFromPayload, -} from '@secretkeylabs/xverse-core'; +import { createContext, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import { Args, ContractFunction } from '@secretkeylabs/xverse-core/types/api/stacks/transaction'; -import FtPostConditionCard from '@components/postCondition/ftPostConditionCard'; -import NftPostConditionCard from '@components/postCondition/nftPostConditionCard'; -import AccountHeaderComponent from '@components/accountHeader'; -import useOnOriginTabClose from '@hooks/useOnTabClosed'; -import InfoContainer from '@components/infoContainer'; -import useNetworkSelector from '@hooks/useNetwork'; -import TransactionDetailComponent from '@components/transactionDetailComponent'; +import styled from 'styled-components'; import finalizeTxSignature from './utils'; const PostConditionContainer = styled.div((props) => ({ @@ -38,17 +35,19 @@ const PostConditionContainer = styled.div((props) => ({ paddingTop: props.theme.spacing(12), paddingBottom: props.theme.spacing(12), marginBottom: props.theme.spacing(12), - borderTop: `0.5px solid ${props.theme.colors.background.elevation3}`, - borderBottom: `0.5px solid ${props.theme.colors.background.elevation3}`, + borderTop: `0.5px solid ${props.theme.colors.elevation3}`, + borderBottom: `0.5px solid ${props.theme.colors.elevation3}`, flexDirection: 'column', })); + const SponsoredContainer = styled.div({ display: 'flex', justifyContent: 'center', alignItems: 'center', }); + const SponsoredTag = styled.div((props) => ({ - background: props.theme.colors.background.elevation3, + background: props.theme.colors.elevation3, marginTop: props.theme.spacing(7.5), paddingTop: props.theme.spacing(4), paddingBottom: props.theme.spacing(4), @@ -56,66 +55,15 @@ const SponsoredTag = styled.div((props) => ({ paddingRight: props.theme.spacing(8), borderRadius: 30, })); + const SponosredText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); + const PostConditionAlertText = styled.h1((props) => ({ ...props.theme.body_medium_l, - color: props.theme.colors.white['0'], -})); - -const Line = styled.div((props) => ({ - position: 'absolute', - width: '100%', - border: `0.5px solid ${props.theme.colors.background.elevation3}`, - marginTop: props.theme.spacing(8), -})); - -const ButtonContainer = styled.div({ - position: 'absolute', - width: '100%', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', -}); - -const ShowMoreButton = styled.button((props) => ({ - position: 'relative', - paddingLeft: props.theme.spacing(4), - paddingRight: props.theme.spacing(4), - paddingTop: props.theme.spacing(2), - paddingBottom: props.theme.spacing(2), - backgroundColor: '#12151E', - borderRadius: 24, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - flexDirection: 'row', - border: `1px solid ${props.theme.colors.background.elevation3}`, -})); - -const ShowMoreButtonContainer = styled.div((props) => ({ - position: 'relative', - width: '100%', - marginTop: props.theme.spacing(12), - marginBottom: props.theme.spacing(12), -})); - -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 700, - marginLeft: props.theme.spacing(2), - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const ButtonSymbolText = styled.div((props) => ({ - ...props.theme.body_xs, - marginLeft: props.theme.spacing(2), - color: props.theme.colors.white['0'], - textAlign: 'center', - fontSize: 20, + color: props.theme.colors.white_0, })); interface ContractCallRequestProps { @@ -136,7 +84,6 @@ export default function ContractCallRequest(props: ContractCallRequestProps) { const selectedNetwork = useNetworkSelector(); const [hasTabClosed, setHasTabClosed] = useState(false); const { t } = useTranslation('translation'); - const [isShowMore, setIsShowMore] = useState(false); useOnOriginTabClose(tabId, () => { setHasTabClosed(true); @@ -145,38 +92,40 @@ export default function ContractCallRequest(props: ContractCallRequestProps) { type ArgToView = { name: string; value: string; type: any }; const getFunctionArgs = (): Array => { - const args: Array = []; const { funcArgs } = extractFromPayload(request); - funcMetaData?.args?.map((arg: Args, index: number) => { - const funcArg = cvToJSON(funcArgs[index]); + const args: Array = funcMetaData?.args + ? funcMetaData?.args?.map((arg: Args, index: number) => { + const funcArg = cvToJSON(funcArgs[index]); - const argTypeIsOptionalSome = funcArgs[index].type === ClarityType.OptionalSome; + const argTypeIsOptionalSome = funcArgs[index].type === ClarityType.OptionalSome; - const funcArgType = argTypeIsOptionalSome - ? (funcArgs[index] as SomeCV).value?.type - : funcArgs[index]?.type; + const funcArgType = argTypeIsOptionalSome + ? (funcArgs[index] as SomeCV).value?.type + : funcArgs[index]?.type; - const funcArgValString = argTypeIsOptionalSome - ? cvToString((funcArgs[index] as SomeCV).value, 'tryAscii') - : cvToString(funcArgs[index]); + const funcArgValString = argTypeIsOptionalSome + ? cvToString((funcArgs[index] as SomeCV).value, 'tryAscii') + : cvToString(funcArgs[index]); - const normalizedValue = (() => { - switch (funcArgType) { - case ClarityType.UInt: - return funcArgValString.split('u').join(''); - case ClarityType.Buffer: - return funcArgValString.substring(1, funcArgValString.length - 1); - default: - return funcArgValString; - } - })(); - const argToView: ArgToView = { - name: arg.name, - value: normalizedValue, - type: funcArg.type, - }; - args.push(argToView); - }); + const normalizedValue = (() => { + switch (funcArgType) { + case ClarityType.UInt: + return funcArgValString.split('u').join(''); + case ClarityType.Buffer: + return funcArgValString.substring(1, funcArgValString.length - 1); + default: + return funcArgValString; + } + })(); + const argToView: ArgToView = { + name: arg.name, + value: normalizedValue, + type: funcArg.type, + }; + + return argToView; + }) + : []; return args; }; @@ -270,26 +219,27 @@ export default function ContractCallRequest(props: ContractCallRequestProps) { const renderPostConditionsCard = () => { const { postConds } = extractFromPayload(request); return postConds?.map((postCondition, i) => { + const key = `${postCondition.conditionType}-${i}`; + switch (postCondition.conditionType) { case PostConditionType.STX: - return ; + return ; case PostConditionType.Fungible: - const coinInfo = coinsMetaData?.find( - (coin: Coin) => - coin.contract === - `${addressToString(postCondition.assetInfo.address)}.${ - postCondition.assetInfo.contractName.content - }`, - ); return ( + coin.contract === + `${addressToString(postCondition.assetInfo.address)}.${ + postCondition.assetInfo.contractName.content + }`, + )} /> ); case PostConditionType.NonFungible: - return ; + return ; default: return ''; } diff --git a/src/app/components/transactionsRequests/ContractDeployTransaction.tsx b/src/app/components/transactionsRequests/ContractDeployTransaction.tsx index fe843a354..de5baf627 100644 --- a/src/app/components/transactionsRequests/ContractDeployTransaction.tsx +++ b/src/app/components/transactionsRequests/ContractDeployTransaction.tsx @@ -1,29 +1,29 @@ -import ConfirmStxTransationComponent from '@components/confirmStxTransactionComponent'; -import { PostCondition, StacksTransaction } from '@stacks/transactions'; -import styled from 'styled-components'; import DownloadImage from '@assets/img/webInteractions/ArrowLineDown.svg'; -import { useTranslation } from 'react-i18next'; -import { useState } from 'react'; -import StxPostConditionCard from '@components/postCondition/stxPostConditionCard'; -import { broadcastSignedTransaction } from '@secretkeylabs/xverse-core'; -import { useNavigate } from 'react-router-dom'; import AccountHeaderComponent from '@components/accountHeader'; -import useOnOriginTabClose from '@hooks/useOnTabClosed'; +import ConfirmStxTransationComponent from '@components/confirmStxTransactionComponent'; import InfoContainer from '@components/infoContainer'; -import useNetworkSelector from '@hooks/useNetwork'; +import StxPostConditionCard from '@components/postCondition/stxPostConditionCard'; import TransactionDetailComponent from '@components/transactionDetailComponent'; +import useNetworkSelector from '@hooks/useNetwork'; +import useOnOriginTabClose from '@hooks/useOnTabClosed'; +import { broadcastSignedTransaction } from '@secretkeylabs/xverse-core'; +import { PostCondition, StacksTransaction } from '@stacks/transactions'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import finalizeTxSignature from './utils'; const Title = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textTransform: 'uppercase', })); const DownloadContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -35,8 +35,8 @@ const PostConditionContainer = styled.div((props) => ({ display: 'flex', paddingTop: props.theme.spacing(12), paddingBottom: props.theme.spacing(12), - borderTop: `0.5px solid ${props.theme.colors.background.elevation3}`, - borderBottom: `0.5px solid ${props.theme.colors.background.elevation3}`, + borderTop: `0.5px solid ${props.theme.colors.elevation3}`, + borderBottom: `0.5px solid ${props.theme.colors.elevation3}`, flexDirection: 'column', })); @@ -49,7 +49,7 @@ const DownloadButtonContainer = styled.div({ const ButtonText = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginRight: props.theme.spacing(2), textAlign: 'center', })); @@ -66,7 +66,7 @@ const SponsoredContainer = styled.div({ }); const SponsoredTag = styled.div((props) => ({ - background: props.theme.colors.background.elevation3, + background: props.theme.colors.elevation3, marginTop: props.theme.spacing(7.5), paddingTop: props.theme.spacing(4), paddingBottom: props.theme.spacing(4), @@ -77,12 +77,12 @@ const SponsoredTag = styled.div((props) => ({ const SponosredText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const PostConditionAlertText = styled.h1((props) => ({ ...props.theme.body_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const Button = styled.button((props) => ({ diff --git a/src/app/components/transferAmountComponent/index.tsx b/src/app/components/transferAmountComponent/index.tsx index ed2c21760..77163e33d 100644 --- a/src/app/components/transferAmountComponent/index.tsx +++ b/src/app/components/transferAmountComponent/index.tsx @@ -1,14 +1,14 @@ -import styled from 'styled-components'; import DropDownIcon from '@assets/img/transactions/dropDownIcon.svg'; -import { useTranslation } from 'react-i18next'; -import { animated, config, useSpring } from '@react-spring/web'; import TransferDetailView from '@components/transferDetailView'; +import { animated, config, useSpring } from '@react-spring/web'; import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -21,25 +21,25 @@ const FromContainer = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const DescriptionText = styled.h1((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(6), marginBottom: props.theme.spacing(4), - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const SubValueText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const Icon = styled.img((props) => ({ diff --git a/src/app/components/transferAmountView/index.tsx b/src/app/components/transferAmountView/index.tsx index 52b05b70f..67ada3b35 100644 --- a/src/app/components/transferAmountView/index.tsx +++ b/src/app/components/transferAmountView/index.tsx @@ -17,7 +17,7 @@ const SendAmountContainer = styled.div({ const TitleText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textTransform: 'uppercase', })); @@ -29,7 +29,7 @@ const AmountText = styled.h1((props) => ({ const FiatAmountText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); interface Props { diff --git a/src/app/components/transferDetailView/index.tsx b/src/app/components/transferDetailView/index.tsx index a7470650f..3b6411f19 100644 --- a/src/app/components/transferDetailView/index.tsx +++ b/src/app/components/transferDetailView/index.tsx @@ -1,10 +1,10 @@ -import styled from 'styled-components'; -import { getTruncatedAddress } from '@utils/helper'; -import { ReactNode, useState } from 'react'; -import CopyButton from '@components/copyButton'; import Eye from '@assets/img/createPassword/Eye.svg'; import Cross from '@assets/img/dashboard/X.svg'; +import CopyButton from '@components/copyButton'; +import { getTruncatedAddress } from '@utils/helper'; +import { ReactNode, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const RowContainer = styled.div({ display: 'flex', @@ -35,17 +35,17 @@ const AddressContainer = styled.div({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const AmountText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const ColumnContainer = styled.div({ diff --git a/src/app/components/transferFeeView/index.tsx b/src/app/components/transferFeeView/index.tsx index 586662a89..bc061948d 100644 --- a/src/app/components/transferFeeView/index.tsx +++ b/src/app/components/transferFeeView/index.tsx @@ -10,7 +10,7 @@ import styled from 'styled-components'; const RowContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -19,7 +19,7 @@ const RowContainer = styled.div((props) => ({ const FeeText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const FeeTitleContainer = styled.div({ @@ -36,13 +36,13 @@ const FeeContainer = styled.div({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const FiatAmountText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); interface Props { diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts index 16084988e..7a82aff39 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptionCollections.ts @@ -9,13 +9,13 @@ const PAGE_SIZE = 30; * Get collections belonging to an address */ const useAddressInscriptionCollections = () => { - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); const getCollectionsByAddress = async ({ pageParam = 0 }) => { if (!ordinalsAddress) { throw new InvalidParamsError('ordinalsAddress is required'); } - return getCollections(ordinalsAddress, pageParam || 0, PAGE_SIZE); + return getCollections(network.type, ordinalsAddress, pageParam || 0, PAGE_SIZE); }; return useInfiniteQuery(['inscription-collections', ordinalsAddress], getCollectionsByAddress, { @@ -31,8 +31,7 @@ const useAddressInscriptionCollections = () => { } return false; }, - refetchOnMount: false, - refetchOnWindowFocus: false, + staleTime: 1 * 60 * 1000, // 1 min }); }; diff --git a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts index ca39fefa9..a2fcce9c6 100644 --- a/src/app/hooks/queries/ordinals/useAddressInscriptions.ts +++ b/src/app/hooks/queries/ordinals/useAddressInscriptions.ts @@ -9,13 +9,14 @@ const PAGE_SIZE = 30; * Get inscriptions belonging to an address, filtered by collection id */ const useAddressInscriptions = (collectionId?: string) => { - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); const getInscriptionsByAddress = async ({ pageParam = 0 }) => { if (!ordinalsAddress || !collectionId) { throw new InvalidParamsError('ordinalsAddress and collectionId are required'); } return getCollectionSpecificInscriptions( + network.type, ordinalsAddress, collectionId, pageParam || 0, // offset, @@ -39,8 +40,7 @@ const useAddressInscriptions = (collectionId?: string) => { } return false; }, - refetchOnMount: false, - refetchOnWindowFocus: false, + staleTime: 1 * 60 * 1000, // 1 min }, ); }; diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index faeb45a12..547cd9cf6 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -1,13 +1,13 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { getAddressUtxoOrdinalBundles, getUtxoOrdinalBundle } from '@secretkeylabs/xverse-core'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; -import { InvalidParamsError, handleRetries } from '@utils/query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; import { mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; const PAGE_SIZE = 30; export const useAddressRareSats = () => { - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); const getRareSatsByAddress = async ({ pageParam = 0 }) => { if (!ordinalsAddress) { @@ -15,6 +15,7 @@ export const useAddressRareSats = () => { } const bundleResponse = await getAddressUtxoOrdinalBundles( + network.type, ordinalsAddress, pageParam, PAGE_SIZE, @@ -27,8 +28,6 @@ export const useAddressRareSats = () => { }; return useInfiniteQuery(['rare-sats', ordinalsAddress], getRareSatsByAddress, { - refetchOnMount: false, - refetchOnWindowFocus: false, retry: handleRetries, getNextPageParam: (lastPage, allPages) => { const currentLength = allPages.map((page) => page.results).flat().length; @@ -36,27 +35,28 @@ export const useAddressRareSats = () => { return currentLength; } }, + staleTime: 1 * 60 * 1000, // 1 min }); }; export const useGetUtxoOrdinalBundle = (output?: string, shouldMakeTheCall?: boolean) => { + const { network } = useWalletSelector(); const getUtxoOrdinalBundleByOutput = async () => { if (!output) { throw new InvalidParamsError('output is required'); } const [txid, vout] = output.split(':'); - const bundleResponse = await getUtxoOrdinalBundle(txid, parseInt(vout, 10)); + const bundleResponse = await getUtxoOrdinalBundle(network.type, txid, parseInt(vout, 10)); return bundleResponse; }; const { data, isLoading } = useQuery({ enabled: !!(output && shouldMakeTheCall), - refetchOnMount: false, - refetchOnWindowFocus: false, queryKey: ['rare-sats', output], queryFn: getUtxoOrdinalBundleByOutput, retry: handleRetries, + staleTime: 1 * 60 * 1000, // 1 min }); const bundle = data?.txid ? mapRareSatsAPIResponseToRareSats(data) : undefined; diff --git a/src/app/hooks/queries/ordinals/useCollectionMarketData.ts b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts index 1f2ecc811..990a667fc 100644 --- a/src/app/hooks/queries/ordinals/useCollectionMarketData.ts +++ b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts @@ -1,3 +1,4 @@ +import useWalletSelector from '@hooks/useWalletSelector'; import { CollectionMarketDataResponse, getCollectionMarketData } from '@secretkeylabs/xverse-core'; import { useQuery } from '@tanstack/react-query'; import { handleRetries, InvalidParamsError } from '@utils/query'; @@ -6,11 +7,12 @@ import { handleRetries, InvalidParamsError } from '@utils/query'; * Get inscription collection market data */ const useInscriptionCollectionMarketData = (collectionId?: string | null) => { + const { network } = useWalletSelector(); const collectionMarketData = async (): Promise => { if (!collectionId) { throw new InvalidParamsError('collectionId is required'); } - return getCollectionMarketData(collectionId); + return getCollectionMarketData(network.type, collectionId); }; return useQuery({ @@ -18,6 +20,7 @@ const useInscriptionCollectionMarketData = (collectionId?: string | null) => { retry: handleRetries, queryKey: ['collection-market-data', collectionId], queryFn: collectionMarketData, + staleTime: 1 * 60 * 1000, // 1 min }); }; diff --git a/src/app/hooks/queries/ordinals/useInscription.ts b/src/app/hooks/queries/ordinals/useInscription.ts index f675395b1..8e41d4c32 100644 --- a/src/app/hooks/queries/ordinals/useInscription.ts +++ b/src/app/hooks/queries/ordinals/useInscription.ts @@ -7,13 +7,13 @@ import { handleRetries, InvalidParamsError } from '@utils/query'; * Get inscriptions details by collection id */ const useAddressInscription = (ordinalId: string, ordinal: Inscription | null) => { - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); const fetchOrdinals = async (): Promise => { if (ordinal) return ordinal; if (!ordinalsAddress || !ordinalId) { throw new InvalidParamsError('ordinalsAddress and ordinalId are required'); } - return getInscription(ordinalsAddress, ordinalId); + return getInscription(network.type, ordinalsAddress, ordinalId); }; return useQuery({ diff --git a/src/app/hooks/queries/ordinals/useInscriptionDetails.ts b/src/app/hooks/queries/ordinals/useInscriptionDetails.ts index f60c0e6f5..adbc5566f 100644 --- a/src/app/hooks/queries/ordinals/useInscriptionDetails.ts +++ b/src/app/hooks/queries/ordinals/useInscriptionDetails.ts @@ -1,16 +1,15 @@ -import { useQuery } from '@tanstack/react-query'; import useOrdinalsApi from '@hooks/useOrdinalsApi'; +import { useQuery } from '@tanstack/react-query'; const useInscriptionDetails = (id: string) => { const OrdinalsApi = useOrdinalsApi(); - return useQuery([`inscription-${id}`], async () => { - try { + return useQuery({ + queryKey: [`inscription-${id}`], + queryFn: async () => { const response = await OrdinalsApi.getInscription(id); return response; - } catch (err) { - return Promise.reject(err); - } + }, }); }; diff --git a/src/app/hooks/queries/useAppConfig.ts b/src/app/hooks/queries/useAppConfig.ts index db9957c24..733d26ece 100644 --- a/src/app/hooks/queries/useAppConfig.ts +++ b/src/app/hooks/queries/useAppConfig.ts @@ -1,24 +1,23 @@ +import useWalletSelector from '@hooks/useWalletSelector'; +import { getAppConfig } from '@secretkeylabs/xverse-core'; +import { ChangeNetworkAction } from '@stores/wallet/actions/actionCreators'; import { useQuery } from '@tanstack/react-query'; import { useDispatch } from 'react-redux'; -import { getAppConfig } from '@secretkeylabs/xverse-core/api/xverse'; -import { ChangeNetworkAction } from '@stores/wallet/actions/actionCreators'; -import useWalletSelector from '@hooks/useWalletSelector'; const useAppConfig = () => { const { network, networkAddress, btcApiUrl } = useWalletSelector(); const dispatch = useDispatch(); - return useQuery(['app-config'], async () => { - try { - const response = await getAppConfig(); + return useQuery({ + queryKey: ['app-config', network.type, btcApiUrl], + queryFn: async () => { + const response = await getAppConfig(network.type); if (response.data.btcApiURL && network.type === 'Mainnet' && !btcApiUrl) { const updatedNetwork = { ...network, btcApiUrl: response.data.btcApiURL }; dispatch(ChangeNetworkAction(updatedNetwork, networkAddress, '')); } return response; - } catch (err) { - return Promise.reject(err); - } + }, }); }; diff --git a/src/app/hooks/queries/useBtcCoinsBalance.ts b/src/app/hooks/queries/useBtcCoinsBalance.ts index 4a52709c1..88dc64ab7 100644 --- a/src/app/hooks/queries/useBtcCoinsBalance.ts +++ b/src/app/hooks/queries/useBtcCoinsBalance.ts @@ -7,11 +7,11 @@ import { useDispatch } from 'react-redux'; const useBtcCoinBalance = () => { const dispatch = useDispatch(); - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); const fetchBrcCoinsBalances = async () => { try { - const list = await getOrdinalsFtBalance(ordinalsAddress); + const list = await getOrdinalsFtBalance(network.type, ordinalsAddress); dispatch( setBrcCoinsDataAction( list.map((brcToken) => ({ ...brcToken, ticker: brcToken.ticker?.toUpperCase() })), diff --git a/src/app/hooks/queries/useBtcWalletData.ts b/src/app/hooks/queries/useBtcWalletData.ts index 64d92ac70..f2615ac55 100644 --- a/src/app/hooks/queries/useBtcWalletData.ts +++ b/src/app/hooks/queries/useBtcWalletData.ts @@ -1,5 +1,5 @@ import useBtcClient from '@hooks/useBtcClient'; -import { BtcAddressData } from '@secretkeylabs/xverse-core/types'; +import type { BtcAddressData } from '@secretkeylabs/xverse-core'; import { SetBtcWalletDataAction } from '@stores/wallet/actions/actionCreators'; import { useQuery } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; @@ -19,10 +19,10 @@ export const useBtcWalletData = () => { }; return useQuery({ - queryKey: [`wallet-data-${btcAddress}`], - refetchOnWindowFocus: true, + queryKey: ['btc-wallet-data', btcAddress], queryFn: fetchBtcWalletData, enabled: !!btcAddress, + staleTime: 10 * 1000, // 10 secs }); }; diff --git a/src/app/hooks/queries/useCoinData.ts b/src/app/hooks/queries/useCoinData.ts index d33afe4dc..2e54bcd68 100644 --- a/src/app/hooks/queries/useCoinData.ts +++ b/src/app/hooks/queries/useCoinData.ts @@ -1,16 +1,16 @@ +import useNetworkSelector from '@hooks/useNetwork'; import useWalletSelector from '@hooks/useWalletSelector'; -import { useDispatch } from 'react-redux'; -import { useQuery } from '@tanstack/react-query'; -import { CoinsResponse, FungibleToken } from '@secretkeylabs/xverse-core/types'; +import { getCoinMetaData } from '@secretkeylabs/xverse-core'; import { getCoinsInfo, getFtData } from '@secretkeylabs/xverse-core/api'; -import useNetworkSelector from '@hooks/useNetwork'; +import { FungibleToken } from '@secretkeylabs/xverse-core/types'; import { setCoinDataAction } from '@stores/wallet/actions/actionCreators'; -import { getCoinMetaData } from '@secretkeylabs/xverse-core'; -import { InvalidParamsError, handleRetries } from '@utils/query'; +import { useQuery } from '@tanstack/react-query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; +import { useDispatch } from 'react-redux'; export const useCoinsData = () => { const dispatch = useDispatch(); - const { stxAddress, coinsList, fiatCurrency } = useWalletSelector(); + const { stxAddress, coinsList, fiatCurrency, network } = useWalletSelector(); const currentNetworkInstance = useNetworkSelector(); const fetchCoinData = async () => { @@ -46,12 +46,12 @@ export const useCoinsData = () => { fungibleTokenList.forEach((ft) => { contractids.push(ft.principal); }); - let coinsReponse: CoinsResponse = await getCoinsInfo(contractids, fiatCurrency); - if (!coinsReponse) { - coinsReponse = await getCoinMetaData(contractids, currentNetworkInstance); + let coinsResponse = await getCoinsInfo(network.type, contractids, fiatCurrency); + if (!coinsResponse) { + coinsResponse = await getCoinMetaData(contractids, currentNetworkInstance); } - coinsReponse.forEach((coin) => { + coinsResponse.forEach((coin) => { if (!coin.name) { const coinName = coin.contract.split('.')[1]; coin.name = coinName; @@ -60,7 +60,7 @@ export const useCoinsData = () => { // update attributes of fungible token list fungibleTokenList.forEach((ft) => { - coinsReponse.forEach((coin) => { + coinsResponse!.forEach((coin) => { if (ft.principal === coin.contract) { ft.ticker = coin.ticker; ft.decimals = coin.decimals; @@ -81,8 +81,8 @@ export const useCoinsData = () => { else unSupportedFts.push(ft); }); const sortedFtList: FungibleToken[] = [...supportedFts, ...unSupportedFts]; - dispatch(setCoinDataAction(sortedFtList, coinsReponse)); - return { sortedFtList, coinsReponse }; + dispatch(setCoinDataAction(sortedFtList, coinsResponse)); + return { sortedFtList, coinsResponse }; } catch (error: any) { return Promise.reject(error); } diff --git a/src/app/hooks/queries/useCoinRates.ts b/src/app/hooks/queries/useCoinRates.ts index 05698dc21..92e2e446b 100644 --- a/src/app/hooks/queries/useCoinRates.ts +++ b/src/app/hooks/queries/useCoinRates.ts @@ -1,19 +1,19 @@ import useWalletSelector from '@hooks/useWalletSelector'; -import { useDispatch } from 'react-redux'; -import { useQuery } from '@tanstack/react-query'; +import { fetchBtcToCurrencyRate, fetchStxToBtcRate } from '@secretkeylabs/xverse-core'; import { setCoinRatesAction } from '@stores/wallet/actions/actionCreators'; -import { fetchBtcToCurrencyRate, fetchStxToBtcRate } from '@secretkeylabs/xverse-core/api'; +import { useQuery } from '@tanstack/react-query'; +import { useDispatch } from 'react-redux'; export const useCoinRates = () => { const dispatch = useDispatch(); - const { fiatCurrency } = useWalletSelector(); + const { fiatCurrency, network } = useWalletSelector(); const fetchCoinRates = async () => { try { - const btcFiatRate = await fetchBtcToCurrencyRate({ + const btcFiatRate = await fetchBtcToCurrencyRate(network.type, { fiatCurrency, }); - const stxBtcRate = await fetchStxToBtcRate(); + const stxBtcRate = await fetchStxToBtcRate(network.type); dispatch(setCoinRatesAction(stxBtcRate, btcFiatRate)); return { stxBtcRate, btcFiatRate }; } catch (e: any) { @@ -24,6 +24,7 @@ export const useCoinRates = () => { return useQuery({ queryKey: ['coin_rates'], queryFn: fetchCoinRates, + staleTime: 5 * 60 * 1000, // 5 min }); }; diff --git a/src/app/hooks/queries/useFeeMultipliers.ts b/src/app/hooks/queries/useFeeMultipliers.ts index 5aa1ba085..f89031ba0 100644 --- a/src/app/hooks/queries/useFeeMultipliers.ts +++ b/src/app/hooks/queries/useFeeMultipliers.ts @@ -1,20 +1,20 @@ -import { useDispatch } from 'react-redux'; -import { useQuery } from '@tanstack/react-query'; -import { AppInfo } from '@secretkeylabs/xverse-core/types'; -import { fetchAppInfo } from '@secretkeylabs/xverse-core/api'; +import useWalletSelector from '@hooks/useWalletSelector'; +import type { AppInfo } from '@secretkeylabs/xverse-core'; +import { fetchAppInfo } from '@secretkeylabs/xverse-core'; import { setFeeMultiplierAction } from '@stores/wallet/actions/actionCreators'; +import { useQuery } from '@tanstack/react-query'; +import { useDispatch } from 'react-redux'; export const useFeeMultipliers = () => { + const { network } = useWalletSelector(); const dispatch = useDispatch(); const fetchFeeMultiplierData = async (): Promise => { - try { - const response: AppInfo = await fetchAppInfo(); - dispatch(setFeeMultiplierAction(response)); - return response; - } catch (err) { - return Promise.reject(err); - } + const response = await fetchAppInfo(network.type); + if (!response) throw new Error('Failed to fetch fee multipliers'); + + dispatch(setFeeMultiplierAction(response)); + return response; }; return useQuery({ diff --git a/src/app/hooks/queries/usePendingOrdinalTx.ts b/src/app/hooks/queries/usePendingOrdinalTx.ts index 7b0d2b0f9..bc2c5382b 100644 --- a/src/app/hooks/queries/usePendingOrdinalTx.ts +++ b/src/app/hooks/queries/usePendingOrdinalTx.ts @@ -1,6 +1,6 @@ -import { BtcAddressMempool } from '@secretkeylabs/xverse-core/types/api/esplora'; -import { useQuery } from '@tanstack/react-query'; import useBtcClient from '@hooks/useBtcClient'; +import type { BtcAddressMempool } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; import useWalletSelector from '../useWalletSelector'; const usePendingOrdinalTxs = (ordinalUtxoHash: string | undefined) => { diff --git a/src/app/hooks/queries/useStackingData.ts b/src/app/hooks/queries/useStackingData.ts index 0ac6fe05d..fcaf9d77f 100644 --- a/src/app/hooks/queries/useStackingData.ts +++ b/src/app/hooks/queries/useStackingData.ts @@ -1,5 +1,3 @@ -import { useQueries } from '@tanstack/react-query'; -import { useCallback } from 'react'; import { fetchDelegationState, fetchPoolStackerInfo, @@ -7,8 +5,10 @@ import { getStacksInfo, StackingData, } from '@secretkeylabs/xverse-core'; -import useWalletSelector from '../useWalletSelector'; +import { useQueries } from '@tanstack/react-query'; +import { useCallback } from 'react'; import useNetworkSelector from '../useNetwork'; +import useWalletSelector from '../useWalletSelector'; const useStackingData = () => { const { stxAddress, network } = useWalletSelector(); @@ -25,12 +25,12 @@ const useStackingData = () => { queryFn: () => fetchDelegationState(stxAddress, selectedNetwork), }, { - queryKey: ['stacking-pool-info'], - queryFn: () => fetchStackingPoolInfo(), + queryKey: ['stacking-pool-info', network.type], + queryFn: () => fetchStackingPoolInfo(network.type), }, { - queryKey: ['pool-stacker-info', stxAddress], - queryFn: () => fetchPoolStackerInfo(stxAddress), + queryKey: ['pool-stacker-info', stxAddress, network.type], + queryFn: () => fetchPoolStackerInfo(network.type, stxAddress), }, ], }); @@ -47,7 +47,7 @@ const useStackingData = () => { }, [results]); const stackingData: StackingData = { - poolInfo: poolInfoData, + poolInfo: poolInfoData!, delegationInfo: delegationStateData!, coreInfo: coreInfoData!, stackerInfo: stackerInfoData, diff --git a/src/app/hooks/queries/useStacksCollectibles.ts b/src/app/hooks/queries/useStacksCollectibles.ts index 1adeea968..d93cdffbc 100644 --- a/src/app/hooks/queries/useStacksCollectibles.ts +++ b/src/app/hooks/queries/useStacksCollectibles.ts @@ -1,9 +1,8 @@ -import { NftsListData } from '@secretkeylabs/xverse-core/types'; -import { getNfts } from '@secretkeylabs/xverse-core/api/stacks'; -import { useInfiniteQuery } from '@tanstack/react-query'; -import useWalletSelector from '@hooks/useWalletSelector'; import useNetworkSelector from '@hooks/useNetwork'; -import { InvalidParamsError, handleRetries } from '@utils/query'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { getNfts, NftsListData } from '@secretkeylabs/xverse-core'; +import { useInfiniteQuery } from '@tanstack/react-query'; +import { handleRetries, InvalidParamsError } from '@utils/query'; const useStacksCollectibles = () => { const { stxAddress } = useWalletSelector(); diff --git a/src/app/hooks/queries/useStxPendingTxData.ts b/src/app/hooks/queries/useStxPendingTxData.ts index 6fca87490..deee18a34 100644 --- a/src/app/hooks/queries/useStxPendingTxData.ts +++ b/src/app/hooks/queries/useStxPendingTxData.ts @@ -1,7 +1,7 @@ +import { fetchStxPendingTxData } from '@secretkeylabs/xverse-core'; +import { StoreState } from '@stores/index'; import { useQuery } from '@tanstack/react-query'; import { useSelector } from 'react-redux'; -import { fetchStxPendingTxData } from '@secretkeylabs/xverse-core/api'; -import { StoreState } from '@stores/index'; import useNetworkSelector from '../useNetwork'; const useStxPendingTxData = () => { diff --git a/src/app/hooks/queries/useStxWalletData.ts b/src/app/hooks/queries/useStxWalletData.ts index 92d414451..0b33b3580 100644 --- a/src/app/hooks/queries/useStxWalletData.ts +++ b/src/app/hooks/queries/useStxWalletData.ts @@ -1,5 +1,5 @@ -import { fetchStxAddressData } from '@secretkeylabs/xverse-core/api'; -import { StxAddressData } from '@secretkeylabs/xverse-core/types'; +import type { StxAddressData } from '@secretkeylabs/xverse-core'; +import { fetchStxAddressData } from '@secretkeylabs/xverse-core'; import { setStxWalletDataAction } from '@stores/wallet/actions/actionCreators'; import { useQuery } from '@tanstack/react-query'; import { PAGINATION_LIMIT } from '@utils/constants'; @@ -32,9 +32,10 @@ export const useStxWalletData = () => { }; return useQuery({ - queryKey: [`wallet-data-${stxAddress}`], + queryKey: ['stx-wallet-data', stxAddress], queryFn: fetchStxWalletData, enabled: !!stxAddress, + staleTime: 10 * 1000, // 10 secs }); }; diff --git a/src/app/hooks/queries/useTransactions.ts b/src/app/hooks/queries/useTransactions.ts index c78999312..347f273fb 100644 --- a/src/app/hooks/queries/useTransactions.ts +++ b/src/app/hooks/queries/useTransactions.ts @@ -1,6 +1,6 @@ import useWalletSelector from '@hooks/useWalletSelector'; -import { fetchBtcTransactionsData, getBrc20History } from '@secretkeylabs/xverse-core/api'; -import { Brc20HistoryTransactionData, BtcTransactionData } from '@secretkeylabs/xverse-core/types'; +import type { Brc20HistoryTransactionData, BtcTransactionData } from '@secretkeylabs/xverse-core'; +import { fetchBtcTransactionsData, getBrc20History } from '@secretkeylabs/xverse-core'; import { AddressTransactionWithTransfers, MempoolTransaction, @@ -32,7 +32,7 @@ export default function useTransactions(coinType: CurrencyTypes, brc20Token: str return btcData; } if (coinType === 'brc20' && brc20Token) { - const brc20Data = await getBrc20History(ordinalsAddress, brc20Token); + const brc20Data = await getBrc20History(network.type, ordinalsAddress, brc20Token); return brc20Data; } return []; diff --git a/src/app/hooks/useBtcFeeRate.ts b/src/app/hooks/useBtcFeeRate.ts index 5b3e99a79..a1507ea17 100644 --- a/src/app/hooks/useBtcFeeRate.ts +++ b/src/app/hooks/useBtcFeeRate.ts @@ -1,11 +1,13 @@ import { getBtcFeeRate } from '@secretkeylabs/xverse-core/transactions/btc'; import { BtcFeeResponse } from '@secretkeylabs/xverse-core/types'; import { useQuery } from '@tanstack/react-query'; +import useWalletSelector from './useWalletSelector'; function useBtcFeeRate() { + const { network } = useWalletSelector(); return useQuery({ - queryKey: ['btcFeeRate'], - queryFn: getBtcFeeRate, + queryKey: ['btcFeeRate', network.type], + queryFn: () => getBtcFeeRate(network.type), staleTime: 5 * 60 * 1000, // 5 mins }); } diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index 84ffb4bef..9483c86d1 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -1,5 +1,6 @@ import { getUtxoOrdinalBundle, ParsedPSBT } from '@secretkeylabs/xverse-core'; import { BundleItem, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { isAxiosError } from 'axios'; import { useEffect, useState } from 'react'; import useWalletSelector from './useWalletSelector'; @@ -7,7 +8,7 @@ const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { const [loading, setLoading] = useState(false); const [userReceivesOrdinal, setUserReceivesOrdinal] = useState(false); const [bundleItemsData, setBundleItemsData] = useState([]); - const { ordinalsAddress } = useWalletSelector(); + const { ordinalsAddress, network } = useWalletSelector(); async function handleOrdinalAndOrdinalInfo() { const bundleItems: BundleItem[] = []; @@ -15,21 +16,30 @@ const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { setLoading(true); await Promise.all( parsedPsbt.inputs.map(async (input) => { - const data = await getUtxoOrdinalBundle(input.txid, input.index); - console.log({ data }); - - const bundle = mapRareSatsAPIResponseToRareSats(data); - bundle.items.forEach((item) => { - // we don't show unknown items for now - if (item.type === 'unknown') { - return; + try { + const data = await getUtxoOrdinalBundle(network.type, input.txid, input.index); + + const bundle = mapRareSatsAPIResponseToRareSats(data); + bundle.items.forEach((item) => { + // we don't show unknown items for now + if (item.type === 'unknown') { + return; + } + bundleItems.push(item); + }); + } catch (e) { + // we get back a 404 if the UTXO is not found, so it is likely this is a UTXO from an unpublished txn + if (!isAxiosError(e) || e.response?.status !== 404) { + // rethrow error if response was not 404 + throw e; } - bundleItems.push(item); - }); + } }), ); + setBundleItemsData(bundleItems); setLoading(false); + parsedPsbt.outputs.forEach(async (output) => { if (output.address === ordinalsAddress) { setUserReceivesOrdinal(true); diff --git a/src/app/hooks/useOrdinalsApi.ts b/src/app/hooks/useOrdinalsApi.ts index 9ba6ca4d8..f2db00e36 100644 --- a/src/app/hooks/useOrdinalsApi.ts +++ b/src/app/hooks/useOrdinalsApi.ts @@ -1,5 +1,5 @@ -import { useMemo } from 'react'; import OrdinalsApi from '@secretkeylabs/xverse-core/api/ordinals/provider'; +import { useMemo } from 'react'; import useWalletSelector from './useWalletSelector'; const useOrdinalsApi = () => { @@ -9,7 +9,7 @@ const useOrdinalsApi = () => { new OrdinalsApi({ network: network.type, }), - [], + [network.type], ); }; diff --git a/src/app/hooks/useOrdinalsByAddress.ts b/src/app/hooks/useOrdinalsByAddress.ts index a84b7c6d2..a0ceba032 100644 --- a/src/app/hooks/useOrdinalsByAddress.ts +++ b/src/app/hooks/useOrdinalsByAddress.ts @@ -1,10 +1,12 @@ import { getOrdinalsByAddress } from '@secretkeylabs/xverse-core/api/xverse'; import { BtcOrdinal } from '@secretkeylabs/xverse-core/types'; import { useQuery } from '@tanstack/react-query'; +import useWalletSelector from './useWalletSelector'; const useOrdinalsByAddress = (address: string) => { + const { network } = useWalletSelector(); const fetchOrdinals = async (): Promise => { - const ordinals = await getOrdinalsByAddress(address); + const ordinals = await getOrdinalsByAddress(network.type, address); return ordinals.filter((item) => item.id !== undefined); }; diff --git a/src/app/hooks/useSeedVault.ts b/src/app/hooks/useSeedVault.ts new file mode 100644 index 000000000..c72b1362f --- /dev/null +++ b/src/app/hooks/useSeedVault.ts @@ -0,0 +1,46 @@ +import { useMemo } from 'react'; +import SeedVault, { + CryptoUtilsAdapter, + StorageAdapter, +} from '@secretkeylabs/xverse-core/seedVault'; +import { generateRandomKey } from '@secretkeylabs/xverse-core/encryption'; +import { chromeSessionStorage, chromeLocalStorage } from '@utils/chromeStorage'; +import { + decryptSeedPhraseHandler, + encryptSeedPhraseHandler, + generateKeyArgon2id, +} from '@utils/encryptionUtils'; + +const cryptoUtilsAdapter: CryptoUtilsAdapter = { + encrypt: encryptSeedPhraseHandler, + decrypt: decryptSeedPhraseHandler, + generateRandomBytes: generateRandomKey, + hash: generateKeyArgon2id, +}; + +const secureStorageAdapter: StorageAdapter = { + get: async (key: string) => chromeSessionStorage.getItem(key), + set: async (key: string, value: string) => chromeSessionStorage.setItem(key, value), + remove: async (key: string) => chromeSessionStorage.removeItem(key), +}; + +const commonStorageAdapter: StorageAdapter = { + get: async (key: string) => chromeLocalStorage.getItem(key), + set: async (key: string, value: string) => chromeLocalStorage.setItem(key, value), + remove: async (key: string) => chromeLocalStorage.removeItem(key), +}; + +const useSeedVault = () => { + const vault = useMemo( + () => + new SeedVault({ + cryptoUtilsAdapter, + secureStorageAdapter, + commonStorageAdapter, + }), + [], + ); + + return vault; +}; +export default useSeedVault; diff --git a/src/app/hooks/useSendBtcRequest.ts b/src/app/hooks/useSendBtcRequest.ts index 7ca9b844e..c5951a637 100644 --- a/src/app/hooks/useSendBtcRequest.ts +++ b/src/app/hooks/useSendBtcRequest.ts @@ -6,6 +6,7 @@ import { useState } from 'react'; import { useLocation } from 'react-router-dom'; import { SendBtcTransactionOptions } from 'sats-connect'; import useWalletSelector from './useWalletSelector'; +import useSeedVault from './useSeedVault'; function useSendBtcRequest() { const { search } = useLocation(); @@ -14,10 +15,11 @@ function useSendBtcRequest() { const requestToken = params.get('sendBtcRequest') ?? ''; const request = decodeToken(requestToken) as any as SendBtcTransactionOptions; const tabId = params.get('tabId') ?? '0'; - - const { network, selectedAccount, seedPhrase } = useWalletSelector(); + const { getSeed } = useSeedVault(); + const { network, selectedAccount } = useWalletSelector(); const generateSignedTransaction = async () => { + const seedPhrase = await getSeed(); const recipients: Recipient[] = []; request.payload?.recipients?.forEach(async (value) => { const txRecipient: Recipient = { diff --git a/src/app/hooks/useSignPsbtTx.ts b/src/app/hooks/useSignPsbtTx.ts index e2562634f..3fb8b7d9a 100644 --- a/src/app/hooks/useSignPsbtTx.ts +++ b/src/app/hooks/useSignPsbtTx.ts @@ -9,10 +9,12 @@ import { } from '@secretkeylabs/xverse-core/transactions/psbt'; import { ExternalSatsMethods, MESSAGE_SOURCE } from '@common/types/message-types'; import useBtcClient from './useBtcClient'; +import useSeedVault from './useSeedVault'; const useSignPsbtTx = () => { - const { seedPhrase, accountsList, network } = useWalletSelector(); + const { accountsList, network } = useWalletSelector(); const { search } = useLocation(); + const { getSeed } = useSeedVault(); const params = new URLSearchParams(search); const requestToken = params.get('signPsbtRequest') ?? ''; const request = decodeToken(requestToken) as any as SignTransactionOptions; @@ -20,6 +22,7 @@ const useSignPsbtTx = () => { const btcClient = useBtcClient(); const confirmSignPsbt = async () => { + const seedPhrase = await getSeed(); const signingResponse = await signPsbt( seedPhrase, accountsList, diff --git a/src/app/hooks/useSignatureRequest.ts b/src/app/hooks/useSignatureRequest.ts index 4bf9018d0..52b19a83f 100644 --- a/src/app/hooks/useSignatureRequest.ts +++ b/src/app/hooks/useSignatureRequest.ts @@ -14,6 +14,7 @@ import { useLocation } from 'react-router-dom'; import { SignMessagePayload } from 'sats-connect'; import { signBip322Message } from '@secretkeylabs/xverse-core/connect/bip322Signature'; import useWalletSelector from './useWalletSelector'; +import useSeedVault from './useSeedVault'; export type SignatureMessageType = 'utf8' | 'structured'; @@ -52,9 +53,11 @@ function useSignatureRequest() { } export function useSignMessage(messageType: SignatureMessageType) { - const { selectedAccount, seedPhrase, network } = useWalletSelector(); + const { selectedAccount, network } = useWalletSelector(); + const { getSeed } = useSeedVault(); return useCallback( async ({ message, domain }: { message: string; domain?: TupleCV }) => { + const seedPhrase = await getSeed(); if (!selectedAccount) return null; const { privateKey } = await getStxAddressKeyChain( seedPhrase, @@ -82,18 +85,18 @@ export function useSignMessage(messageType: SignatureMessageType) { } export function useSignBip322Message(message: string, address: string) { - const { accountsList, seedPhrase, network } = useWalletSelector(); - return useCallback( - async () => - signBip322Message({ - accounts: accountsList, - message, - signatureAddress: address, - seedPhrase, - network: network.type, - }), - [], - ); + const { accountsList, network } = useWalletSelector(); + const { getSeed } = useSeedVault(); + return useCallback(async () => { + const seedPhrase = await getSeed(); + return signBip322Message({ + accounts: accountsList, + message, + signatureAddress: address, + seedPhrase, + network: network.type, + }); + }, []); } export default useSignatureRequest; diff --git a/src/app/hooks/useTextOrdinalContent.ts b/src/app/hooks/useTextOrdinalContent.ts index 000d49a3d..130dfdcc2 100644 --- a/src/app/hooks/useTextOrdinalContent.ts +++ b/src/app/hooks/useTextOrdinalContent.ts @@ -1,16 +1,17 @@ -import { getTextOrdinalContent } from '@secretkeylabs/xverse-core/api/index'; -import type { CondensedInscription, Inscription } from '@secretkeylabs/xverse-core/types'; +import type { CondensedInscription, Inscription } from '@secretkeylabs/xverse-core'; +import { getTextOrdinalContent } from '@secretkeylabs/xverse-core'; import { useQuery } from '@tanstack/react-query'; import PQueue from 'p-queue'; +import useWalletSelector from './useWalletSelector'; const queue = new PQueue({ concurrency: 1 }); const useTextOrdinalContent = (ordinal: Inscription | CondensedInscription) => { + const { network } = useWalletSelector(); const { data: textContent } = useQuery({ queryKey: [`ordinal-text-${ordinal?.id}`], - queryFn: async () => queue.add(() => getTextOrdinalContent(ordinal?.id)), - refetchOnMount: false, - refetchOnWindowFocus: false, + queryFn: async () => queue.add(() => getTextOrdinalContent(network.type, ordinal?.id)), + staleTime: 5 * 60 * 1000, // 5 min }); return textContent?.toString(); diff --git a/src/app/hooks/useWalletReducer.ts b/src/app/hooks/useWalletReducer.ts index 38cc7411f..89f923452 100644 --- a/src/app/hooks/useWalletReducer.ts +++ b/src/app/hooks/useWalletReducer.ts @@ -2,44 +2,54 @@ import { getDeviceAccountIndex } from '@common/utils/ledger'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; import useStxWalletData from '@hooks/queries/useStxWalletData'; import useNetworkSelector from '@hooks/useNetwork'; -import { createWalletAccount, restoreWalletWithAccounts } from '@secretkeylabs/xverse-core/account'; -import { getBnsName } from '@secretkeylabs/xverse-core/api/stacks'; import { Account, AnalyticsEvents, + createWalletAccount, + decryptSeedPhraseCBC, + getBnsName, + newWallet, + restoreWalletWithAccounts, SettingsNetwork, StacksNetwork, -} from '@secretkeylabs/xverse-core/types'; -import { newWallet, walletFromSeedPhrase } from '@secretkeylabs/xverse-core/wallet'; + walletFromSeedPhrase, +} from '@secretkeylabs/xverse-core'; import { - ChangeNetworkAction, addAccountAction, + ChangeNetworkAction, fetchAccountAction, getActiveAccountsAction, - lockWalletAction, resetWalletAction, selectAccount, setWalletAction, + setWalletUnlockedAction, storeEncryptedSeedAction, - unlockWalletAction, updateLedgerAccountsAction, } from '@stores/wallet/actions/actionCreators'; import { useQueryClient } from '@tanstack/react-query'; -import { decryptSeedPhrase, encryptSeedPhrase, generatePasswordHash } from '@utils/encryptionUtils'; +import { generatePasswordHash } from '@utils/encryptionUtils'; import { isHardwareAccount, isLedgerAccount } from '@utils/helper'; import { resetMixPanel, trackMixPanel } from '@utils/mixpanel'; import { useDispatch } from 'react-redux'; +import useSeedVault from './useSeedVault'; import useWalletSelector from './useWalletSelector'; import useWalletSession from './useWalletSession'; const useWalletReducer = () => { - const { encryptedSeed, accountsList, seedPhrase, selectedAccount, network, ledgerAccountsList } = - useWalletSelector(); + const { + accountsList, + selectedAccount, + network, + ledgerAccountsList, + encryptedSeed, + masterPubKey, + } = useWalletSelector(); + const seedVault = useSeedVault(); const selectedNetwork = useNetworkSelector(); const dispatch = useDispatch(); const { refetch: refetchStxData } = useStxWalletData(); const { refetch: refetchBtcData } = useBtcWalletData(); - const { setSessionStartTime, clearSessionTime, clearSessionKey } = useWalletSession(); + const { setSessionStartTime, clearSessionTime } = useWalletSession(); const queryClient = useQueryClient(); const loadActiveAccounts = async ( @@ -103,37 +113,48 @@ const useWalletReducer = () => { dispatch(getActiveAccountsAction(walletAccounts)); }; - const unlockWallet = async (password: string) => { + const migrateLegacySeedStorage = async (password: string) => { const pHash = await generatePasswordHash(password); - const decrypted = await decryptSeedPhrase(encryptedSeed, password); + await decryptSeedPhraseCBC(encryptedSeed, pHash.hash).then(async (decrypted) => { + await seedVault.init(password); + await seedVault.storeSeed(decrypted); + localStorage.removeItem('salt'); + dispatch(storeEncryptedSeedAction('')); + }); + }; + + const unlockWallet = async (password: string) => { + if (encryptedSeed && encryptedSeed.length > 0) { + await migrateLegacySeedStorage(password); + return; + } + await seedVault.unlockVault(password); try { + const decrypted = await seedVault.getSeed(); await loadActiveAccounts(decrypted, network, selectedNetwork, accountsList); } catch (err) { dispatch(fetchAccountAction(accountsList[0], accountsList)); dispatch(getActiveAccountsAction(accountsList)); } finally { - chrome.storage.session.set({ - pHash: pHash.hash, - }); setSessionStartTime(); } - dispatch(unlockWalletAction(decrypted)); - return decrypted; }; const lockWallet = async () => { - dispatch(lockWalletAction()); - await clearSessionTime(); - await clearSessionKey(); + await seedVault.lockVault(); + dispatch(setWalletUnlockedAction(false)); }; - const resetWallet = () => { + const resetWallet = async () => { resetMixPanel(); dispatch(resetWalletAction()); - chrome.storage.local.clear(); - chrome.storage.session.clear(); localStorage.clear(); - clearSessionTime(); + queryClient.clear(); + await Promise.all([ + clearSessionTime(), + chrome.storage.local.clear(), + chrome.storage.session.clear(), + ]); }; const restoreWallet = async (seed: string, password: string) => { @@ -151,15 +172,16 @@ const useWalletReducer = () => { ordinalsPublicKey: wallet.ordinalsPublicKey, stxAddress: wallet.stxAddress, stxPublicKey: wallet.stxPublicKey, - bnsName: wallet.bnsName, }; + const hasSeed = await seedVault.hasSeed(); + if (hasSeed && !masterPubKey) { + await seedVault.clearVaultStorage(); + } + await seedVault.init(password); + await seedVault.storeSeed(seed); trackMixPanel(AnalyticsEvents.RestoreWallet); - - const encryptSeed = await encryptSeedPhrase(seed, password); const bnsName = await getBnsName(wallet.stxAddress, selectedNetwork); - dispatch(storeEncryptedSeedAction(encryptSeed)); dispatch(setWalletAction(wallet)); - const pHash = await generatePasswordHash(password); localStorage.setItem('migrated', 'true'); try { await loadActiveAccounts(seed, network, selectedNetwork, [ @@ -192,9 +214,6 @@ const useWalletReducer = () => { ); } finally { setSessionStartTime(); - chrome.storage.session.set({ - pHash: pHash.hash, - }); } }; @@ -212,7 +231,6 @@ const useWalletReducer = () => { ordinalsPublicKey: wallet.ordinalsPublicKey, stxAddress: wallet.stxAddress, stxPublicKey: wallet.stxPublicKey, - bnsName: wallet.bnsName, }; trackMixPanel(AnalyticsEvents.CreateNewWallet); @@ -223,6 +241,7 @@ const useWalletReducer = () => { }; const createAccount = async () => { + const seedPhrase = await seedVault.getSeed(); const newAccountsList = await createWalletAccount( seedPhrase, network, @@ -235,7 +254,7 @@ const useWalletReducer = () => { const switchAccount = async (account: Account) => { // we clear the query cache to prevent data from the other account potentially being displayed await queryClient.cancelQueries(); - await queryClient.clear(); + queryClient.clear(); dispatch( selectAccount( @@ -262,6 +281,7 @@ const useWalletReducer = () => { networkAddress: string, btcApiUrl: string, ) => { + const seedPhrase = await seedVault.getSeed(); dispatch(ChangeNetworkAction(changedNetwork, networkAddress, btcApiUrl)); const wallet = await walletFromSeedPhrase({ mnemonic: seedPhrase, @@ -277,7 +297,6 @@ const useWalletReducer = () => { ordinalsPublicKey: wallet.ordinalsPublicKey, stxAddress: wallet.stxAddress, stxPublicKey: wallet.stxPublicKey, - bnsName: wallet.bnsName, }; dispatch(setWalletAction(wallet)); try { @@ -306,13 +325,6 @@ const useWalletReducer = () => { await refetchBtcData(); }; - /** - * This should only be used as a storage location when creating a new wallet - */ - const storeSeedPhrase = async (seed: string) => { - dispatch(unlockWalletAction(seed)); - }; - const addLedgerAccount = async (ledgerAccount: Account) => { try { dispatch(updateLedgerAccountsAction([...ledgerAccountsList, ledgerAccount])); @@ -356,7 +368,6 @@ const useWalletReducer = () => { switchAccount, changeNetwork, createAccount, - storeSeedPhrase, addLedgerAccount, removeLedgerAccount, updateLedgerAccounts, diff --git a/src/app/hooks/useWalletSession.ts b/src/app/hooks/useWalletSession.ts index ab8dc6b94..95ceb0d5d 100644 --- a/src/app/hooks/useWalletSession.ts +++ b/src/app/hooks/useWalletSession.ts @@ -3,33 +3,29 @@ import { setWalletLockPeriodAction } from '@stores/wallet/actions/actionCreators import { WalletSessionPeriods } from '@stores/wallet/actions/types'; import { addMinutes } from 'date-fns'; import { useDispatch } from 'react-redux'; +import { chromeSessionStorage } from '@utils/chromeStorage'; +import useSeedVault from './useSeedVault'; const SESSION_START_TIME_KEY = 'sessionStartTime'; const useWalletSession = () => { const { walletLockPeriod } = useWalletSelector(); const dispatch = useDispatch(); + const { isVaultUnlocked } = useSeedVault(); const setSessionStartTime = () => { const sessionStartTime = new Date().getTime(); - chrome.storage.session.set({ [SESSION_START_TIME_KEY]: sessionStartTime }); + chromeSessionStorage.setItem(SESSION_START_TIME_KEY, sessionStartTime); }; const clearSessionTime = async () => { - await chrome.storage.session.remove(SESSION_START_TIME_KEY); - }; - - const getSessionStartTime = async () => { - const { sessionStartTime } = await chrome.storage.session.get(SESSION_START_TIME_KEY); - return sessionStartTime; + await chromeSessionStorage.removeItem(SESSION_START_TIME_KEY); }; const shouldLock = async () => { - const pHash = await chrome.storage.session.get('pHash'); - - if (!pHash) return false; - - const startTime = await getSessionStartTime(); + const isUnlocked = await isVaultUnlocked(); + if (!isUnlocked) return false; + const startTime = await chromeSessionStorage.getItem(SESSION_START_TIME_KEY); const currentTime = new Date().getTime(); return currentTime >= addMinutes(startTime, walletLockPeriod).getTime(); }; @@ -40,17 +36,11 @@ const useWalletSession = () => { setSessionStartTime(); }; - const clearSessionKey = async () => { - await chrome.storage.session.remove('pHash'); - }; - return { setSessionStartTime, setWalletLockPeriod, - getSessionStartTime, shouldLock, clearSessionTime, - clearSessionKey, }; }; diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index 81775dac5..9d426fb2a 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -291,7 +291,11 @@ const router = createHashRouter([ }, { path: 'settings', - element: , + element: ( + + + + ), }, { path: 'restore-funds', diff --git a/src/app/screens/accountList/index.tsx b/src/app/screens/accountList/index.tsx index 76735df48..7cf8d9ecf 100644 --- a/src/app/screens/accountList/index.tsx +++ b/src/app/screens/accountList/index.tsx @@ -33,7 +33,7 @@ const ButtonContainer = styled.button((props) => ({ paddingRight: props.theme.spacing(11), transition: 'background-color 0.2s ease', ':hover': { - backgroundColor: props.theme.colors.background.elevation1, + backgroundColor: props.theme.colors.elevation1, }, })); @@ -53,7 +53,7 @@ const AddAccountContainer = styled.div((props) => ({ borderRadius: 25, justifyContent: 'center', alignItems: 'center', - backgroundColor: props.theme.colors.background.elevation1, + backgroundColor: props.theme.colors.elevation1, marginRight: props.theme.spacing(8), })); @@ -65,14 +65,14 @@ const ButtonImage = styled.img({ const AddAccountText = styled.h1((props) => ({ ...props.theme.body_m, opacity: 0.8, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const ButtonsWrapper = styled.div( (props) => ` position: sticky; bottom: 0; - background-color: ${props.theme.colors.background.elevation0}; + background-color: ${props.theme.colors.elevation0}; margin-top: ${props.theme.spacing(8)}px; margin-bottom: ${props.theme.spacing(11)}px; `, diff --git a/src/app/screens/authenticationRequest/index.tsx b/src/app/screens/authenticationRequest/index.tsx index ce50ef4a6..4feb45178 100644 --- a/src/app/screens/authenticationRequest/index.tsx +++ b/src/app/screens/authenticationRequest/index.tsx @@ -1,25 +1,26 @@ -import styled from 'styled-components'; -import { useLocation } from 'react-router-dom'; -import ConfirmScreen from '@components/confirmScreen'; -import { decodeToken } from 'jsontokens'; -import { useTranslation } from 'react-i18next'; -import { createAuthResponse, handleLedgerStxJWTAuth } from '@secretkeylabs/xverse-core'; -import { MESSAGE_SOURCE } from '@common/types/message-types'; -import { useState } from 'react'; -import useWalletSelector from '@hooks/useWalletSelector'; +import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg'; +import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; import DappPlaceholderIcon from '@assets/img/webInteractions/authPlaceholder.svg'; -import validUrl from 'valid-url'; +import { MESSAGE_SOURCE } from '@common/types/message-types'; +import { ledgerDelay } from '@common/utils/ledger'; import AccountHeaderComponent from '@components/accountHeader'; import BottomModal from '@components/bottomModal'; -import ledgerConnectDefaultIcon from '@assets/img/ledger/ledger_connect_default.svg'; -import ledgerConnectStxIcon from '@assets/img/ledger/ledger_import_connect_stx.svg'; -import LedgerConnectionView from '@components/ledger/connectLedgerView'; import ActionButton from '@components/button'; +import ConfirmScreen from '@components/confirmScreen'; +import InfoContainer from '@components/infoContainer'; +import LedgerConnectionView from '@components/ledger/connectLedgerView'; +import useSeedVault from '@hooks/useSeedVault'; +import useWalletSelector from '@hooks/useWalletSelector'; import Transport from '@ledgerhq/hw-transport-webusb'; -import { ledgerDelay } from '@common/utils/ledger'; -import { AddressVersion, StacksMessageType, publicKeyToAddress } from '@stacks/transactions'; +import { createAuthResponse, handleLedgerStxJWTAuth } from '@secretkeylabs/xverse-core'; +import { AddressVersion, publicKeyToAddress, StacksMessageType } from '@stacks/transactions'; import { isHardwareAccount } from '@utils/helper'; -import InfoContainer from '@components/infoContainer'; +import { decodeToken } from 'jsontokens'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'react-router-dom'; +import styled from 'styled-components'; +import validUrl from 'valid-url'; const MainContainer = styled.div({ display: 'flex', @@ -52,13 +53,13 @@ const TopImage = styled.img({ const FunctionTitle = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(8), })); const DappTitle = styled.h2((props) => ({ ...props.theme.body_l, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(2), })); @@ -82,7 +83,8 @@ function AuthenticationRequest() { const params = new URLSearchParams(search); const authRequestToken = params.get('authRequest') ?? ''; const authRequest = decodeToken(authRequestToken); - const { seedPhrase, selectedAccount } = useWalletSelector(); + const { selectedAccount } = useWalletSelector(); + const { getSeed } = useSeedVault(); const isDisabled = !selectedAccount?.stxAddress; const confirmCallback = async () => { @@ -93,6 +95,7 @@ function AuthenticationRequest() { return; } + const seedPhrase = await getSeed(); const authResponse = await createAuthResponse( seedPhrase, selectedAccount?.id ?? 0, diff --git a/src/app/screens/backupWallet/index.tsx b/src/app/screens/backupWallet/index.tsx index 1dd584687..1d7df69b3 100644 --- a/src/app/screens/backupWallet/index.tsx +++ b/src/app/screens/backupWallet/index.tsx @@ -1,7 +1,7 @@ import backup from '@assets/img/backupWallet/backup.svg'; import ActionButton from '@components/button'; -import useWalletReducer from '@hooks/useWalletReducer'; -import useWalletSelector from '@hooks/useWalletSelector'; +import useSeedVault from '@hooks/useSeedVault'; +import { a } from '@react-spring/web'; import { generateMnemonic } from '@secretkeylabs/xverse-core/wallet'; import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; @@ -39,7 +39,7 @@ const SubTitle = styled.h2((props) => ({ ...props.theme.body_l, textAlign: 'center', marginTop: props.theme.spacing(4), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const BackupActionsContainer = styled.div((props) => ({ @@ -58,14 +58,33 @@ const TransparentButtonContainer = styled.div((props) => ({ function BackupWallet(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'BACKUP_WALLET_SCREEN' }); const navigate = useNavigate(); - const { seedPhrase } = useWalletSelector(); - const { storeSeedPhrase } = useWalletReducer(); + const { + init: initSeedVault, + storeSeed, + unlockVault, + hasSeed, + clearVaultStorage, + } = useSeedVault(); + + const generateAndStoreSeedPhrase = async () => { + const newSeedPhrase = generateMnemonic(); + await initSeedVault(''); + await storeSeed(newSeedPhrase); + }; useEffect(() => { - if (!seedPhrase) { - const newSeedPhrase = generateMnemonic(); - storeSeedPhrase(newSeedPhrase); - } + (async () => { + const hasSeedPhrase = await hasSeed(); + if (!hasSeedPhrase) { + await generateAndStoreSeedPhrase(); + } else { + // attempt to unlock the wallet with an empty password (verifies the user didn't finish onboarding) + await unlockVault(''); + // clear the vault storage and generate a new seed phrase + await clearVaultStorage(); + await generateAndStoreSeedPhrase(); + } + })(); }, []); const handleBackup = () => { diff --git a/src/app/screens/backupWalletSteps/index.tsx b/src/app/screens/backupWalletSteps/index.tsx index 8fd975748..d6c7a669c 100644 --- a/src/app/screens/backupWalletSteps/index.tsx +++ b/src/app/screens/backupWalletSteps/index.tsx @@ -2,14 +2,11 @@ import { useWalletExistsContext } from '@components/guards/onboarding'; import PasswordInput from '@components/passwordInput'; import Steps from '@components/steps'; import useWalletReducer from '@hooks/useWalletReducer'; -import { StoreState } from '@stores/index'; -import { storeEncryptedSeedAction } from '@stores/wallet/actions/actionCreators'; -import { encryptSeedPhrase } from '@utils/encryptionUtils'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import useSeedVault from '@hooks/useSeedVault'; import SeedCheck from './seedCheck'; import VerifySeed from './verifySeed'; @@ -39,19 +36,22 @@ export default function BackupWalletSteps(): JSX.Element { const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); - const dispatch = useDispatch(); const navigate = useNavigate(); - const { seedPhrase } = useSelector((state: StoreState) => ({ - ...state.walletState, - })); + const [seedPhrase, setSeedPhrase] = useState(''); + const { getSeed, changePassword } = useSeedVault(); const { createWallet } = useWalletReducer(); const { disableWalletExistsGuard } = useWalletExistsContext(); useEffect(() => { - if (!seedPhrase) { - navigate('/backup'); - } - }, [seedPhrase]); + (async () => { + try { + const seed = await getSeed(); + setSeedPhrase(seed); + } catch (e) { + navigate('/backup'); + } + })(); + }, []); const handleSeedCheckContinue = () => { setCurrentActiveIndex(1); @@ -80,9 +80,8 @@ export default function BackupWalletSteps(): JSX.Element { const handleConfirmPasswordContinue = async () => { if (confirmPassword === password) { disableWalletExistsGuard?.(); - const encryptedSeed = await encryptSeedPhrase(seedPhrase, password); - dispatch(storeEncryptedSeedAction(encryptedSeed)); await createWallet(seedPhrase); + await changePassword('', password); navigate('/wallet-success/create', { replace: true }); } else { setError(t('CONFIRM_PASSWORD_MATCH_ERROR')); @@ -90,15 +89,16 @@ export default function BackupWalletSteps(): JSX.Element { }; const backupSteps = [ - + , , - + , - + ({ ...props.theme.body_l, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(20), })); const Label = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(4), })); @@ -35,7 +35,7 @@ const ContinueButton = styled.button((props) => ({ borderRadius: props.theme.radius(1), backgroundColor: props.theme.colors.action.classic, marginBottom: props.theme.spacing(30), - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, width: '100%', height: 44, opacity: props.enabled ? 1 : 0.6, diff --git a/src/app/screens/backupWalletSteps/verifySeed.tsx b/src/app/screens/backupWalletSteps/verifySeed.tsx index 9178d4249..1f0ee0be2 100644 --- a/src/app/screens/backupWalletSteps/verifySeed.tsx +++ b/src/app/screens/backupWalletSteps/verifySeed.tsx @@ -1,8 +1,8 @@ +import ActionButton from '@components/button'; +import { generateMnemonic } from 'bip39'; import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { generateMnemonic } from 'bip39'; -import ActionButton from '@components/button'; const Container = styled.div((props) => ({ display: 'flex', @@ -28,7 +28,7 @@ const TransparentButtonContainer = styled.div((props) => ({ const Heading = styled.h3((props) => ({ ...props.theme.body_l, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(16), })); @@ -41,8 +41,8 @@ const WordGrid = styled.div` const WordButton = styled.button` ${(props) => props.theme.body_medium_m}; - color: ${(props) => props.theme.colors.white['0']}; - background-color: ${(props) => props.theme.colors.background.elevation3}; + color: ${(props) => props.theme.colors.white_0}; + background-color: ${(props) => props.theme.colors.elevation3}; display: flex; justify-content: center; align-items: center; @@ -59,7 +59,7 @@ const WordButton = styled.button` const NthSpan = styled.span` ${(props) => props.theme.body_bold_l}; - color: ${(props) => props.theme.colors.white['0']}; + color: ${(props) => props.theme.colors.white_0}; `; const ErrorMessage = styled.p<{ visible: boolean }>` diff --git a/src/app/screens/btcSelectAddressScreen/accountView.tsx b/src/app/screens/btcSelectAddressScreen/accountView.tsx index 6b113f2f5..d4ca8a77d 100644 --- a/src/app/screens/btcSelectAddressScreen/accountView.tsx +++ b/src/app/screens/btcSelectAddressScreen/accountView.tsx @@ -1,8 +1,8 @@ +import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import { Account } from '@secretkeylabs/xverse-core'; import { getAccountGradient } from '@utils/gradient'; import { getTruncatedAddress } from '@utils/helper'; import { useTranslation } from 'react-i18next'; -import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import styled from 'styled-components'; interface GradientCircleProps { @@ -45,14 +45,14 @@ const RowContainer = styled.div({ const CurrentSelectedAccountText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'start', })); const AddressText = styled.h1((props) => ({ ...props.theme.body_m, marginTop: props.theme.spacing(1), - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const BitcoinDot = styled.div((props) => ({ diff --git a/src/app/screens/btcSelectAddressScreen/index.tsx b/src/app/screens/btcSelectAddressScreen/index.tsx index e78d851a8..bf2ce535c 100644 --- a/src/app/screens/btcSelectAddressScreen/index.tsx +++ b/src/app/screens/btcSelectAddressScreen/index.tsx @@ -44,11 +44,11 @@ const Container = styled.div({ const LogoContainer = styled.div((props) => ({ padding: props.theme.spacing(11), marginBottom: props.theme.spacing(16), - borderBottom: `1px solid ${props.theme.colors.background.elevation3}`, + borderBottom: `1px solid ${props.theme.colors.elevation3}`, })); const AddressContainer = styled.div((props) => ({ - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, borderRadius: 40, height: 24, display: 'flex', @@ -67,7 +67,7 @@ const AccountListContainer = styled(animated.div)((props) => ({ height: 214, marginTop: props.theme.spacing(9.5), boxShadow: '0px 8px 104px rgba(0, 0, 0, 0.5)', - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, '&::-webkit-scrollbar': { display: 'none', }, @@ -83,13 +83,13 @@ const TopImage = styled.img({ const FunctionTitle = styled.h1((props) => ({ ...props.theme.body_bold_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: 16, })); const AccountContainer = styled.button((props) => ({ - background: props.theme.colors.background.elevation1, - border: `1px solid ${props.theme.colors.background.elevation3}`, + background: props.theme.colors.elevation1, + border: `1px solid ${props.theme.colors.elevation3}`, borderRadius: 8, width: '100%', padding: '12px 16px', @@ -97,26 +97,26 @@ const AccountContainer = styled.button((props) => ({ flexDirection: 'row', marginTop: props.theme.spacing(4), ':hover': { - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, }, })); const AccountText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: 24, })); const DappTitle = styled.h2((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginTop: 12, textAlign: 'center', })); const AddressTextTitle = styled.h1((props) => ({ ...props.theme.body_medium_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, fontSize: 10, textAlign: 'center', })); @@ -150,7 +150,7 @@ const AccountListRow = styled.div((props) => ({ paddingLeft: 16, paddingRight: 16, ':hover': { - background: props.theme.colors.background.elevation3, + background: props.theme.colors.elevation3, }, })); diff --git a/src/app/screens/btcSendScreen/index.tsx b/src/app/screens/btcSendScreen/index.tsx index 0957b58d6..04e84627a 100644 --- a/src/app/screens/btcSendScreen/index.tsx +++ b/src/app/screens/btcSendScreen/index.tsx @@ -2,7 +2,6 @@ import useSendBtcRequest from '@hooks/useSendBtcRequest'; import useWalletSelector from '@hooks/useWalletSelector'; import { ErrorCodes, getBtcFiatEquivalent } from '@secretkeylabs/xverse-core'; import { BITCOIN_DUST_AMOUNT_SATS } from '@utils/constants'; -import BigNumber from 'bignumber.js'; import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; diff --git a/src/app/screens/buy/index.tsx b/src/app/screens/buy/index.tsx index 99a0ccdf7..0ce64e3e3 100644 --- a/src/app/screens/buy/index.tsx +++ b/src/app/screens/buy/index.tsx @@ -1,16 +1,16 @@ -import TopRow from '@components/topRow'; -import { useTranslation } from 'react-i18next'; -import { useNavigate, useParams } from 'react-router-dom'; -import styled from 'styled-components'; -import BottomBar from '@components/tabBar'; import MoonPay from '@assets/img/dashboard/moonpay.svg'; import Transak from '@assets/img/dashboard/transak.svg'; -import { MOON_PAY_API_KEY, MOON_PAY_URL, TRANSAC_API_KEY, TRANSAC_URL } from '@utils/constants'; +import InfoContainer from '@components/infoContainer'; +import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; import useWalletSelector from '@hooks/useWalletSelector'; -import { useEffect, useState } from 'react'; import { getMoonPaySignedUrl } from '@secretkeylabs/xverse-core/api'; +import { MOON_PAY_API_KEY, MOON_PAY_URL, TRANSAC_API_KEY, TRANSAC_URL } from '@utils/constants'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate, useParams } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; -import InfoContainer from '@components/infoContainer'; +import styled from 'styled-components'; import RedirectButton from './redirectButton'; const Container = styled.div` @@ -28,7 +28,7 @@ const Container = styled.div` const Text = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(14), })); @@ -52,7 +52,7 @@ function Buy() { const { t } = useTranslation('translation', { keyPrefix: 'BUY_SCREEN' }); const navigate = useNavigate(); const { currency } = useParams(); - const { stxAddress, btcAddress } = useWalletSelector(); + const { stxAddress, btcAddress, network } = useWalletSelector(); const address = currency === 'STX' ? stxAddress : btcAddress; const [url, setUrl] = useState(''); const [loading, setLoading] = useState(false); @@ -75,7 +75,7 @@ function Buy() { moonPayUrl.searchParams.append('currencyCode', currency!); moonPayUrl.searchParams.append('walletAddress', address); moonPayUrl.searchParams.append('colorCode', '#5546FF'); - const signedUrl = await getMoonPaySignedUrl(moonPayUrl.href); + const signedUrl = await getMoonPaySignedUrl(network.type, moonPayUrl.href); setUrl(signedUrl?.signedUrl ?? ''); } catch (e) { setLoading(false); diff --git a/src/app/screens/buy/redirectButton.tsx b/src/app/screens/buy/redirectButton.tsx index 5addf973c..0cabaf6ee 100644 --- a/src/app/screens/buy/redirectButton.tsx +++ b/src/app/screens/buy/redirectButton.tsx @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import CaretRight from '@assets/img/dashboard/caret_right.svg'; +import styled from 'styled-components'; const Button = styled.button((props) => ({ display: 'flex', @@ -10,12 +10,12 @@ const Button = styled.button((props) => ({ backgroundColor: 'transparent', padding: props.theme.spacing(8), marginBottom: props.theme.spacing(8), - border: `1px solid ${props.theme.colors.background.elevation3}`, + border: `1px solid ${props.theme.colors.elevation3}`, })); const Text = styled.h1((props) => ({ ...props.theme.body_bold_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', marginLeft: props.theme.spacing(8), marginTop: props.theme.spacing(4), diff --git a/src/app/screens/coinDashboard/coinHeader.tsx b/src/app/screens/coinDashboard/coinHeader.tsx index c10f2c275..ce741ad1c 100644 --- a/src/app/screens/coinDashboard/coinHeader.tsx +++ b/src/app/screens/coinDashboard/coinHeader.tsx @@ -1,23 +1,23 @@ -import TokenImage from '@components/tokenImage'; import ArrowDown from '@assets/img/dashboard/arrow_down.svg'; import ArrowUp from '@assets/img/dashboard/arrow_up.svg'; -import Lock from '@assets/img/transactions/Lock.svg'; import Buy from '@assets/img/dashboard/black_plus.svg'; +import Lock from '@assets/img/transactions/Lock.svg'; +import BottomModal from '@components/bottomModal'; +import ActionButton from '@components/button'; +import SmallActionButton from '@components/smallActionButton'; +import TokenImage from '@components/tokenImage'; import useWalletSelector from '@hooks/useWalletSelector'; import { FungibleToken, microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; -import BigNumber from 'bignumber.js'; -import { NumericFormat } from 'react-number-format'; -import styled from 'styled-components'; import { CurrencyTypes } from '@utils/constants'; -import { getFtBalance, getFtTicker } from '@utils/tokens'; -import { useNavigate } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; import { isLedgerAccount } from '@utils/helper'; -import SmallActionButton from '@components/smallActionButton'; +import { getFtBalance, getFtTicker } from '@utils/tokens'; +import BigNumber from 'bignumber.js'; import { useState } from 'react'; -import BottomModal from '@components/bottomModal'; -import ActionButton from '@components/button'; +import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; interface CoinBalanceProps { coin: CurrencyTypes; @@ -45,9 +45,9 @@ const ProtocolText = styled.p((props) => ({ marginTop: props.theme.spacing(3), textTransform: 'uppercase', marginLeft: props.theme.spacing(2), - backgroundColor: props.theme.colors.white['400'], + backgroundColor: props.theme.colors.white_400, padding: '1px 6px 1px', - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, borderRadius: props.theme.radius(2), })); @@ -65,13 +65,13 @@ const BalanceValuesContainer = styled.div({ const CoinBalanceText = styled.h1((props) => ({ ...props.theme.headline_l, fontSize: '1.5rem', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); const FiatAmountText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, fontSize: '0.875rem', marginTop: props.theme.spacing(2), textAlign: 'center', @@ -79,7 +79,7 @@ const FiatAmountText = styled.h1((props) => ({ const BalanceTitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'center', marginTop: props.theme.spacing(4), })); @@ -104,7 +104,7 @@ const RecieveButtonContainer = styled.div({ }); const HeaderSeparator = styled.div((props) => ({ - border: `0.5px solid ${props.theme.colors.white[400]}`, + border: `0.5px solid ${props.theme.colors.white_400}`, width: '50%', alignSelf: 'center', marginTop: props.theme.spacing(8), @@ -120,7 +120,7 @@ const LockedStxContainer = styled.div((props) => ({ alignItems: 'center', justifyContent: 'center', span: { - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, marginRight: props.theme.spacing(3), }, img: { @@ -134,7 +134,7 @@ const AvailableStxContainer = styled.div((props) => ({ justifyContent: 'center', marginTop: props.theme.spacing(4), span: { - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, marginRight: props.theme.spacing(3), }, })); @@ -151,7 +151,7 @@ const VerifyButtonContainer = styled.div((props) => ({ const StacksLockedInfoText = styled.span((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, textAlign: 'left', })); @@ -374,7 +374,7 @@ export default function CoinHeader(props: CoinBalanceProps) { {renderStackingBalances()} - goToSendScreen()} /> + goToSendScreen()} /> {!fungibleToken ? ( @@ -392,7 +392,7 @@ export default function CoinHeader(props: CoinBalanceProps) { }} /> - navigate(`/buy/${coin}`)} /> + navigate(`/buy/${coin}`)} /> ) : ( diff --git a/src/app/screens/coinDashboard/index.tsx b/src/app/screens/coinDashboard/index.tsx index bbda2f88d..c312e9fc3 100644 --- a/src/app/screens/coinDashboard/index.tsx +++ b/src/app/screens/coinDashboard/index.tsx @@ -32,29 +32,8 @@ const TokenContractContainer = styled.div((props) => ({ paddingRight: props.theme.spacing(8), marginTop: props.theme.spacing(16), h1: { - ...props.theme.body_medium_m, - color: props.theme.colors.white[400], - }, -})); - -const TransactionHistoryContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'column', - flex: 1, - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), - marginTop: props.theme.spacing(30), - borderTop: `1px solid ${props.theme.colors.background.elevation2}`, - h1: { - ...props.theme.headline_s, - color: props.theme.colors.white[0], - marginTop: 32, - }, - h2: { - ...props.theme.body_m, - fontStyle: 'italic', - color: props.theme.colors.white[200], - marginTop: props.theme.spacing(8), + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_400, }, })); @@ -65,8 +44,8 @@ const ContractAddressCopyButton = styled.button((props) => ({ })); const TokenContractAddress = styled.p((props) => ({ - ...props.theme.body_medium_l, - color: props.theme.colors.white[0], + ...props.theme.typography.body_medium_l, + color: props.theme.colors.white_0, textAlign: 'left', overflowWrap: 'break-word', width: 300, @@ -75,7 +54,7 @@ const TokenContractAddress = styled.p((props) => ({ const FtInfoContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - borderTop: `1px solid ${props.theme.colors.background.elevation2}`, + borderTop: `1px solid ${props.theme.colors.elevation2}`, paddingTop: props.theme.spacing(12), marginTop: props.theme.spacing(16), paddingLeft: props.theme.spacing(8), @@ -92,14 +71,14 @@ const CopyButtonContainer = styled.div((props) => ({ })); const ContractDeploymentButton = styled.button((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, display: 'flex', alignItems: 'center', marginTop: props.theme.spacing(12), background: 'none', - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, span: { - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(3), }, img: { @@ -107,11 +86,10 @@ const ContractDeploymentButton = styled.button((props) => ({ }, })); -interface ButtonProps { +const Button = styled.button<{ isSelected: boolean; -} -const Button = styled.button((props) => ({ - ...props.theme.body_bold_l, +}>((props) => ({ + ...props.theme.typography.body_bold_l, fontSize: 11, display: 'flex', justifyContent: 'center', @@ -121,8 +99,8 @@ const Button = styled.button((props) => ({ paddingRight: props.theme.spacing(6), marginRight: props.theme.spacing(2), borderRadius: 44, - background: props.isSelected ? props.theme.colors.background.elevation2 : 'transparent', - color: props.theme.colors.white[0], + background: props.isSelected ? props.theme.colors.elevation2 : 'transparent', + color: props.theme.colors.white_0, opacity: props.isSelected ? 1 : 0.6, })); @@ -167,36 +145,6 @@ export default function CoinDashboard() { const formatAddress = (addr: string): string => addr ? `${addr.substring(0, 20)}...${addr.substring(addr.length - 20, addr.length)}` : ''; - const showContent = () => { - if (ft) { - if (showFtContractDetails) { - return ( - -

{t('FT_CONTRACT_PREFIX')}

- - {formatAddress(ft?.principal as string)} - - - - - - {t('OPEN_FT_CONTRACT_DEPLOYMENT')} - {t('STACKS_EXPLORER')} - - -
- ); - } - } - return ( - - ); - }; - return ( <> @@ -212,7 +160,28 @@ export default function CoinDashboard() { )} - {showContent()} + {ft && showFtContractDetails ? ( + +

{t('FT_CONTRACT_PREFIX')}

+ + {formatAddress(ft?.principal as string)} + + + + + + {t('OPEN_FT_CONTRACT_DEPLOYMENT')} + {t('STACKS_EXPLORER')} + + +
+ ) : ( + + )} diff --git a/src/app/screens/coinDashboard/transactionsHistoryList.tsx b/src/app/screens/coinDashboard/transactionsHistoryList.tsx index e05f6eb29..f3980db45 100644 --- a/src/app/screens/coinDashboard/transactionsHistoryList.tsx +++ b/src/app/screens/coinDashboard/transactionsHistoryList.tsx @@ -50,7 +50,7 @@ const NoTransactionsContainer = styled.div((props) => ({ flex: 1, justifyContent: 'center', alignItems: 'center', - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const GroupContainer = styled(animated.div)((props) => ({ @@ -67,14 +67,14 @@ const SectionHeader = styled.div((props) => ({ })); const SectionSeparator = styled.div((props) => ({ - border: `0.5px solid ${props.theme.colors.white[400]}`, + border: `0.5px solid ${props.theme.colors.white_400}`, opacity: 0.2, flexGrow: 1, })); const SectionTitle = styled.p((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginRight: props.theme.spacing(4), })); diff --git a/src/app/screens/confirmBrc20Transaction/brc20FeesComponent.tsx b/src/app/screens/confirmBrc20Transaction/brc20FeesComponent.tsx index 678d4e5ca..2a2123698 100644 --- a/src/app/screens/confirmBrc20Transaction/brc20FeesComponent.tsx +++ b/src/app/screens/confirmBrc20Transaction/brc20FeesComponent.tsx @@ -6,7 +6,7 @@ import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; const Card = styled.div` - background: ${(props) => props.theme.colors.background.elevation1}; + background: ${(props) => props.theme.colors.elevation1}; border-radius: ${(props) => props.theme.radius(2)}px; padding: ${(props) => props.theme.spacing(8)}px; `; @@ -17,12 +17,12 @@ const CardTitle = styled.div` const TextLabel = styled.label` ${(props) => props.theme.body_medium_m} - color: ${(props) => props.theme.colors.white[200]}; + color: ${(props) => props.theme.colors.white_200}; `; const TextValue = styled.p` ${(props) => props.theme.body_medium_m} - color: ${(props) => props.theme.colors.white[0]}; + color: ${(props) => props.theme.colors.white_0}; `; const Rows = styled.div` @@ -38,7 +38,7 @@ const RowItem = styled.div` const FiatAmountText = styled.p` ${(props) => props.theme.body_medium_s} - color: ${(props) => props.theme.colors.white[400]}; + color: ${(props) => props.theme.colors.white_400}; display: flex; justify-content: flex-end; `; diff --git a/src/app/screens/confirmBrc20Transaction/editFees.tsx b/src/app/screens/confirmBrc20Transaction/editFees.tsx index 0f1d75780..cad42c787 100644 --- a/src/app/screens/confirmBrc20Transaction/editFees.tsx +++ b/src/app/screens/confirmBrc20Transaction/editFees.tsx @@ -1,16 +1,16 @@ -import ActionButton from '@components/button'; -import BigNumber from 'bignumber.js'; +import { BetterBarLoader } from '@components/barLoader'; import BottomModal from '@components/bottomModal'; -import styled from 'styled-components'; +import ActionButton from '@components/button'; +import FiatAmountText from '@components/fiatAmountText'; import useBtcFeeRate from '@hooks/useBtcFeeRate'; import useWalletSelector from '@hooks/useWalletSelector'; -import { BetterBarLoader } from '@components/barLoader'; -import { NumericFormat } from 'react-number-format'; import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; +import InputFeedback from '@ui-library/inputFeedback'; +import BigNumber from 'bignumber.js'; import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import FiatAmountText from '@components/fiatAmountText'; -import InputFeedback from '@ui-library/inputFeedback'; +import { NumericFormat } from 'react-number-format'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -22,7 +22,7 @@ const Container = styled.div((props) => ({ const DetailText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(8), })); @@ -52,7 +52,7 @@ const InputContainer = styled.div<{ withError?: boolean }>((props) => ({ const InputField = styled.input((props) => ({ ...props.theme.body_m, backgroundColor: 'transparent', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, border: 'transparent', width: '50%', '&::-webkit-outer-spin-button': { @@ -70,7 +70,7 @@ const InputField = styled.input((props) => ({ const FeeText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const ButtonContainer = styled.div` @@ -84,13 +84,9 @@ const FeeButton = styled.button<{ isSelected: boolean; }>((props) => ({ ...props.theme.body_medium_m, - color: `${ - props.isSelected ? props.theme.colors.background.elevation2 : props.theme.colors.white['400'] - }`, + color: `${props.isSelected ? props.theme.colors.elevation2 : props.theme.colors.white_400}`, background: `${props.isSelected ? props.theme.colors.white : 'transparent'}`, - border: `1px solid ${ - props.isSelected ? 'transparent' : props.theme.colors.background.elevation6 - }`, + border: `1px solid ${props.isSelected ? 'transparent' : props.theme.colors.elevation6}`, borderRadius: 40, height: 40, display: 'flex', @@ -124,7 +120,7 @@ const StyledInputFeedback = styled(InputFeedback)` const StyledFiatAmountText = styled(FiatAmountText)((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const buttons = [ diff --git a/src/app/screens/confirmBrc20Transaction/index.tsx b/src/app/screens/confirmBrc20Transaction/index.tsx index 94f6935e8..6c64cc606 100644 --- a/src/app/screens/confirmBrc20Transaction/index.tsx +++ b/src/app/screens/confirmBrc20Transaction/index.tsx @@ -1,5 +1,6 @@ import AccountHeaderComponent from '@components/accountHeader'; import ActionButton from '@components/button'; +import InfoContainer from '@components/infoContainer'; import BottomBar from '@components/tabBar'; import TransactionDetailComponent from '@components/transactionDetailComponent'; import useDebounce from '@hooks/useDebounce'; @@ -26,7 +27,6 @@ import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import InfoContainer from '@components/infoContainer'; import Brc20FeesComponent from './brc20FeesComponent'; import { EditFees, OnChangeFeeRate } from './editFees'; import RecipientCard, { RecipientCardProps } from './recipientCard'; @@ -167,6 +167,7 @@ const useConfirmBrc20Transfer = (): { errorCode, } = useBrc20TransferFees({ ...estimateFeesParams, + network: network.type, feeRate: Number(debouncedUserInputFeeRate), skipInitialFetch: true, }); diff --git a/src/app/screens/confirmBtcTransaction/index.tsx b/src/app/screens/confirmBtcTransaction/index.tsx index 4c2b6ef70..59ee95294 100644 --- a/src/app/screens/confirmBtcTransaction/index.tsx +++ b/src/app/screens/confirmBtcTransaction/index.tsx @@ -1,24 +1,25 @@ -import { useNavigate, useLocation } from 'react-router-dom'; -import { useEffect, useState } from 'react'; -import { useMutation } from '@tanstack/react-query'; -import { BtcTransactionBroadcastResponse } from '@secretkeylabs/xverse-core/types'; -import BottomBar from '@components/tabBar'; -import useBtcWalletData from '@hooks/queries/useBtcWalletData'; -import useWalletSelector from '@hooks/useWalletSelector'; +import { ConfirmBtcTransactionState, LedgerTransactionType } from '@common/types/ledger'; +import { ExternalSatsMethods, MESSAGE_SOURCE } from '@common/types/message-types'; +import AccountHeaderComponent from '@components/accountHeader'; +import AlertMessage from '@components/alertMessage'; import ConfirmBtcTransactionComponent from '@components/confirmBtcTransactionComponent'; -import styled from 'styled-components'; -import { saveTimeForNonOrdinalTransferTransaction } from '@utils/localStorage'; import InfoContainer from '@components/infoContainer'; -import { useTranslation } from 'react-i18next'; +import BottomBar from '@components/tabBar'; +import useBtcWalletData from '@hooks/queries/useBtcWalletData'; +import useBtcClient from '@hooks/useBtcClient'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; -import AlertMessage from '@components/alertMessage'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; import { Recipient } from '@secretkeylabs/xverse-core/transactions/btc'; -import useBtcClient from '@hooks/useBtcClient'; +import { BtcTransactionBroadcastResponse } from '@secretkeylabs/xverse-core/types'; +import { useMutation } from '@tanstack/react-query'; import { isLedgerAccount } from '@utils/helper'; -import { ConfirmBtcTransactionState, LedgerTransactionType } from '@common/types/ledger'; -import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import { ExternalSatsMethods, MESSAGE_SOURCE } from '@common/types/message-types'; -import AccountHeaderComponent from '@components/accountHeader'; +import { saveTimeForNonOrdinalTransferTransaction } from '@utils/localStorage'; +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const BottomBarContainer = styled.h1((props) => ({ marginTop: props.theme.spacing(5), @@ -29,7 +30,6 @@ function ConfirmBtcTransaction() { const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' }); const { ordinalsAddress, btcAddress, selectedAccount } = useWalletSelector(); const btcClient = useBtcClient(); - const [recipientAddress, setRecipientAddress] = useState(''); const [signedTx, setSignedTx] = useState(''); const [showOrdinalsDetectedAlert, setShowOrdinalsDetectedAlert] = useState(false); const location = useLocation(); @@ -40,6 +40,7 @@ function ConfirmBtcTransaction() { amount, signedTxHex, recipient, + recipientAddress, isRestoreFundFlow, unspentUtxos, btcSendBrowserTx, @@ -48,6 +49,10 @@ function ConfirmBtcTransaction() { isBrc20TokenFlow, feePerVByte, } = location.state; + if (typeof fee !== 'string' && !BigNumber.isBigNumber(fee)) { + Object.setPrototypeOf(fee, BigNumber.prototype); + } + const [currentFee, setCurrentFee] = useState(fee); const [currentFeeRate, setCurrentFeeRate] = useState(feePerVByte); @@ -94,10 +99,6 @@ function ConfirmBtcTransaction() { } }, [errorBtcOrdinalTransaction]); - useEffect(() => { - setRecipientAddress(location.state.recipientAddress); - }, [location]); - useEffect(() => { if (btcTxBroadcastData) { if (btcSendBrowserTx) { @@ -219,11 +220,8 @@ function ConfirmBtcTransaction() { isWarningAlert /> )} - {btcSendBrowserTx && ( - - )} + {btcSendBrowserTx && } ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(16), marginBottom: props.theme.spacing(16), textAlign: 'center', @@ -97,7 +98,7 @@ const Button = styled.button((props) => ({ const ButtonText = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -118,12 +119,12 @@ const DetailRow = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const Icon = styled.img((props) => ({ @@ -151,7 +152,8 @@ function ConfirmInscriptionRequest() { brcContent, feePerVByte, } = location.state; - const { btcAddress, network, selectedAccount, seedPhrase, btcFiatRate } = useWalletSelector(); + const { btcAddress, network, selectedAccount, btcFiatRate } = useWalletSelector(); + const { getSeed } = useSeedVault(); const btcClient = useBtcClient(); const [signedTx, setSignedTx] = useState(''); const [textContent, setTextContent] = useState(''); @@ -200,9 +202,10 @@ function ConfirmInscriptionRequest() { { recipients: Recipient[]; txFee: string; + seedPhrase: string; } >({ - mutationFn: async ({ recipients, txFee }) => + mutationFn: async ({ recipients, txFee, seedPhrase }) => signBtcTransaction( recipients, btcAddress, @@ -305,7 +308,7 @@ function ConfirmInscriptionRequest() { setShowFeeSettings(true); }; - const onApplyClick = ({ + const onApplyClick = async ({ fee: modifiedFee, feeRate, }: { @@ -313,8 +316,9 @@ function ConfirmInscriptionRequest() { feeRate?: string; nonce?: string; }) => { + const seedPhrase = await getSeed(); setCurrentFeeRate(new BigNumber(feeRate)); - mutateTxFee({ recipients: recipient, txFee: modifiedFee }); + mutateTxFee({ recipients: recipient, txFee: modifiedFee, seedPhrase }); }; const closeTransactionSettingAlert = () => { diff --git a/src/app/screens/confirmNftTransaction/index.tsx b/src/app/screens/confirmNftTransaction/index.tsx index 965baa8f1..fa4ee2b76 100644 --- a/src/app/screens/confirmNftTransaction/index.tsx +++ b/src/app/screens/confirmNftTransaction/index.tsx @@ -1,27 +1,27 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import { useMutation } from '@tanstack/react-query'; -import { useEffect } from 'react'; -import { useLocation, useNavigate, useParams } from 'react-router-dom'; -import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; -import { broadcastSignedTransaction } from '@secretkeylabs/xverse-core/transactions'; -import { deserializeTransaction } from '@stacks/transactions'; -import BottomBar from '@components/tabBar'; import AssetIcon from '@assets/img/transactions/Assets.svg'; -import ConfirmStxTransationComponent from '@components/confirmStxTransactionComponent'; -import useNftDataSelector from '@hooks/stores/useNftDataSelector'; -import NftImage from '@screens/nftDashboard/nftImage'; +import { ConfirmStxTransactionState, LedgerTransactionType } from '@common/types/ledger'; import AccountHeaderComponent from '@components/accountHeader'; -import TopRow from '@components/topRow'; -import useNetworkSelector from '@hooks/useNetwork'; +import ConfirmStxTransationComponent from '@components/confirmStxTransactionComponent'; import RecipientComponent from '@components/recipientComponent'; +import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; import TransactionDetailComponent from '@components/transactionDetailComponent'; -import useWalletSelector from '@hooks/useWalletSelector'; import useStxWalletData from '@hooks/queries/useStxWalletData'; -import { isLedgerAccount } from '@utils/helper'; -import { ConfirmStxTransactionState, LedgerTransactionType } from '@common/types/ledger'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useNetworkSelector from '@hooks/useNetwork'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import NftImage from '@screens/nftDashboard/nftImage'; +import { broadcastSignedTransaction } from '@secretkeylabs/xverse-core/transactions'; +import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; +import { deserializeTransaction } from '@stacks/transactions'; +import { useMutation } from '@tanstack/react-query'; +import { isLedgerAccount } from '@utils/helper'; import BigNumber from 'bignumber.js'; +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import styled from 'styled-components'; const ScrollContainer = styled.div` display: flex; @@ -36,38 +36,6 @@ const ScrollContainer = styled.div` margin: auto; `; -const ButtonContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'row', - marginLeft: '15%', - marginTop: props.theme.spacing(40), -})); - -const Button = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-end', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - opacity: 0.8, - marginTop: props.theme.spacing(5), -})); - -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', -})); - const Container = styled.div({ display: 'flex', flexDirection: 'column', @@ -83,14 +51,14 @@ const NFtContainer = styled.div((props) => ({ aspectRatio: 1, justifyContent: 'center', alignItems: 'center', - borderRadius: 8, + borderRadius: props.theme.radius(1), padding: props.theme.spacing(5), marginBottom: props.theme.spacing(6), })); const ReviewTransactionText = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(16), textAlign: 'center', })); @@ -187,17 +155,7 @@ function ConfirmNftTransaction() { return ( <> {isGalleryOpen && ( - <> - - {/* - - */} - + )} {!isGalleryOpen && } diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index bcb83443c..9187d19ab 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -78,8 +78,8 @@ function ConfirmOrdinalTransaction() { const [currentFee, setCurrentFee] = useState(fee); const [currentFeeRate, setCurrentFeeRate] = useState(feePerVByte); - const bundleId = selectedSatBundle ? getBundleId(selectedSatBundle) : ''; - const bundleSubText = selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; + const bundleId = isRareSat && selectedSatBundle ? getBundleId(selectedSatBundle) : ''; + const bundleSubText = isRareSat && selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; const { isLoading, diff --git a/src/app/screens/createInscription/ContentLabel/index.tsx b/src/app/screens/createInscription/ContentLabel/index.tsx index cc5aee1ee..8131b14da 100644 --- a/src/app/screens/createInscription/ContentLabel/index.tsx +++ b/src/app/screens/createInscription/ContentLabel/index.tsx @@ -6,6 +6,7 @@ import styled from 'styled-components'; import { DotsThreeVertical, Eye, Share } from '@phosphor-icons/react'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; +import useWalletSelector from '@hooks/useWalletSelector'; import { getBrc20Details } from '@utils/brc20'; import { ContentType } from './common'; import Preview from './preview'; @@ -104,6 +105,7 @@ function ContentIcon({ type, content, contentType: inputContentType }: Props) { const [showPreview, setShowPreview] = useState(false); const [showMenu, setShowMenu] = useState(false); const menuRef = useRef(null); + const { network } = useWalletSelector(); useEffect(() => { // Close menu when clicking outside @@ -182,12 +184,15 @@ function ContentIcon({ type, content, contentType: inputContentType }: Props) { const displayContent = type === 'PLAIN_TEXT' ? content : atob(content); if (canPreviewInOrd) { - const { data: previewId } = await axios.post(`${XVERSE_ORDIVIEW_URL}/previewHtml`, { - html: displayContent, - contentType: inputContentType, - }); - - window.open(`${XVERSE_ORDIVIEW_URL}/previewHtml/${previewId}`, '_blank'); + const { data: previewId } = await axios.post( + `${XVERSE_ORDIVIEW_URL(network.type)}/previewHtml`, + { + html: displayContent, + contentType: inputContentType, + }, + ); + + window.open(`${XVERSE_ORDIVIEW_URL(network.type)}/previewHtml/${previewId}`, '_blank'); } }; diff --git a/src/app/screens/createInscription/ErrorModal/index.tsx b/src/app/screens/createInscription/ErrorModal/index.tsx index 849fdfc26..dfd33c0ff 100644 --- a/src/app/screens/createInscription/ErrorModal/index.tsx +++ b/src/app/screens/createInscription/ErrorModal/index.tsx @@ -120,7 +120,7 @@ function ErrorModal({ errorCode, onRetrySubmit, onEnd }: Props) { } }; - const canResubmit = RESUBMIT_ERROR_CODES.includes(errorCode); + const canResubmit = onRetrySubmit && RESUBMIT_ERROR_CODES.includes(errorCode); return ( diff --git a/src/app/screens/createInscription/index.tsx b/src/app/screens/createInscription/index.tsx index 5710a0c84..29b96cb1c 100644 --- a/src/app/screens/createInscription/index.tsx +++ b/src/app/screens/createInscription/index.tsx @@ -27,6 +27,7 @@ import useWalletSelector from '@hooks/useWalletSelector'; import type { UTXO } from '@secretkeylabs/xverse-core/types'; import { getShortTruncatedAddress } from '@utils/helper'; +import useSeedVault from '@hooks/useSeedVault'; import CompleteScreen from './CompleteScreen'; import ContentLabel from './ContentLabel'; import EditFee from './EditFee'; @@ -179,23 +180,17 @@ function CreateInscription() { const [showFeeSettings, setShowFeeSettings] = useState(false); const [feeRate, setFeeRate] = useState(suggestedMinerFeeRate ?? DEFAULT_FEE_RATE); const [feeRates, setFeeRates] = useState(); + const { getSeed } = useSeedVault(); - const { - ordinalsAddress, - network, - btcAddress, - seedPhrase, - selectedAccount, - btcFiatRate, - fiatCurrency, - } = useWalletSelector(); + const { ordinalsAddress, network, btcAddress, selectedAccount, btcFiatRate, fiatCurrency } = + useWalletSelector(); useEffect(() => { getNonOrdinalUtxo(btcAddress, requestedNetwork.type).then(setUtxos); }, [btcAddress, requestedNetwork]); useEffect(() => { - fetchBtcFeeRate().then((feeRatesResponse: BtcFeeResponse) => { + fetchBtcFeeRate(network.type).then((feeRatesResponse: BtcFeeResponse) => { setFeeRates(feeRatesResponse); if (suggestedMinerFeeRate === undefined) { setFeeRate(feeRatesResponse.regular); @@ -238,6 +233,7 @@ function CreateInscription() { revealAddress: ordinalsAddress, serviceFee: appFee, serviceFeeAddress: appFeeAddress, + network: network.type, }); const { @@ -254,7 +250,7 @@ function CreateInscription() { feeRate, network: requestedNetwork.type, revealAddress: ordinalsAddress, - seedPhrase, + getSeedPhrase: getSeed, contentBase64: payloadType === 'BASE_64' ? content : undefined, contentString: payloadType === 'PLAIN_TEXT' ? content : undefined, serviceFee: appFee, @@ -328,7 +324,7 @@ function CreateInscription() { isError={!!errorCode} > - + {t('TITLE')} {t('SUBTITLE')} @@ -482,7 +478,7 @@ function CreateInscription() { )} diff --git a/src/app/screens/createPassword/index.tsx b/src/app/screens/createPassword/index.tsx index 3af658a6e..1df095a90 100644 --- a/src/app/screens/createPassword/index.tsx +++ b/src/app/screens/createPassword/index.tsx @@ -1,12 +1,9 @@ import { useWalletExistsContext } from '@components/guards/onboarding'; import PasswordInput from '@components/passwordInput'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletReducer from '@hooks/useWalletReducer'; -import { StoreState } from '@stores/index'; -import { storeEncryptedSeedAction } from '@stores/wallet/actions/actionCreators'; -import { encryptSeedPhrase } from '@utils/encryptionUtils'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; @@ -38,9 +35,7 @@ const StepDot = styled.div((props) => ({ width: 8, height: 8, borderRadius: 4, - backgroundColor: props.active - ? props.theme.colors.action.classic - : props.theme.colors.background.elevation3, + backgroundColor: props.active ? props.theme.colors.action.classic : props.theme.colors.elevation3, marginRight: props.theme.spacing(4), })); @@ -50,19 +45,10 @@ function CreatePassword(): JSX.Element { const [error, setError] = useState(''); const [currentStepIndex, setCurrentStepIndex] = useState(0); const navigate = useNavigate(); - const dispatch = useDispatch(); - const { seedPhrase } = useSelector((state: StoreState) => ({ - ...state.walletState, - })); const { t } = useTranslation('translation', { keyPrefix: 'CREATE_PASSWORD_SCREEN' }); const { createWallet } = useWalletReducer(); const { disableWalletExistsGuard } = useWalletExistsContext(); - - useEffect(() => { - if (!seedPhrase) { - navigate('/backup'); - } - }, [seedPhrase]); + const { getSeed, changePassword } = useSeedVault(); const handleContinuePasswordCreation = () => { setCurrentStepIndex(1); @@ -71,11 +57,9 @@ function CreatePassword(): JSX.Element { const handleConfirmPassword = async () => { if (confirmPassword === password) { disableWalletExistsGuard?.(); - - const encryptedSeed = await encryptSeedPhrase(seedPhrase, password); - dispatch(storeEncryptedSeedAction(encryptedSeed)); + const seedPhrase = await getSeed(); await createWallet(seedPhrase); - + await changePassword('', password); navigate('/wallet-success/create', { replace: true }); } else { setError(t('CONFIRM_PASSWORD_MATCH_ERROR')); diff --git a/src/app/screens/createWalletSuccess/index.tsx b/src/app/screens/createWalletSuccess/index.tsx index f14995102..1c2441d2e 100644 --- a/src/app/screens/createWalletSuccess/index.tsx +++ b/src/app/screens/createWalletSuccess/index.tsx @@ -16,7 +16,7 @@ const InstructionsContainer = styled.div((props) => ({ height: 127, width: 278, backgroundColor: 'rgba(39, 42, 68, 0.4)', - border: `1px solid ${props.theme.colors.background.elevation3}`, + border: `1px solid ${props.theme.colors.elevation3}`, borderRadius: 12, padding: `${props.theme.spacing(10.5)}px ${props.theme.spacing(10.5)}px ${props.theme.spacing( 10.5, @@ -49,7 +49,7 @@ const ContentContainer = styled.div((props) => ({ const Title = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(8), textAlign: 'center', fontSize: 20, @@ -57,14 +57,14 @@ const Title = styled.h1((props) => ({ const Subtitle = styled.h2((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(8), textAlign: 'center', })); const ContinueButton = styled.button((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, backgroundColor: props.theme.colors.action.classic, borderRadius: props.theme.radius(1), marginLeft: props.theme.spacing(8), diff --git a/src/app/screens/error/index.tsx b/src/app/screens/error/index.tsx index 4ba6135d3..95f88fdb4 100644 --- a/src/app/screens/error/index.tsx +++ b/src/app/screens/error/index.tsx @@ -1,9 +1,9 @@ +import Error from '@assets/img/ErrorBoundary/error.svg'; +import { SUPPORT_EMAIL } from '@utils/constants'; import React from 'react'; +import { useTranslation } from 'react-i18next'; import { useRouteError } from 'react-router-dom'; -import Error from '@assets/img/ErrorBoundary/error.svg'; import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; -import { SUPPORT_EMAIL } from '@utils/constants'; const ScreenContainer = styled.div((props) => ({ display: 'flex', @@ -12,7 +12,7 @@ const ScreenContainer = styled.div((props) => ({ width: '100vw', flexDirection: 'column', alignItems: 'center', - backgroundColor: props.theme.colors.background.elevation_1, + backgroundColor: props.theme.colors.elevation_n1, paddingTop: props.theme.spacing(80), paddingLeft: props.theme.spacing(9), paddingRight: props.theme.spacing(9), @@ -27,16 +27,16 @@ const ErrorDescription = styled.p((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(8), textAlign: 'center', - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const SupportText = styled.p((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(5), textAlign: 'center', - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, span: { - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, }, })); @@ -44,7 +44,7 @@ const ErrorContent = styled.p((props) => ({ ...props.theme.body_medium_m, marginTop: props.theme.spacing(20), textAlign: 'center', - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); function ErrorBoundary() { diff --git a/src/app/screens/executeBrc20Transaction/index.tsx b/src/app/screens/executeBrc20Transaction/index.tsx index b9407ccd2..e7244df54 100644 --- a/src/app/screens/executeBrc20Transaction/index.tsx +++ b/src/app/screens/executeBrc20Transaction/index.tsx @@ -1,26 +1,28 @@ +import { LoadingTransactionStatus } from '@components/loadingTransactionStatus'; +import { ConfirmationStatus } from '@components/loadingTransactionStatus/circularSvgAnimation'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; -import { ExecuteBrc20TransferState } from '@utils/brc20'; import { ExecuteTransferProgressCodes, useBrc20TransferExecute } from '@secretkeylabs/xverse-core'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { ExecuteBrc20TransferState } from '@utils/brc20'; import { getBtcTxStatusUrl } from '@utils/helper'; -import { ConfirmationStatus } from '@components/loadingTransactionStatus/circularSvgAnimation'; -import { useState, useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { LoadingTransactionStatus } from '@components/loadingTransactionStatus'; +import { useLocation, useNavigate } from 'react-router-dom'; const AMOUNT_OF_STEPS = Object.keys(ExecuteTransferProgressCodes).length + 1; const PERCENTAGE_PER_STEP = 1 / AMOUNT_OF_STEPS; export function ExecuteBrc20Transaction() { const { t } = useTranslation('translation', { keyPrefix: 'EXECUTE_BRC20' }); - const { selectedAccount, btcAddress, network, seedPhrase } = useWalletSelector(); + const { selectedAccount, btcAddress, network } = useWalletSelector(); const navigate = useNavigate(); const { recipientAddress, estimateFeesParams }: ExecuteBrc20TransferState = useLocation().state; + const { getSeed } = useSeedVault(); const { progress, complete, executeTransfer, transferTransactionId, errorCode } = useBrc20TransferExecute({ ...estimateFeesParams, - seedPhrase, + getSeedPhrase: getSeed, accountIndex: selectedAccount?.id ?? 0, changeAddress: btcAddress, recipientAddress, diff --git a/src/app/screens/forgotPassword/index.tsx b/src/app/screens/forgotPassword/index.tsx index 38edcf941..93e2c5303 100644 --- a/src/app/screens/forgotPassword/index.tsx +++ b/src/app/screens/forgotPassword/index.tsx @@ -1,5 +1,6 @@ -import BackHeader from '@components/backHeader'; +import ActionButton from '@components/button'; import CheckBox from '@components/checkBox'; +import TopRow from '@components/topRow'; import useWalletReducer from '@hooks/useWalletReducer'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -10,13 +11,13 @@ const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', height: '100%', - backgroundColor: props.theme.colors.background.elevation0, + backgroundColor: props.theme.colors.elevation0, padding: `0 ${props.theme.spacing(8)}px 0 ${props.theme.spacing(8)}px`, })); const Paragraph = styled.p((props) => ({ ...props.theme.body_l, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, textAlign: 'left', marginTop: props.theme.spacing(12), })); @@ -27,42 +28,19 @@ const BottomContainer = styled.div((props) => ({ const ButtonsContainer = styled.div((props) => ({ display: 'flex', - marginTop: props.theme.spacing(16), alignItems: 'center', justifyContent: 'space-between', + marginTop: props.theme.spacing(16), + columnGap: props.theme.spacing(8), })); -const ResetButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: props.theme.colors.feedback.error, - color: props.theme.colors.white['0'], - width: '48%', - height: 44, - '&:disabled': { - opacity: 0.6, - }, -})); - -const CancelButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: props.theme.colors.background.elevation0, - border: `1px solid ${props.theme.colors.background.elevation2}`, - color: props.theme.colors.white['0'], - width: '48%', - height: 44, -})); +const StyledTopRow = styled(TopRow)({ + marginLeft: 0, +}); function ForgotPassword(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'FORGOT_PASSWORD_SCREEN' }); - const [hasBackedUp, setHasBackedUp] = useState(false); + const [hasBackedUp, setHasBackedUp] = useState(false); const navigate = useNavigate(); const { resetWallet } = useWalletReducer(); @@ -74,14 +52,14 @@ function ForgotPassword(): JSX.Element { setHasBackedUp(!hasBackedUp); }; - const handleResetWallet = () => { - resetWallet(); + const handleResetWallet = async () => { + await resetWallet(); navigate('/'); }; return ( - + {t('PARAGRAPH1')} {t('PARAGRAPH2')} @@ -92,10 +70,13 @@ function ForgotPassword(): JSX.Element { onCheck={handleToggleBackUp} /> - Cancel - - Reset - + + diff --git a/src/app/screens/home/balanceCard/index.tsx b/src/app/screens/home/balanceCard/index.tsx index 1f686a460..880547c9c 100644 --- a/src/app/screens/home/balanceCard/index.tsx +++ b/src/app/screens/home/balanceCard/index.tsx @@ -18,20 +18,20 @@ const RowContainer = styled.div((props) => ({ const BalanceHeadingText = styled.h3((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, textTransform: 'uppercase', opacity: 0.7, })); const CurrencyText = styled.label((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, fontSize: 13, })); const BalanceAmountText = styled.p((props) => ({ ...props.theme.headline_xl, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const BarLoaderContainer = styled.div((props) => ({ @@ -43,7 +43,7 @@ const BarLoaderContainer = styled.div((props) => ({ const CurrencyCard = styled.div((props) => ({ display: 'flex', justifyContent: 'center', - backgroundColor: props.theme.colors.background.elevation3, + backgroundColor: props.theme.colors.elevation3, width: 45, borderRadius: 30, marginLeft: props.theme.spacing(4), diff --git a/src/app/screens/home/coinSelectModal/index.tsx b/src/app/screens/home/coinSelectModal/index.tsx index 7c5e966e3..38728bc3e 100644 --- a/src/app/screens/home/coinSelectModal/index.tsx +++ b/src/app/screens/home/coinSelectModal/index.tsx @@ -1,11 +1,11 @@ -import BottomModal from '@components/bottomModal'; -import TokenTile from '@components/tokenTile'; -import { FungibleToken } from '@secretkeylabs/xverse-core/types'; import IconBitcoin from '@assets/img/dashboard/bitcoin_icon.svg'; import IconStacks from '@assets/img/dashboard/stack_icon.svg'; +import BottomModal from '@components/bottomModal'; +import TokenTile from '@components/tokenTile'; +import useWalletSelector from '@hooks/useWalletSelector'; +import type { FungibleToken } from '@secretkeylabs/xverse-core'; import { useTranslation } from 'react-i18next'; import styled, { useTheme } from 'styled-components'; -import useWalletSelector from '@hooks/useWalletSelector'; const Container = styled.div((props) => ({ marginTop: props.theme.spacing(6), @@ -55,7 +55,7 @@ function CoinSelectModal({ currency="BTC" icon={IconBitcoin} loading={loadingWalletData} - underlayColor={theme.colors.background.elevation2} + underlayColor={theme.colors.elevation2} margin={14} enlargeTicker onPress={handleOnBitcoinPress} @@ -67,7 +67,7 @@ function CoinSelectModal({ currency="STX" icon={IconStacks} loading={loadingWalletData} - underlayColor={theme.colors.background.elevation2} + underlayColor={theme.colors.elevation2} margin={14} enlargeTicker onPress={handleOnStackPress} @@ -89,7 +89,7 @@ function CoinSelectModal({ currency="FT" icon={IconStacks} loading={loadingWalletData} - underlayColor={theme.colors.background.elevation2} + underlayColor={theme.colors.elevation2} margin={14} enlargeTicker onPress={() => { diff --git a/src/app/screens/home/index.tsx b/src/app/screens/home/index.tsx index cd79d583e..b32baf195 100644 --- a/src/app/screens/home/index.tsx +++ b/src/app/screens/home/index.tsx @@ -5,7 +5,7 @@ import ListDashes from '@assets/img/dashboard/list_dashes.svg'; import ordinalsIcon from '@assets/img/dashboard/ordinalBRC20.svg'; import SIP10Icon from '@assets/img/dashboard/SIP10.svg'; import stacksIcon from '@assets/img/dashboard/stack_icon.svg'; -import Swap from '@assets/img/dashboard/swap.svg'; +import ArrowSwap from '@assets/img/icons/ArrowSwap.svg'; import AccountHeaderComponent from '@components/accountHeader'; import BottomModal from '@components/bottomModal'; import ActionButton from '@components/button'; @@ -25,7 +25,7 @@ import useStxWalletData from '@hooks/queries/useStxWalletData'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowDown, ArrowUp, Plus } from '@phosphor-icons/react'; import CoinSelectModal from '@screens/home/coinSelectModal'; -import { FungibleToken } from '@secretkeylabs/xverse-core/types'; +import type { FungibleToken } from '@secretkeylabs/xverse-core'; import { changeShowDataCollectionAlertAction } from '@stores/wallet/actions/actionCreators'; import { CurrencyTypes } from '@utils/constants'; import { isLedgerAccount } from '@utils/helper'; @@ -88,7 +88,7 @@ const Button = styled.button((props) => ({ const ButtonText = styled.div((props) => ({ ...props.theme.body_xs, fontWeight: 700, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -193,6 +193,7 @@ function Home() { showBtcReceiveAlert, showOrdinalReceiveAlert, showDataCollectionAlert, + network, } = useWalletSelector(); const [areReceivingAddressesVisible, setAreReceivingAddressesVisible] = useState( !isLedgerAccount(selectedAccount), @@ -434,7 +435,7 @@ function Home() { dispatch(changeShowDataCollectionAlertAction(false)); }; - const showSwaps = !isLedgerAccount(selectedAccount); + const showSwaps = !isLedgerAccount(selectedAccount) && network.type !== 'Testnet'; return ( <> @@ -466,7 +467,7 @@ function Home() { text={t('RECEIVE')} onPress={onReceiveModalOpen} /> - {showSwaps && } + {showSwaps && } } text={t('BUY')} diff --git a/src/app/screens/landing/index.tsx b/src/app/screens/landing/index.tsx index 6f0e363d2..c4bff032a 100644 --- a/src/app/screens/landing/index.tsx +++ b/src/app/screens/landing/index.tsx @@ -27,7 +27,7 @@ const LandingTitle = styled.h1((props) => ({ paddingTop: props.theme.spacing(15), paddingLeft: props.theme.spacing(34), paddingRight: props.theme.spacing(34), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, textAlign: 'center', fontSize: 16, })); @@ -46,7 +46,7 @@ const CreateButton = styled.button((props) => ({ display: 'flex', ...props.theme.body_medium_m, fontSize: 12, - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, textAlign: 'center', flexDirection: 'row', justifyContent: 'center', @@ -67,7 +67,7 @@ const CreateButton = styled.button((props) => ({ const AppVersion = styled.p((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'right', marginRight: props.theme.spacing(9), marginTop: props.theme.spacing(8), @@ -77,18 +77,18 @@ const RestoreButton = styled.button((props) => ({ display: 'flex', ...props.theme.body_medium_m, fontSize: 12, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', borderRadius: props.theme.radius(1), - backgroundColor: props.theme.colors.background.elevation0, - border: `0.5px solid ${props.theme.colors.background.elevation2}`, + backgroundColor: props.theme.colors.elevation0, + border: `0.5px solid ${props.theme.colors.elevation2}`, width: '100%', height: 44, ':hover': { - background: props.theme.colors.background.elevation6_800, + background: props.theme.colors.elevation6_800, }, ':focus': { background: props.theme.colors.action.classic800, diff --git a/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts b/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts index c2a87b3eb..e275def9f 100644 --- a/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts +++ b/src/app/screens/ledger/confirmLedgerTransaction/index.styled.ts @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import { animated } from '@react-spring/web'; +import styled from 'styled-components'; export const Container = styled.div` display: flex; @@ -47,7 +47,7 @@ export const TxConfirmedTitle = styled.h1((props) => ({ export const TxConfirmedDescription = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); export const InfoImage = styled.img({ @@ -66,7 +66,7 @@ export const ConnectLedgerTextAdvanced = styled.p<{ ...props.theme.body_m, display: 'flex', alignItems: 'flex-start', - color: props.isCompleted ? props.theme.colors.white[400] : props.theme.colors.white[200], + color: props.isCompleted ? props.theme.colors.white_400 : props.theme.colors.white_200, textAlign: 'center', marginBottom: props.theme.spacing(16), })); @@ -90,7 +90,7 @@ export const TxDetailsRow = styled.div((props) => ({ })); export const TxDetailsTitle = styled.div((props) => ({ - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); export const RecipientsWrapper = styled.div({ diff --git a/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts b/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts index 9315ffe30..00a5c04b4 100644 --- a/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts +++ b/src/app/screens/ledger/verifyLedgerAccountAddress/index.styled.ts @@ -1,5 +1,5 @@ -import styled from 'styled-components'; import { animated } from '@react-spring/web'; +import styled from 'styled-components'; export const Container = styled.div` display: flex; @@ -37,7 +37,7 @@ export const SelectAssetTitle = styled.h1((props) => ({ export const SelectAssetText = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, textAlign: 'center', })); @@ -80,7 +80,7 @@ export const CopyContainer = styled.div((props) => ({ export const QRCodeContainer = styled.div((props) => ({ display: 'flex', aspectRatio: 1, - backgroundColor: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.white_0, justifyContent: 'center', alignItems: 'center', borderRadius: props.theme.radius(1), diff --git a/src/app/screens/legalLinks/index.tsx b/src/app/screens/legalLinks/index.tsx index a21455c02..6ea1f47d5 100644 --- a/src/app/screens/legalLinks/index.tsx +++ b/src/app/screens/legalLinks/index.tsx @@ -18,19 +18,19 @@ const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', padding: props.theme.spacing(8), - paddingTop: props.theme.spacing(28), - paddingBottom: props.theme.spacing(28), + paddingTop: props.theme.spacing(20), + paddingBottom: props.theme.spacing(32), justifyContent: 'space-between', })); const Title = styled.h1((props) => ({ ...props.theme.bold_tile_text, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const SubTitle = styled.h1((props) => ({ - ...props.theme.body_l, - color: props.theme.colors.white['200'], + ...props.theme.typography.body_m, + color: props.theme.colors.white_200, marginTop: props.theme.spacing(8), })); @@ -39,11 +39,11 @@ const LinksContainer = styled.div((props) => ({ })); const Link = styled.a((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_medium_m, display: 'flex', justifyContent: 'space-between', marginTop: props.theme.spacing(8), - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const CustomizedLink = styled(Link)` @@ -57,6 +57,7 @@ const CustomizedLink = styled(Link)` `; const SwitchContainer = styled.div((props) => ({ + ...props.theme.typography.body_medium_m, display: 'flex', justifyContent: 'space-between', alignItems: 'center', @@ -64,6 +65,12 @@ const SwitchContainer = styled.div((props) => ({ fontSize: '0.875rem', })); +const DataCollectionDescription = styled.p((props) => ({ + ...props.theme.body_m, + color: props.theme.colors.white_200, + marginTop: props.theme.spacing(32), +})); + function LegalLinks() { const { t } = useTranslation('translation', { keyPrefix: 'LEGAL_SCREEN' }); const navigate = useNavigate(); @@ -71,7 +78,7 @@ function LegalLinks() { const { selectedAccount } = useWalletSelector(); const [searchParams] = useSearchParams(); const theme = useTheme(); - const [isToggleEnabled, setIsToggleEnabled] = useState(false); + const [isToggleEnabled, setIsToggleEnabled] = useState(true); const handleSwitchToggle = () => setIsToggleEnabled((prevEnabledState) => !prevEnabledState); @@ -105,9 +112,11 @@ function LegalLinks() { {t('PRIVACY_POLICY_LINK_BUTTON')} privacy - + + {t('AUTHORIZE_DATA_COLLECTION.DESCRIPTION')} + -
{t('AUTHORIZE_DATA_COLLECTION')}
+
{t('AUTHORIZE_DATA_COLLECTION.TITLE')}
({ display: 'flex', flexDirection: 'column', flex: 1, - paddingLeft: 18, - paddingRight: 18, + paddingLeft: props.theme.spacing(9), + paddingRight: props.theme.spacing(9), overflowY: 'auto', '&::-webkit-scrollbar': { display: 'none', }, -}); +})); const ContentContainer = styled(animated.div)({ display: 'flex', @@ -46,7 +41,7 @@ const ContentContainer = styled(animated.div)({ const AppVersion = styled.p((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'right', marginTop: props.theme.spacing(8), })); @@ -70,7 +65,7 @@ const PasswordInputContainer = styled.div((props) => ({ display: 'flex', alignItems: 'center', width: '100%', - border: `1px solid ${props.theme.colors.background.elevation3}`, + border: `1px solid ${props.theme.colors.elevation3}`, paddingLeft: props.theme.spacing(8), paddingRight: props.theme.spacing(8), borderRadius: props.theme.radius(1), @@ -80,8 +75,8 @@ const PasswordInputContainer = styled.div((props) => ({ const PasswordInput = styled.input((props) => ({ ...props.theme.body_medium_m, height: 44, - backgroundColor: props.theme.colors.background.elevation0, - color: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.elevation0, + color: props.theme.colors.white_0, width: '100%', border: 'none', })); @@ -91,7 +86,7 @@ const LandingTitle = styled.h1((props) => ({ paddingTop: props.theme.spacing(15), paddingLeft: props.theme.spacing(34), paddingRight: props.theme.spacing(34), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, textAlign: 'center', })); @@ -111,7 +106,7 @@ const ForgotPasswordButton = styled.a((props) => ({ ...props.theme.body_m, textAlign: 'center', marginTop: props.theme.spacing(12), - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textDecoration: 'underline', })); @@ -119,8 +114,6 @@ function Login(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'LOGIN_SCREEN' }); const navigate = useNavigate(); const { unlockWallet } = useWalletReducer(); - const { encryptedSeed } = useWalletSelector(); - const [isPasswordVisible, setIsPasswordVisible] = useState(false); const [password, setPassword] = useState(''); const [error, setError] = useState(''); @@ -166,7 +159,6 @@ function Login(): JSX.Element { const handleVerifyPassword = async () => { setIsVerifying(true); try { - await decryptSeedPhrase(encryptedSeed, password); const hasMigrated = localStorage.getItem('migrated'); const isReminderDue = Number(localStorage.getItem('migrationReminder') || 0) <= new Date().getTime(); diff --git a/src/app/screens/manageTokens/coinItem/index.tsx b/src/app/screens/manageTokens/coinItem/index.tsx index c76098630..df92b5aa0 100644 --- a/src/app/screens/manageTokens/coinItem/index.tsx +++ b/src/app/screens/manageTokens/coinItem/index.tsx @@ -53,7 +53,7 @@ const TickerIconContainer = styled.div((props) => ({ const TickerText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', wordBreak: 'break-all', fontSize: 10, @@ -61,13 +61,13 @@ const TickerText = styled.h1((props) => ({ const SelectedCoinTitleText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); const UnSelectedCoinTitleText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'center', })); diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx index bc9b56d33..a1ab7d94c 100644 --- a/src/app/screens/nftDashboard/collectiblesTabs.tsx +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -40,8 +40,8 @@ const StyledWrenchErrorMessage = styled(WrenchErrorMessage)` `; const NoCollectiblesText = styled.div((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['200'], + ...props.theme.typography.body_bold_m, + color: props.theme.colors.white_200, marginTop: props.theme.spacing(16), textAlign: 'center', })); @@ -78,10 +78,11 @@ function SkeletonLoader({ isGalleryOpen }: { isGalleryOpen: boolean }) { ); } -const tabs: { +type TabButton = { key: string; label: string; -}[] = [ +}; +const tabs: TabButton[] = [ { key: 'inscriptions', label: 'INSCRIPTIONS', @@ -118,16 +119,15 @@ export default function CollectiblesTabs({ const [tabIndex, setTabIndex] = useState(tabKeyToIndex(searchParams?.get('tab'))); const { isGalleryOpen, - hasActivatedOrdinalsKey, rareSatsQuery, totalNfts, totalInscriptions, hasActivatedRareSatsKey, + hasActivatedOrdinalsKey, showNoticeAlert, onDismissRareSatsNotice, - onLoadMoreRareSatsButtonClick, - isLoading, - isLoadingOrdinalCollections, + stacksNftsQuery, + inscriptionsQuery, } = nftDashboard; const handleSelectTab = (index: number) => { @@ -142,31 +142,43 @@ export default function CollectiblesTabs({ const showNoBundlesNotice = ordinalBundleCount === 0 && !rareSatsQuery.isLoading && !rareSatsQuery.error; + const visibleTabButtons = tabs.filter((tab: TabButton) => { + if (tab.key === 'rareSats' && !hasActivatedRareSatsKey) { + return false; + } + if (tab.key === 'inscriptions' && !hasActivatedOrdinalsKey) { + return false; + } + return true; + }); + return ( - {hasActivatedRareSatsKey && ( + {visibleTabButtons.length > 1 && ( - {tabs.map(({ key, label }) => ( + {visibleTabButtons.map(({ key, label }) => ( {t(label)} ))} )} + {hasActivatedOrdinalsKey && ( + + {inscriptionsQuery.isLoading ? ( + + ) : ( + <> + {totalInscriptions > 0 && ( + + {t('TOTAL_ITEMS', { total: totalInscriptions || 0 })} + + )} + {inscriptionListView} + + )} + + )} - {isLoadingOrdinalCollections ? ( - - ) : ( - <> - {totalInscriptions > 0 && ( - - {t('TOTAL_ITEMS', { total: totalInscriptions || 0 })} - - )} - {inscriptionListView} - - )} - - - {isLoading ? ( + {stacksNftsQuery.isLoading ? ( ) : ( <> @@ -179,56 +191,59 @@ export default function CollectiblesTabs({ )} - - {!rareSatsQuery.isLoading && ordinalBundleCount > 0 && ( - - {t('TOTAL_ITEMS', { total: ordinalBundleCount })} - - )} - - {!rareSatsQuery.isLoading && showNoticeAlert && ( - - { - onDismissRareSatsNotice(); - }} - seeRarities={() => { - navigate('supported-rarity-scale'); - }} - /> - - )} - {showNoBundlesNotice && {t('NO_COLLECTIBLES')}} - - {!!rareSatsQuery.error && } - {rareSatsQuery.isLoading ? ( - - ) : ( - - {hasActivatedOrdinalsKey && - !rareSatsQuery.error && - !rareSatsQuery.isLoading && - rareSatsQuery.data?.pages - ?.map((page) => page?.results) - .flat() - .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) - .map((bundle: Bundle) => )} - - )} - {rareSatsQuery.hasNextPage && ( - - - - )} - + {hasActivatedRareSatsKey && ( + + {!rareSatsQuery.isLoading && ordinalBundleCount > 0 && ( + + {t('TOTAL_ITEMS', { total: ordinalBundleCount })} + + )} + + {!rareSatsQuery.isLoading && showNoticeAlert && ( + + { + onDismissRareSatsNotice(); + }} + seeRarities={() => { + navigate('supported-rarity-scale'); + }} + /> + + )} + {showNoBundlesNotice && {t('NO_COLLECTIBLES')}} + + {!!rareSatsQuery.error && } + {rareSatsQuery.isLoading ? ( + + ) : ( + + {!rareSatsQuery.error && + !rareSatsQuery.isLoading && + rareSatsQuery.data?.pages + ?.map((page) => page?.results) + .flat() + .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) + .map((bundle: Bundle) => ( + + ))} + + )} + {rareSatsQuery.hasNextPage && ( + + + + )} + + )} ); } diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index 3e432d575..ccd04392e 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -9,7 +9,7 @@ import { useAddressRareSats } from '@hooks/queries/ordinals/useAddressRareSats'; import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowDown, Wrench } from '@phosphor-icons/react'; -import type { InscriptionCollectionsData } from '@secretkeylabs/xverse-core/types'; +import type { InscriptionCollectionsData } from '@secretkeylabs/xverse-core'; import { ChangeActivateOrdinalsAction, ChangeActivateRareSatsAction, @@ -27,6 +27,7 @@ import CollectiblesTabs, { GridContainer } from './collectiblesTabs'; import { InscriptionsTabGridItem } from './inscriptionsTabGridItem'; import Nft from './nft'; import ReceiveNftModal from './receiveNft'; +import { StyledBarLoader, TilesSkeletonLoader } from './tilesSkeletonLoader'; const Container = styled.div` display: flex; @@ -39,7 +40,7 @@ const Container = styled.div` const PageHeader = styled.div` padding: ${(props) => props.theme.space.s}; padding-bottom: ${(props) => props.theme.space.xl}; - border-bottom: 0.5px solid ${(props) => props.theme.colors.background.elevation3}; + border-bottom: 0.5px solid ${(props) => props.theme.colors.elevation3}; max-width: 1224px; margin-left: auto; margin-right: auto; @@ -65,7 +66,7 @@ const ReceiveNftContainer = styled.div((props) => ({ top: 0, right: 0, zIndex: 2000, - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, borderRadius: 16, })); @@ -87,8 +88,8 @@ const ReceiveButtonContainer = styled.div(() => ({ })); const NoCollectiblesText = styled.h1((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['200'], + ...props.theme.typography.body_bold_m, + color: props.theme.colors.white_200, marginTop: props.theme.spacing(16), marginBottom: 'auto', textAlign: 'center', @@ -109,8 +110,8 @@ const ErrorTextContainer = styled.div((props) => ({ })); const ErrorText = styled.div((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['200'], + ...props.theme.typography.body_bold_m, + color: props.theme.colors.white_200, })); const LoadMoreButtonContainer = styled.div((props) => ({ @@ -128,8 +129,9 @@ export type NftDashboardState = { openReceiveModal: boolean; showNewFeatureAlert: boolean; isOrdinalReceiveAlertVisible: boolean; - isLoading: boolean; - isLoadingOrdinalCollections: boolean; + stacksNftsQuery: ReturnType; + inscriptionsQuery: ReturnType; + rareSatsQuery: ReturnType; openInGalleryView: () => void; onReceiveModalOpen: () => void; onReceiveModalClose: () => void; @@ -145,59 +147,25 @@ export type NftDashboardState = { hasActivatedOrdinalsKey?: boolean; hasActivatedRareSatsKey?: boolean; showNoticeAlert?: boolean; - rareSatsQuery: ReturnType; totalNfts: number; totalInscriptions: number; - onLoadMoreRareSatsButtonClick: () => void; }; const useNftDashboard = (): NftDashboardState => { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); const dispatch = useDispatch(); - const { - stxAddress, - ordinalsAddress, - hasActivatedOrdinalsKey, - hasActivatedRareSatsKey, - rareSatsNoticeDismissed, - } = useWalletSelector(); + const { hasActivatedOrdinalsKey, hasActivatedRareSatsKey, rareSatsNoticeDismissed } = + useWalletSelector(); const [openReceiveModal, setOpenReceiveModal] = useState(false); const [showNewFeatureAlert, setShowNewFeatureAlert] = useState(false); const [showNoticeAlert, setShowNoticeAlert] = useState(false); const [isOrdinalReceiveAlertVisible, setIsOrdinalReceiveAlertVisible] = useState(false); - const { - data: nftsList, - error: stacksError, - hasNextPage, - isFetchingNextPage, - isLoading, - refetch, - fetchNextPage, - } = useStacksCollectibles(); - const { - data: ordinalCollections, - error: ordinalCollectionsError, - hasNextPage: hasNextPageOrdinalCollections, - isFetchingNextPage: isFetchingNextPageOrdinalCollections, - isLoading: isLoadingOrdinalCollections, - fetchNextPage: fetchNextOrdinalsPageCollections, - refetch: refetchOrdinalCollections, - } = useAddressInscriptionCollections(); - + const stacksNftsQuery = useStacksCollectibles(); + const inscriptionsQuery = useAddressInscriptionCollections(); const rareSatsQuery = useAddressRareSats(); - const refetchCollectibles = useCallback(async () => { - await refetch(); - await refetchOrdinalCollections(); - }, [refetch, refetchOrdinalCollections]); - - useEffect(() => { - refetchCollectibles(); - }, [stxAddress, ordinalsAddress]); - - const nfts = nftsList?.pages.map((page) => page.nftsList).flat(); - const ordinalsLength = ordinalCollections?.pages[0].total; - const totalNfts = nftsList && nftsList.pages.length > 0 ? nftsList.pages[0].total : 0; + const ordinalsLength = inscriptionsQuery.data?.pages?.[0]?.total ?? 0; + const totalNfts = stacksNftsQuery.data?.pages?.[0]?.total ?? 0; const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); @@ -214,15 +182,6 @@ const useNftDashboard = (): NftDashboardState => { setShowNoticeAlert(rareSatsNoticeDismissed === undefined); }, [rareSatsNoticeDismissed]); - const onLoadMoreButtonClick = () => { - if (hasNextPageOrdinalCollections) { - fetchNextOrdinalsPageCollections(); - } - if (hasNextPage) { - fetchNextPage(); - } - }; - const openInGalleryView = async () => { await chrome.tabs.create({ url: chrome.runtime.getURL('options.html#/nft-dashboard'), @@ -246,7 +205,7 @@ const useNftDashboard = (): NftDashboardState => { }; const InscriptionListView = useCallback(() => { - if (ordinalCollectionsError && !(ordinalCollectionsError instanceof InvalidParamsError)) { + if (inscriptionsQuery.error && !(inscriptionsQuery.error instanceof InvalidParamsError)) { return ( @@ -265,36 +224,30 @@ const useNftDashboard = (): NftDashboardState => { return ( <> - {ordinalCollections?.pages + {inscriptionsQuery.data?.pages ?.map((page) => page?.results) .flat() .map((collection: InscriptionCollectionsData) => ( ))} - {hasNextPageOrdinalCollections && ( + {inscriptionsQuery.hasNextPage && ( )} ); - }, [ - ordinalCollections, - hasActivatedOrdinalsKey, - ordinalCollectionsError, - hasNextPageOrdinalCollections, - isFetchingNextPageOrdinalCollections, - ]); + }, [inscriptionsQuery, isGalleryOpen, ordinalsLength, t]); const NftListView = useCallback(() => { - if (stacksError && !(stacksError instanceof InvalidParamsError)) { + if (stacksNftsQuery.error && !(stacksNftsQuery.error instanceof InvalidParamsError)) { return ( @@ -313,8 +266,10 @@ const useNftDashboard = (): NftDashboardState => { return ( <> - {!stacksError && - nfts?.map((nft) => ( + {stacksNftsQuery.data?.pages + ?.map((page) => page.nftsList) + .flat() + .map((nft) => ( { /> ))} - {hasNextPage && ( + {stacksNftsQuery.hasNextPage && ( )} ); - }, [nfts, stacksError]); + }, [stacksNftsQuery, isGalleryOpen, totalNfts, t]); const onActivateRareSatsAlertCrossPress = () => { setShowNewFeatureAlert(false); @@ -358,18 +313,12 @@ const useNftDashboard = (): NftDashboardState => { dispatch(SetRareSatsNoticeDismissedAction(true)); }; - const onLoadMoreRareSatsButtonClick = () => { - if (rareSatsQuery?.hasNextPage) { - rareSatsQuery.fetchNextPage(); - } - }; - return { openReceiveModal, showNewFeatureAlert, isOrdinalReceiveAlertVisible, - isLoading, - isLoadingOrdinalCollections, + stacksNftsQuery, + inscriptionsQuery, openInGalleryView, onReceiveModalOpen, onReceiveModalClose, @@ -388,7 +337,6 @@ const useNftDashboard = (): NftDashboardState => { rareSatsQuery, totalNfts, totalInscriptions: ordinalsLength, - onLoadMoreRareSatsButtonClick, }; }; diff --git a/src/app/screens/nftDashboard/notice.tsx b/src/app/screens/nftDashboard/notice.tsx index 5c995910e..f1672147a 100644 --- a/src/app/screens/nftDashboard/notice.tsx +++ b/src/app/screens/nftDashboard/notice.tsx @@ -46,7 +46,7 @@ const BundleLinkContainer = styled.button((props) => ({ color: props.theme.colors.white_0, transition: 'background-color 0.2s ease, opacity 0.2s ease', ':hover': { - color: props.theme.colors.white_200 + color: props.theme.colors.white_200, }, })); const BundleLinkText = styled.div((props) => ({ diff --git a/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx b/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx new file mode 100644 index 000000000..e514977cb --- /dev/null +++ b/src/app/screens/nftDashboard/tilesSkeletonLoader.tsx @@ -0,0 +1,41 @@ +import { BetterBarLoader } from '@components/barLoader'; +import styled from 'styled-components'; + +const TilesLoaderContainer = styled.div({ + display: 'flex', + justifyContent: 'space-between', +}); + +const TileLoaderContainer = styled.div({ + display: 'flex', + flexDirection: 'column', +}); + +export const StyledBarLoader = styled(BetterBarLoader)<{ + withMarginBottom?: boolean; +}>((props) => ({ + padding: 0, + borderRadius: 6, + marginBottom: props.withMarginBottom ? props.theme.spacing(6) : 0, +})); + +export function TilesSkeletonLoader({ + className, + tileSize = 151, +}: { + className?: string; + tileSize?: number; +}) { + return ( + + + + + + + + + + + ); +} diff --git a/src/app/screens/nftDetail/index.tsx b/src/app/screens/nftDetail/index.tsx index 9afbbc16d..5497fc607 100644 --- a/src/app/screens/nftDetail/index.tsx +++ b/src/app/screens/nftDetail/index.tsx @@ -108,33 +108,33 @@ const ExtensionNFtContainer = styled.div((props) => ({ const NftTitleText = styled.h1((props) => ({ ...props.theme.headline_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(12), textAlign: 'center', })); const CollectibleText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'center', })); const NftGalleryTitleText = styled.h1((props) => ({ ...props.theme.headline_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(12), })); const DescriptionText = styled.h1((props) => ({ ...props.theme.headline_l, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, fontSize: 24, marginBottom: props.theme.spacing(16), })); const NftOwnedByText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'center', })); @@ -162,7 +162,7 @@ const GridContainer = styled.div((props) => ({ gridTemplateColumns: 'repeat(auto-fit,minmax(150px,1fr))', paddingBottom: props.theme.spacing(16), marginBottom: props.theme.spacing(12), - borderBottom: `1px solid ${props.theme.colors.background.elevation2}`, + borderBottom: `1px solid ${props.theme.colors.elevation2}`, })); const ShareButtonContainer = styled.div((props) => ({ @@ -179,7 +179,7 @@ const DescriptionContainer = styled.h1((props) => ({ const AttributeText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginBottom: props.theme.spacing(2), letterSpacing: '0.02em', textTransform: 'uppercase', @@ -199,7 +199,7 @@ const WebGalleryButton = styled.button((props) => ({ const WebGalleryButtonText = styled.div((props) => ({ ...props.theme.body_m, fontWeight: 700, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, textAlign: 'center', })); @@ -220,20 +220,20 @@ const Button = styled.button((props) => ({ const ButtonText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const AssetDeatilButtonText = styled.div((props) => ({ ...props.theme.body_xs, fontWeight: 400, fontSize: 14, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); const ButtonHiglightedText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(2), marginRight: props.theme.spacing(2), })); diff --git a/src/app/screens/nftDetail/nftAttribute.tsx b/src/app/screens/nftDetail/nftAttribute.tsx index d4eb63056..7f00fd22c 100644 --- a/src/app/screens/nftDetail/nftAttribute.tsx +++ b/src/app/screens/nftDetail/nftAttribute.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; const Container = styled.h1((props) => ({ display: 'flex', borderRadius: 20, - border: `1px solid ${props.theme.colors.background.elevation3}`, + border: `1px solid ${props.theme.colors.elevation3}`, flexDirection: 'row', marginEnd: 10, padding: props.theme.spacing(5), @@ -12,12 +12,12 @@ const Container = styled.h1((props) => ({ const TypeText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, wordBreak: 'break-all', marginLeft: props.theme.spacing(3), })); diff --git a/src/app/screens/onboarding/index.tsx b/src/app/screens/onboarding/index.tsx index f061f0aa4..9e9e91c4c 100644 --- a/src/app/screens/onboarding/index.tsx +++ b/src/app/screens/onboarding/index.tsx @@ -46,7 +46,7 @@ const OnboardingSubTitle = styled.h1((props) => ({ ...props.theme.body_l, textAlign: 'center', marginTop: props.theme.spacing(8), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const OnBoardingActionsContainer = styled.div((props) => ({ display: 'flex', diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index f4cbc3925..418feae32 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import SquaresFour from '@assets/img/nftDashboard/squares_four.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import AccountHeaderComponent from '@components/accountHeader'; import AlertMessage from '@components/alertMessage'; @@ -11,6 +10,7 @@ import Separator from '@components/separator'; import SquareButton from '@components/squareButton'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; +import WebGalleryButton from '@components/webGalleryButton'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import { ArrowRight, ArrowUp, CubeTransparent, Share } from '@phosphor-icons/react'; import OrdinalImage from '@screens/ordinals/ordinalImage'; @@ -95,31 +95,31 @@ const ExtensionOrdinalsContainer = styled.div((props) => ({ })); const OrdinalTitleText = styled.h1((props) => ({ - ...props.theme.headline_m, + ...props.theme.typography.headline_m, color: props.theme.colors.white_0, marginTop: props.theme.spacing(1), textAlign: 'center', })); const OrdinalGalleryTitleText = styled.h1((props) => ({ - ...props.theme.headline_l, - color: props.theme.colors.white['0'], + ...props.theme.typography.headline_l, + color: props.theme.colors.white_0, })); const DescriptionText = styled.h1((props) => ({ - ...props.theme.headline_l, - color: props.theme.colors.white['0'], + ...props.theme.typography.headline_l, + color: props.theme.colors.white_0, fontSize: 24, marginBottom: props.theme.spacing(8), })); const NftOwnedByText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_400, })); const OwnerAddressText = styled.h1((props) => ({ - ...props.theme.body_medium_m, + ...props.theme.typography.body_medium_m, marginLeft: props.theme.spacing(3), })); @@ -152,6 +152,7 @@ const OrdinalDetailsContainer = styled.div((props) => ({ wordBreak: 'break-all', whiteSpace: 'pre-wrap', width: props.isGallery ? 400 : '100%', + marginTop: props.theme.spacing(8), })); const Row = styled.div({ @@ -170,16 +171,9 @@ const DescriptionContainer = styled.h1((props) => ({ marginBottom: props.theme.spacing(30), })); -const WebGalleryButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - width: '100%', - marginTop: props.theme.spacing(6), -})); +const StyledWebGalleryButton = styled(WebGalleryButton)` + margintop: ${(props) => props.theme.space.s}; +`; const ViewInExplorerButton = styled.button((props) => ({ display: 'flex', @@ -197,13 +191,13 @@ const ViewInExplorerButton = styled.button((props) => ({ })); const ButtonText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_400, })); const ButtonHiglightedText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_0, marginLeft: props.theme.spacing(2), marginRight: props.theme.spacing(2), })); @@ -218,13 +212,6 @@ const StyledTooltip = styled(Tooltip)` } `; -const WebGalleryButtonText = styled.div((props) => ({ - ...props.theme.body_m, - fontWeight: 700, - color: props.theme.colors.white['200'], - textAlign: 'center', -})); - const ButtonImage = styled.img((props) => ({ marginRight: props.theme.spacing(3), alignSelf: 'center', @@ -241,10 +228,10 @@ const Button = styled.button((props) => ({ })); const AssetDeatilButtonText = styled.div((props) => ({ - ...props.theme.body_xs, + ...props.theme.typography.body_s, fontWeight: 400, fontSize: 14, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -266,20 +253,20 @@ const OrdinalsTag = styled.div({ }); const CollectibleText = styled.h1((props) => ({ - ...props.theme.body_bold_m, - color: props.theme.colors.white['400'], + ...props.theme.typography.body_bold_m, + color: props.theme.colors.white_400, textAlign: 'center', })); const GalleryCollectibleText = styled.h1((props) => ({ - ...props.theme.body_bold_l, - color: props.theme.colors.white['400'], + ...props.theme.typography.body_bold_l, + color: props.theme.colors.white_400, })); const Text = styled.h1((props) => ({ - ...props.theme.body_bold_m, + ...props.theme.typography.body_bold_m, textTransform: 'uppercase', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontSize: 10, marginLeft: props.theme.spacing(2), })); @@ -298,7 +285,7 @@ const CubeTransparentIcon = styled(CubeTransparent)((props) => ({ marginRight: props.theme.spacing(8), })); const RareSatsBundleTextDescription = styled.div((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, color: props.theme.colors.white_200, })); const BundleLinkContainer = styled.button((props) => ({ @@ -310,12 +297,11 @@ const BundleLinkContainer = styled.button((props) => ({ color: props.theme.colors.white_0, transition: 'background-color 0.2s ease, opacity 0.2s ease', ':hover': { - color: props.theme.colors.action.classicLight, - opacity: 0.6, + color: props.theme.colors.white_200, }, })); const BundleLinkText = styled.div((props) => ({ - ...props.theme.body_medium_m, + ...props.theme.typography.body_medium_m, marginRight: props.theme.spacing(1), })); @@ -330,7 +316,7 @@ const RowButtonContainer = styled.div((props) => ({ justifyContent: 'center', columnGap: props.theme.spacing(11), paddingBottom: props.theme.spacing(16), - marginBottom: props.theme.spacing(16), + marginBottom: props.theme.spacing(4), marginTop: props.theme.spacing(4), width: '100%', borderBottom: `1px solid ${props.theme.colors.elevation3}`, @@ -340,6 +326,7 @@ const DetailSection = styled.div((props) => ({ display: 'flex', flexDirection: !props.isGallery ? 'row' : 'column', justifyContent: 'space-between', + columnGap: props.theme.space.m, width: '100%', })); @@ -637,12 +624,7 @@ function OrdinalDetailScreen() { {isBrc20Ordinal ? t('BRC20_INSCRIPTION') : ordinal?.collection_name || t('INSCRIPTION')} {ordinal?.number} - - <> - - {t('WEB_GALLERY')} - - + diff --git a/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx b/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx index 38fcfa6fc..c44dfb242 100644 --- a/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx +++ b/src/app/screens/ordinalDetail/ordinalAttributeComponent.tsx @@ -20,7 +20,7 @@ const RowContainer = styled.div((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, textAlign: 'center', })); @@ -59,7 +59,7 @@ const ButtonIcon = styled.img({ const Text = styled.h1((props) => ({ ...props.theme.body_bold_m, textTransform: 'uppercase', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontSize: 10, marginLeft: props.theme.spacing(2), })); diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts index ee74d30f3..abd694b05 100644 --- a/src/app/screens/ordinalDetail/useOrdinalDetail.ts +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -100,7 +100,7 @@ export default function useOrdinalDetail() { }; const openInOrdinalsExplorer = () => { - window.open(`${XVERSE_ORDIVIEW_URL}/inscription/${ordinalData?.id}`); + window.open(`${XVERSE_ORDIVIEW_URL(network.type)}/inscription/${ordinalData?.id}`); }; const handleNavigationToRareSatsBundle = () => { @@ -112,7 +112,9 @@ export default function useOrdinalDetail() { }; const onCopyClick = () => { - navigator.clipboard.writeText(`${XVERSE_ORDIVIEW_URL}/inscription/${ordinalData?.id}`); + navigator.clipboard.writeText( + `${XVERSE_ORDIVIEW_URL(network.type)}/inscription/${ordinalData?.id}`, + ); }; const backButtonText = ordinalData?.collection_id diff --git a/src/app/screens/ordinals/brc20Tile.tsx b/src/app/screens/ordinals/brc20Tile.tsx index 8d1d6440b..4e6abc304 100644 --- a/src/app/screens/ordinals/brc20Tile.tsx +++ b/src/app/screens/ordinals/brc20Tile.tsx @@ -33,7 +33,7 @@ const BRC20Container = styled.div({ const OrdinalContentText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontSize: props.inNftSend || props.withoutSizeIncrease ? 15 : 'calc(0.8vw + 2vh)', overflow: 'hidden', textAlign: 'center', @@ -133,7 +133,7 @@ const ButtonIcon = styled.img({ const Text = styled.h1((props) => ({ ...props.theme.body_bold_m, textTransform: 'uppercase', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontSize: 10, marginLeft: props.theme.spacing(4), })); diff --git a/src/app/screens/ordinals/index.tsx b/src/app/screens/ordinals/index.tsx index 7ce326e4b..8153df5c7 100644 --- a/src/app/screens/ordinals/index.tsx +++ b/src/app/screens/ordinals/index.tsx @@ -1,5 +1,5 @@ import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; -import { Inscription } from '@secretkeylabs/xverse-core/types/index'; +import type { Inscription } from '@secretkeylabs/xverse-core'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; diff --git a/src/app/screens/ordinals/ordinalImage.tsx b/src/app/screens/ordinals/ordinalImage.tsx index 71eb65eab..c9091ea08 100644 --- a/src/app/screens/ordinals/ordinalImage.tsx +++ b/src/app/screens/ordinals/ordinalImage.tsx @@ -2,6 +2,7 @@ import PlaceholderImage from '@assets/img/nftDashboard/nft_fallback.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import { BetterBarLoader } from '@components/barLoader'; import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; +import useWalletSelector from '@hooks/useWalletSelector'; import { CondensedInscription, getErc721Metadata, Inscription } from '@secretkeylabs/xverse-core'; import { getBrc20Details } from '@utils/brc20'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; @@ -62,9 +63,9 @@ const OrdinalsTag = styled.div((props) => ({ })); const Text = styled.h1((props) => ({ - ...props.theme.body_bold_m, + ...props.theme.typography.body_bold_m, textTransform: 'uppercase', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, fontSize: 10, marginLeft: props.theme.spacing(4), })); @@ -97,8 +98,8 @@ const OrdinalContentText = styled.p((props) => { fontSize = '15px'; } return { - ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_0, fontSize, overflow: 'hidden', textAlign: 'center', @@ -146,35 +147,37 @@ function OrdinalImage({ const textContent = useTextOrdinalContent(ordinal); const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); const [brc721eImage, setBrc721eImage] = useState(undefined); + const { network } = useWalletSelector(); - const fetchBrc721eMetadata = async () => { - if (!textContent) { - return; - } + useEffect(() => { + const fetchBrc721eMetadata = async () => { + if (!textContent) { + return; + } - try { - const parsedContent = JSON.parse(textContent); - const erc721Metadata = await getErc721Metadata( - parsedContent.contract, - parsedContent.token_id, - ); + try { + const parsedContent = JSON.parse(textContent); + const erc721Metadata = await getErc721Metadata( + network.type, + parsedContent.contract, + parsedContent.token_id, + ); - const url = getFetchableUrl(erc721Metadata, 'ipfs'); + const url = getFetchableUrl(erc721Metadata, 'ipfs'); - if (url) { - const ipfsMetadata = await (await fetch(url)).json(); - setBrc721eImage(getFetchableUrl(ipfsMetadata.image, 'ipfs')); + if (url) { + const ipfsMetadata = await (await fetch(url)).json(); + setBrc721eImage(getFetchableUrl(ipfsMetadata.image, 'ipfs')); + } + } catch (e) { + console.error(e); // eslint-disable-line no-console } - } catch (e) { - console.error(e); - } - }; + }; - useEffect(() => { if (textContent?.includes('brc-721e')) { fetchBrc721eMetadata(); } - }, [textContent]); + }, [textContent, network.type]); let loaderSize = 151; if (inNftDetail && isGalleryOpen) { @@ -187,12 +190,14 @@ function OrdinalImage({ } src={src} + preview={false} /> {isNftDashboard && ( @@ -211,11 +216,14 @@ function OrdinalImage({ ); if (contentType.includes('image/svg')) { - return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL}/thumbnail/${ordinal.id}`); + return renderImage( + t('ORDINAL'), + `${XVERSE_ORDIVIEW_URL(network.type)}/thumbnail/${ordinal.id}`, + ); } if (contentType.includes('image')) { - return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL}/content/${ordinal.id}`); + return renderImage(t('ORDINAL'), `${XVERSE_ORDIVIEW_URL(network.type)}/content/${ordinal.id}`); } if (textContent?.includes('brc-721e')) { @@ -246,7 +254,10 @@ function OrdinalImage({ if (contentType.includes('html')) { return ( - + {isNftDashboard && ( diff --git a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx index f9c3bfdad..57e7bef4c 100644 --- a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx +++ b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx @@ -11,22 +11,22 @@ import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; -import { Circle, ArrowRight, ArrowUp } from '@phosphor-icons/react'; +import { ArrowRight, ArrowUp, Circle } from '@phosphor-icons/react'; import Callout from '@ui-library/callout'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; import { getBtcTxStatusUrl, getTruncatedAddress, isLedgerAccount } from '@utils/helper'; -import { useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useNavigate, useLocation } from 'react-router-dom'; -import styled from 'styled-components'; import { + BundleItem, getBundleItemId, + getBundleItemSubText, getRareSatsColorsByRareSatsType, getRareSatsLabelByType, getRarityLabelByRareSatsType, - getBundleItemSubText, - BundleItem, } from '@utils/rareSats'; +import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; interface DetailSectionProps { @@ -316,7 +316,7 @@ function RareSatsDetailScreen() { if (!isInscription) { return; } - window.open(`${XVERSE_ORDIVIEW_URL}/inscription/${item.inscription.id}`); + window.open(`${XVERSE_ORDIVIEW_URL(network.type)}/inscription/${item.inscription.id}`); }; const { color, backgroundColor } = getRareSatsColorsByRareSatsType(item.rarity_ranking); diff --git a/src/app/screens/receive/index.tsx b/src/app/screens/receive/index.tsx index 4c84ae8a4..4dab5adaf 100644 --- a/src/app/screens/receive/index.tsx +++ b/src/app/screens/receive/index.tsx @@ -35,7 +35,7 @@ const ReceiveScreenText = styled.h1((props) => ({ ...props.theme.body_m, textAlign: 'center', marginTop: props.theme.spacing(3), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const BnsNameText = styled.h1((props) => ({ @@ -69,7 +69,7 @@ const CopyContainer = styled.div((props) => ({ const QRCodeContainer = styled.div((props) => ({ display: 'flex', aspectRatio: 1, - backgroundColor: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.white_0, justifyContent: 'center', alignItems: 'center', borderRadius: 8, @@ -81,7 +81,7 @@ const QRCodeContainer = styled.div((props) => ({ const AddressText = styled.h1((props) => ({ ...props.theme.body_m, textAlign: 'center', - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, wordBreak: 'break-all', })); diff --git a/src/app/screens/restoreFunds/fundsRow.tsx b/src/app/screens/restoreFunds/fundsRow.tsx index a2820b414..166f9ccf2 100644 --- a/src/app/screens/restoreFunds/fundsRow.tsx +++ b/src/app/screens/restoreFunds/fundsRow.tsx @@ -9,13 +9,13 @@ const Icon = styled.img((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_bold_l, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_m, textAlign: 'left', - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const Container = styled.div({ @@ -29,7 +29,7 @@ const RowContainer = styled.button((props) => ({ flexDirection: 'row', alignItems: 'center', borderRadius: 8, - border: `1px solid ${props.theme.colors.background.elevation3}`, + border: `1px solid ${props.theme.colors.elevation3}`, padding: 16, background: 'transparent', width: '100%', diff --git a/src/app/screens/restoreFunds/index.tsx b/src/app/screens/restoreFunds/index.tsx index 3d94447ed..e6ab2c740 100644 --- a/src/app/screens/restoreFunds/index.tsx +++ b/src/app/screens/restoreFunds/index.tsx @@ -1,10 +1,10 @@ -import TopRow from '@components/topRow'; import BitcoinIcon from '@assets/img/dashboard/bitcoin_icon.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/ordinals_icon.svg'; +import BottomTabBar from '@components/tabBar'; +import TopRow from '@components/topRow'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import BottomTabBar from '@components/tabBar'; import FundsRow from './fundsRow'; const RestoreFundTitle = styled.h1((props) => ({ @@ -13,7 +13,7 @@ const RestoreFundTitle = styled.h1((props) => ({ marginTop: 24, marginLeft: 16, marginRight: 16, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const Container = styled.div({ diff --git a/src/app/screens/restoreFunds/restoreBtc/index.tsx b/src/app/screens/restoreFunds/restoreBtc/index.tsx index eb2593ac8..4d442289d 100644 --- a/src/app/screens/restoreFunds/restoreBtc/index.tsx +++ b/src/app/screens/restoreFunds/restoreBtc/index.tsx @@ -1,13 +1,11 @@ +import IconBitcoin from '@assets/img/dashboard/bitcoin_icon.svg'; +import ActionButton from '@components/button'; +import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; +import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; -import IconBitcoin from '@assets/img/dashboard/bitcoin_icon.svg'; -import { - BtcUtxoDataResponse, - getBtcFiatEquivalent, - NetworkType, - satsToBtc, - UTXO, -} from '@secretkeylabs/xverse-core'; +import { getBtcFiatEquivalent, NetworkType, satsToBtc, UTXO } from '@secretkeylabs/xverse-core'; import { getBtcFeesForNonOrdinalBtcSend, SignedBtcTx, @@ -16,25 +14,22 @@ import { } from '@secretkeylabs/xverse-core/transactions/btc'; import { useMutation, useQuery } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import ActionButton from '@components/button'; -import BottomTabBar from '@components/tabBar'; -import { useEffect } from 'react'; -import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; const RestoreFundTitle = styled.h1((props) => ({ ...props.theme.body_l, - marginBottom: 32, - color: props.theme.colors.white[200], + marginBottom: props.theme.spacing(16), + color: props.theme.colors.white_200, })); const BtcCard = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - background: props.theme.colors.background.elevation1, - borderRadius: 8, + background: props.theme.colors.elevation1, + borderRadius: props.theme.radius(1), padding: '16px 12px', })); @@ -47,12 +42,12 @@ const Icon = styled.img((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const BtcContainer = styled.div({ @@ -60,25 +55,26 @@ const BtcContainer = styled.div({ flexDirection: 'column', }); -const Container = styled.div({ +const Container = styled.div((props) => ({ display: 'flex', flex: 1, flexDirection: 'column', - marginLeft: 16, - marginTop: 32, - marginRight: 16, -}); + marginLeft: props.theme.spacing(8), + marginTop: props.theme.spacing(16), + marginRight: props.theme.spacing(8), +})); -const ButtonContainer = styled.div({ - marginLeft: 16, - marginBottom: 32, - marginRight: 16, -}); +const ButtonContainer = styled.div((props) => ({ + marginLeft: props.theme.spacing(8), + marginBottom: props.theme.spacing(16), + marginRight: props.theme.spacing(8), +})); function RestoreBtc() { const { t } = useTranslation('translation', { keyPrefix: 'RESTORE_BTC_SCREEN' }); - const { ordinalsAddress, btcAddress, network, selectedAccount, btcFiatRate, seedPhrase } = + const { ordinalsAddress, btcAddress, network, selectedAccount, btcFiatRate } = useWalletSelector(); + const { getSeed } = useSeedVault(); const navigate = useNavigate(); const { unspentUtxos } = useNonOrdinalUtxos(); let amount = new BigNumber(0); @@ -113,21 +109,22 @@ function RestoreBtc() { recipientAddress, nonOrdinalUtxos, accountIndex, - seedPhrase, - network, + seedPhrase: currentSeedPhrase, + network: currentNetwork, fee, }) => signNonOrdinalBtcSendTransaction( recipientAddress, nonOrdinalUtxos, accountIndex, - seedPhrase, - network, + currentSeedPhrase, + currentNetwork, fee, ), }); - const onClickTransfer = () => { + const onClickTransfer = async () => { + const seedPhrase = await getSeed(); mutateSignNonOrdinalBtcTransaction({ recipientAddress: btcAddress, nonOrdinalUtxos: unspentUtxos, @@ -208,4 +205,4 @@ function RestoreBtc() { ); } -export default RestoreBtc; \ No newline at end of file +export default RestoreBtc; diff --git a/src/app/screens/restoreFunds/restoreOrdinals/index.tsx b/src/app/screens/restoreFunds/restoreOrdinals/index.tsx index f57dc14a5..a0c551e9c 100644 --- a/src/app/screens/restoreFunds/restoreOrdinals/index.tsx +++ b/src/app/screens/restoreFunds/restoreOrdinals/index.tsx @@ -3,6 +3,7 @@ import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; import { @@ -14,13 +15,14 @@ import { useMutation } from '@tanstack/react-query'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; +import { MoonLoader } from 'react-spinners'; import styled from 'styled-components'; import OrdinalRow from './ordinalRow'; const RestoreFundTitle = styled.h1((props) => ({ ...props.theme.body_l, marginBottom: 32, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ErrorContainer = styled.div({ @@ -38,6 +40,13 @@ const Container = styled.div({ marginRight: 16, }); +const LoaderContainer = styled.div({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + flex: 1, +}); + const ErrorText = styled.h1((props) => ({ ...props.theme.body_xs, marginBottom: 20, @@ -53,8 +62,9 @@ const ButtonContainer = styled.div({ function RestoreOrdinals() { const { t } = useTranslation('translation'); - const { network, ordinalsAddress, btcAddress, selectedAccount, seedPhrase, btcFiatRate } = + const { network, ordinalsAddress, btcAddress, selectedAccount, btcFiatRate } = useWalletSelector(); + const { getSeed } = useSeedVault(); const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); const navigate = useNavigate(); const { ordinals } = useOrdinalsByAddress(btcAddress); @@ -69,8 +79,8 @@ function RestoreOrdinals() { isLoading, error: transactionError, mutateAsync, - } = useMutation({ - mutationFn: async (ordinal) => { + } = useMutation({ + mutationFn: async ({ ordinal, seedPhrase }) => { const tx = await signOrdinalSendTransaction( ordinalsAddress, ordinal.utxo, @@ -104,8 +114,8 @@ function RestoreOrdinals() { const onClickTransfer = async (selectedOrdinal: BtcOrdinal, ordinalData: Inscription) => { setTransferringOrdinalId(selectedOrdinal.id); - - const signedTx = await mutateAsync(selectedOrdinal); + const seedPhrase = await getSeed(); + const signedTx = await mutateAsync({ ordinal: selectedOrdinal, seedPhrase }); setSelectedOrdinalDetails(ordinalData); navigate(`/confirm-ordinal-tx/${selectedOrdinal.id}`, { state: { @@ -121,33 +131,42 @@ function RestoreOrdinals() { }); }; + const showContent = + ordinals?.length === 0 ? ( + <> + {t('RESTORE_ORDINAL_SCREEN.NO_FUNDS')} + + + + + ) : ( + <> + {t('RESTORE_ORDINAL_SCREEN.DESCRIPTION')} + {ordinals?.map((ordinal) => ( + + ))} + + {error} + + + ); + return ( <> - {ordinals?.length === 0 ? ( - <> - {t('RESTORE_ORDINAL_SCREEN.NO_FUNDS')} - - - - + {!ordinals ? ( + + + ) : ( - <> - {t('RESTORE_ORDINAL_SCREEN.DESCRIPTION')} - {ordinals?.map((ordinal) => ( - - ))} - - {error} - - + showContent )} diff --git a/src/app/screens/restoreFunds/restoreOrdinals/ordinalRow.tsx b/src/app/screens/restoreFunds/restoreOrdinals/ordinalRow.tsx index fd3e02008..0d8de5c11 100644 --- a/src/app/screens/restoreFunds/restoreOrdinals/ordinalRow.tsx +++ b/src/app/screens/restoreFunds/restoreOrdinals/ordinalRow.tsx @@ -1,6 +1,6 @@ import useInscriptionDetails from '@hooks/queries/ordinals/useInscriptionDetails'; import OrdinalImage from '@screens/ordinals/ordinalImage'; -import { BtcOrdinal, Inscription } from '@secretkeylabs/xverse-core/types'; +import type { BtcOrdinal, Inscription } from '@secretkeylabs/xverse-core'; import { useTranslation } from 'react-i18next'; import { MoonLoader } from 'react-spinners'; import styled from 'styled-components'; @@ -8,7 +8,7 @@ import styled from 'styled-components'; const OrdinalCard = styled.div((props) => ({ display: 'flex', flexDirection: 'row', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 8, padding: '16px 12px', })); @@ -16,25 +16,25 @@ const OrdinalCard = styled.div((props) => ({ const OrdinalImageContainer = styled.div((props) => ({ width: 48, height: 48, - background: props.theme.colors.background.elevation2, + background: props.theme.colors.elevation2, })); const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const TransferButton = styled.button((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, background: 'transparent', width: 86, - border: `1px solid ${props.theme.colors.background.elevation6}`, + border: `1px solid ${props.theme.colors.elevation6}`, borderRadius: 8, padding: '12px 16px', })); diff --git a/src/app/screens/restoreWallet/enterSeedphrase.tsx b/src/app/screens/restoreWallet/enterSeedphrase.tsx index 7fdd765bc..2de226878 100644 --- a/src/app/screens/restoreWallet/enterSeedphrase.tsx +++ b/src/app/screens/restoreWallet/enterSeedphrase.tsx @@ -12,7 +12,7 @@ const Container = styled.div({ const Title = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(21), marginBottom: props.theme.spacing(16), textAlign: 'center', diff --git a/src/app/screens/restoreWallet/index.tsx b/src/app/screens/restoreWallet/index.tsx index 4a719c9bd..d263c3ff6 100644 --- a/src/app/screens/restoreWallet/index.tsx +++ b/src/app/screens/restoreWallet/index.tsx @@ -20,9 +20,9 @@ const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', height: 'auto', - backgroundColor: props.theme.colors.background.elevation0, + backgroundColor: props.theme.colors.elevation0, padding: `${props.theme.spacing(12)}px`, - border: `1px solid ${props.theme.colors.background.elevation2}`, + border: `1px solid ${props.theme.colors.elevation2}`, borderRadius: props.theme.radius(2), })); diff --git a/src/app/screens/sendBrc20/brc20TransferForm.tsx b/src/app/screens/sendBrc20/brc20TransferForm.tsx index c90450122..3e1597b6e 100644 --- a/src/app/screens/sendBrc20/brc20TransferForm.tsx +++ b/src/app/screens/sendBrc20/brc20TransferForm.tsx @@ -39,14 +39,14 @@ const AmountInputContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(4), border: props.error ? '1px solid rgba(211, 60, 60, 0.3)' - : `1px solid ${props.theme.colors.background.elevation3}`, - backgroundColor: props.theme.colors.background.elevation_1, + : `1px solid ${props.theme.colors.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: 8, paddingLeft: props.theme.spacing(5), paddingRight: props.theme.spacing(5), height: 44, ':focus-within': { - border: `1px solid ${props.theme.colors.background.elevation6}`, + border: `1px solid ${props.theme.colors.elevation6}`, }, })); @@ -62,8 +62,8 @@ const InputFieldContainer = styled.div(() => ({ const InputField = styled.input((props) => ({ ...props.theme.body_m, - backgroundColor: props.theme.colors.background.elevation_1, - color: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.elevation_n1, + color: props.theme.colors.white_0, width: '100%', border: 'transparent', })); @@ -74,7 +74,7 @@ const Text = styled.h1((props) => ({ const BalanceText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginRight: props.theme.spacing(2), })); diff --git a/src/app/screens/sendBrc20/brc20TransferInfo.tsx b/src/app/screens/sendBrc20/brc20TransferInfo.tsx index bafd037a8..ee1e01877 100644 --- a/src/app/screens/sendBrc20/brc20TransferInfo.tsx +++ b/src/app/screens/sendBrc20/brc20TransferInfo.tsx @@ -16,7 +16,7 @@ const InfoTitle = styled.h1((props) => ({ const InfoSubtitle = styled.h2((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(6), })); @@ -27,7 +27,7 @@ const TransferStepTitle = styled.h3((props) => ({ const TransferStep = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(2), })); diff --git a/src/app/screens/sendBrc20/index.tsx b/src/app/screens/sendBrc20/index.tsx index 5dc9d1c3a..f46642876 100644 --- a/src/app/screens/sendBrc20/index.tsx +++ b/src/app/screens/sendBrc20/index.tsx @@ -15,6 +15,7 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import useSeedVault from '@hooks/useSeedVault'; import Brc20TransferForm from './brc20TransferForm'; import Brc20TransferInfo from './brc20TransferInfo'; @@ -53,15 +54,9 @@ const SendButtonContainer = styled.div((props) => ({ function SendBrc20Screen() { const { t } = useTranslation('translation'); const navigate = useNavigate(); - const { - btcAddress, - ordinalsAddress, - selectedAccount, - seedPhrase, - network, - btcFiatRate, - brcCoinsList, - } = useWalletSelector(); + const { btcAddress, ordinalsAddress, selectedAccount, network, btcFiatRate, brcCoinsList } = + useWalletSelector(); + const { getSeed } = useSeedVault(); const [amountError, setAmountError] = useState(''); const [amountToSend, setAmountToSend] = useState(''); const [isCreatingOrder, setIsCreatingOrder] = useState(false); @@ -146,6 +141,7 @@ function SendBrc20Screen() { amountSats: orderAmount, }, ]; + const seedPhrase = await getSeed(); const data = await signBtcTransaction( recipients, btcAddress, diff --git a/src/app/screens/sendBrc20OneStep/index.tsx b/src/app/screens/sendBrc20OneStep/index.tsx index d40673fb6..67d4668ea 100644 --- a/src/app/screens/sendBrc20OneStep/index.tsx +++ b/src/app/screens/sendBrc20OneStep/index.tsx @@ -124,6 +124,7 @@ function SendBrc20Screen() { amount: numberAmount, revealAddress: ordinalsAddress, feeRate: feeRate?.regular, + network: network.type, }; const estimatedFees = await brc20TransferEstimateFees(estimateFeesParams); const state: ConfirmBrc20TransferState = { diff --git a/src/app/screens/sendBtc/index.tsx b/src/app/screens/sendBtc/index.tsx index ecd5c101e..ab5c8eb93 100644 --- a/src/app/screens/sendBtc/index.tsx +++ b/src/app/screens/sendBtc/index.tsx @@ -2,20 +2,20 @@ import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useMutation } from '@tanstack/react-query'; -import { useSelector } from 'react-redux'; import { useLocation, useNavigate } from 'react-router-dom'; import SendForm from '@components/sendForm'; import TopRow from '@components/topRow'; import BottomBar from '@components/tabBar'; -import { StoreState } from '@stores/index'; import { signBtcTransaction } from '@secretkeylabs/xverse-core/transactions'; import { btcToSats, getBtcFiatEquivalent, satsToBtc } from '@secretkeylabs/xverse-core/currency'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { BITCOIN_DUST_AMOUNT_SATS } from '@utils/constants'; import { Recipient, SignedBtcTx } from '@secretkeylabs/xverse-core/transactions/btc'; import { ErrorCodes, ResponseError } from '@secretkeylabs/xverse-core'; -import { isInOptions } from '@utils/helper'; +import useWalletSelector from '@hooks/useWalletSelector'; +import useSeedVault from '@hooks/useSeedVault'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import { isInOptions } from '@utils/helper'; function SendBtcScreen() { const location = useLocation(); @@ -31,12 +31,10 @@ function SendBtcScreen() { const [warning, setWarning] = useState(''); const [recipient, setRecipient] = useState(); const [amount, setAmount] = useState(enteredAmountToSend ?? ''); - const { btcAddress, network, btcBalance, selectedAccount, seedPhrase, btcFiatRate } = useSelector( - (state: StoreState) => state.walletState, - ); + const { btcAddress, network, btcBalance, selectedAccount, btcFiatRate } = useWalletSelector(); const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); - const navigate = useNavigate(); + const { getSeed } = useSeedVault(); const { isLoading, data, @@ -47,9 +45,10 @@ function SendBtcScreen() { ResponseError, { recipients: Recipient[]; + seedPhrase: string; } >({ - mutationFn: async ({ recipients }) => + mutationFn: async ({ recipients, seedPhrase }) => signBtcTransaction( recipients, btcAddress, @@ -145,6 +144,7 @@ function SendBtcScreen() { const handleNextClick = async (address: string, amountToSend: string) => { setRecipientAddress(address); setAmount(amountToSend); + const seedPhrase = await getSeed(); const recipients: Recipient[] = [ { address, @@ -153,7 +153,7 @@ function SendBtcScreen() { ]; setRecipient(recipients); if (validateFields(address, amountToSend)) { - mutate({ recipients }); + mutate({ recipients, seedPhrase }); } }; diff --git a/src/app/screens/sendNft/index.tsx b/src/app/screens/sendNft/index.tsx index 9d0fb8c4c..7704b6672 100644 --- a/src/app/screens/sendNft/index.tsx +++ b/src/app/screens/sendNft/index.tsx @@ -1,29 +1,29 @@ -import { useTranslation } from 'react-i18next'; -import { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; +import AccountHeaderComponent from '@components/accountHeader'; +import SendForm from '@components/sendForm'; +import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useNetworkSelector from '@hooks/useNetwork'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import NftImage from '@screens/nftDashboard/nftImage'; +import { validateStxAddress } from '@secretkeylabs/xverse-core'; +import { generateUnsignedTransaction } from '@secretkeylabs/xverse-core/transactions'; import { - StacksTransaction, cvToHex, + StacksTransaction, uintCV, UnsignedStacksTransation, } from '@secretkeylabs/xverse-core/types'; +import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; import { useMutation } from '@tanstack/react-query'; -import { generateUnsignedTransaction } from '@secretkeylabs/xverse-core/transactions'; -import { validateStxAddress } from '@secretkeylabs/xverse-core'; -import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import SendForm from '@components/sendForm'; -import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; -import useWalletSelector from '@hooks/useWalletSelector'; -import TopRow from '@components/topRow'; -import BottomBar from '@components/tabBar'; import { checkNftExists, isLedgerAccount } from '@utils/helper'; -import NftImage from '@screens/nftDashboard/nftImage'; -import useNftDataSelector from '@hooks/stores/useNftDataSelector'; -import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; -import AccountHeaderComponent from '@components/accountHeader'; -import useNetworkSelector from '@hooks/useNetwork'; -import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate, useParams } from 'react-router-dom'; +import styled from 'styled-components'; const ScrollContainer = styled.div` display: flex; @@ -59,7 +59,7 @@ const NftContainer = styled.div((props) => ({ const NftTitleText = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); @@ -89,7 +89,7 @@ const ButtonText = styled.div((props) => ({ ...props.theme.body_xs, fontWeight: 400, fontSize: 14, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index c475a2b10..12a59bea9 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -5,6 +5,7 @@ import TopRow from '@components/topRow'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowLeft } from '@phosphor-icons/react'; import { isOrdinalOwnedByAccount } from '@secretkeylabs/xverse-core'; @@ -143,8 +144,9 @@ function SendOrdinal() { const { selectedOrdinal } = useNftDataSelector(); const btcClient = useBtcClient(); const location = useLocation(); - const { network, ordinalsAddress, btcAddress, selectedAccount, seedPhrase, btcFiatRate } = + const { network, ordinalsAddress, btcAddress, selectedAccount, btcFiatRate } = useWalletSelector(); + const { getSeed } = useSeedVault(); const [ordinalUtxo, setOrdinalUtxo] = useState(undefined); const [recipientAddress, setRecipientAddress] = useState(location.state?.recipientAddress ?? ''); const [recipientError, setRecipientError] = useState(null); @@ -160,6 +162,7 @@ function SendOrdinal() { mutate, } = useMutation({ mutationFn: async (recipient) => { + const seedPhrase = await getSeed(); const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); const ordUtxo = addressUtxos.find( (utxo) => `${utxo.txid}:${utxo.vout}` === selectedOrdinal?.output, diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx index d2988aac4..58084010b 100644 --- a/src/app/screens/sendRareSat/index.tsx +++ b/src/app/screens/sendRareSat/index.tsx @@ -1,5 +1,6 @@ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import AccountHeaderComponent from '@components/accountHeader'; +import BundleAsset from '@components/bundleAsset/bundleAsset'; import SendForm from '@components/sendForm'; import BottomBar from '@components/tabBar'; import TopRow from '@components/topRow'; @@ -7,6 +8,7 @@ import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; +import useSeedVault from '@hooks/useSeedVault'; import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; import { SignedBtcTx, @@ -15,14 +17,13 @@ import { import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { useMutation } from '@tanstack/react-query'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; import { isLedgerAccount } from '@utils/helper'; -import { getBundleSubText, getBundleId } from '@utils/rareSats'; +import { getBundleId, getBundleSubText } from '@utils/rareSats'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; -import { StyledHeading, StyledP } from '@ui-library/common.styled'; import styled from 'styled-components'; -import BundleAsset from '@components/bundleAsset/bundleAsset'; const ScrollContainer = styled.div` display: flex; @@ -98,8 +99,9 @@ function SendOrdinal() { const { selectedSatBundle } = useNftDataSelector(); const btcClient = useBtcClient(); const location = useLocation(); - const { network, ordinalsAddress, btcAddress, selectedAccount, seedPhrase, btcFiatRate } = + const { network, ordinalsAddress, btcAddress, selectedAccount, btcFiatRate } = useWalletSelector(); + const { getSeed } = useSeedVault(); const [ordinalUtxo, setOrdinalUtxo] = useState(undefined); const [error, setError] = useState(''); const [recipientAddress, setRecipientAddress] = useState(''); @@ -120,6 +122,7 @@ function SendOrdinal() { ); setOrdinalUtxo(ordUtxo); if (ordUtxo) { + const seedPhrase = await getSeed(); const signedTx = await signOrdinalSendTransaction( recipient, ordUtxo, @@ -234,8 +237,10 @@ function SendOrdinal() { onPressSend={onPressNext} onAddressInputChange={handleInputChange} warning={warning} + info={t('SEND.INFO.ADDRESS_SUPPORTS_RARE_SATS')} hideMemo hideTokenImage + hideDefaultWarning > diff --git a/src/app/screens/sendStx/index.tsx b/src/app/screens/sendStx/index.tsx index bd647dfa9..b741d365a 100644 --- a/src/app/screens/sendStx/index.tsx +++ b/src/app/screens/sendStx/index.tsx @@ -1,19 +1,22 @@ +import SendForm from '@components/sendForm'; +import BottomBar from '@components/tabBar'; +import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; +import useNetworkSelector from '@hooks/useNetwork'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { + generateUnsignedStxTokenTransferTransaction, + microstacksToStx, + StacksTransaction, + stxToMicrostacks, + validateStxAddress, +} from '@secretkeylabs/xverse-core'; import { useMutation } from '@tanstack/react-query'; +import { replaceCommaByDot } from '@utils/helper'; import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; -import { generateUnsignedStxTokenTransferTransaction } from '@secretkeylabs/xverse-core/transactions'; -import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; -import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; -import { validateStxAddress } from '@secretkeylabs/xverse-core/wallet'; -import SendForm from '@components/sendForm'; -import TopRow from '@components/topRow'; -import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; -import { replaceCommaByDot } from '@utils/helper'; -import BottomBar from '@components/tabBar'; -import useNetworkSelector from '@hooks/useNetwork'; -import useWalletSelector from '@hooks/useWalletSelector'; +import TopRow from '../../components/topRow'; function SendStxScreen() { const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); diff --git a/src/app/screens/settings/backupWallet/index.tsx b/src/app/screens/settings/backupWallet/index.tsx index b4df80b54..d95c79fb3 100644 --- a/src/app/screens/settings/backupWallet/index.tsx +++ b/src/app/screens/settings/backupWallet/index.tsx @@ -1,13 +1,12 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import PasswordInput from '@components/passwordInput'; import TopRow from '@components/topRow'; import BottomBar from '@components/tabBar'; -import useWalletReducer from '@hooks/useWalletReducer'; import SeedCheck from '@screens/backupWalletSteps/seedCheck'; -import useWalletSelector from '@hooks/useWalletSelector'; import styled from 'styled-components'; +import useSeedVault from '@hooks/useSeedVault'; const Container = styled.div` display: flex; @@ -42,13 +41,24 @@ const SeedphraseContainer = styled.div((props) => ({ function BackupWalletScreen() { const { t } = useTranslation('translation'); - const { seedPhrase } = useWalletSelector(); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const [showSeed, setShowSeed] = useState(false); + const [seed, setSeed] = useState(''); const navigate = useNavigate(); - const { unlockWallet } = useWalletReducer(); + const { getSeed, unlockVault } = useSeedVault(); + + useEffect(() => { + (async () => { + const seedPhrase = await getSeed(); + setSeed(seedPhrase); + })(); + + return () => { + setSeed(''); + }; + }, []); const goToSettingScreen = () => { navigate('/settings'); @@ -57,7 +67,7 @@ function BackupWalletScreen() { const handlePasswordNextClick = async () => { try { setLoading(true); - await unlockWallet(password); + await unlockVault(password); setPassword(''); setError(''); setShowSeed(true); @@ -89,7 +99,7 @@ function BackupWalletScreen() { )} {showSeed && ( - + )} diff --git a/src/app/screens/settings/changeNetwork/index.tsx b/src/app/screens/settings/changeNetwork/index.tsx index f23208ff5..085699432 100644 --- a/src/app/screens/settings/changeNetwork/index.tsx +++ b/src/app/screens/settings/changeNetwork/index.tsx @@ -1,16 +1,16 @@ -import styled from 'styled-components'; +import Cross from '@assets/img/settings/x.svg'; +import ActionButton from '@components/button'; import BottomBar from '@components/tabBar'; import TopRow from '@components/topRow'; -import { useTranslation } from 'react-i18next'; +import useWalletReducer from '@hooks/useWalletReducer'; import useWalletSelector from '@hooks/useWalletSelector'; -import { useNavigate } from 'react-router-dom'; +import { SettingsNetwork, StacksMainnet, StacksTestnet } from '@secretkeylabs/xverse-core'; import { initialNetworksList } from '@utils/constants'; -import Cross from '@assets/img/settings/x.svg'; -import { useState } from 'react'; -import ActionButton from '@components/button'; import { isValidBtcApi, isValidStacksApi } from '@utils/helper'; -import { SettingsNetwork, StacksMainnet, StacksTestnet } from '@secretkeylabs/xverse-core/types'; -import useWalletReducer from '@hooks/useWalletReducer'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import NetworkRow from './networkRow'; const Container = styled.div` @@ -49,8 +49,8 @@ const InputContainer = styled.div((props) => ({ display: 'flex', alignItems: 'center', width: '100%', - border: `1px solid ${props.theme.colors.background.elevation3}`, - backgroundColor: props.theme.colors.background.elevation_1, + border: `1px solid ${props.theme.colors.elevation3}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: props.theme.radius(1), paddingLeft: props.theme.spacing(4), paddingRight: props.theme.spacing(4), @@ -75,8 +75,8 @@ const Input = styled.input((props) => ({ height: 44, display: 'flex', flex: 1, - backgroundColor: props.theme.colors.background.elevation_1, - color: props.theme.colors.white['0'], + backgroundColor: props.theme.colors.elevation_n1, + color: props.theme.colors.white_0, border: 'none', })); diff --git a/src/app/screens/settings/changeNetwork/networkRow.tsx b/src/app/screens/settings/changeNetwork/networkRow.tsx index 606807ddc..2169c1354 100644 --- a/src/app/screens/settings/changeNetwork/networkRow.tsx +++ b/src/app/screens/settings/changeNetwork/networkRow.tsx @@ -1,6 +1,6 @@ -import styled, { useTheme } from 'styled-components'; import TickIcon from '@assets/img/settings/tick.svg'; -import { SettingsNetwork } from '@secretkeylabs/xverse-core/types'; +import type { SettingsNetwork } from '@secretkeylabs/xverse-core'; +import styled, { useTheme } from 'styled-components'; interface TitleProps { color: string; @@ -41,9 +41,7 @@ function NetworkRow({ network, isSelected, onNetworkSelected, showDivider }: Pro return ( ); diff --git a/src/app/screens/settings/changePassword/index.tsx b/src/app/screens/settings/changePassword/index.tsx index 5dfaa13c7..436f71962 100644 --- a/src/app/screens/settings/changePassword/index.tsx +++ b/src/app/screens/settings/changePassword/index.tsx @@ -1,17 +1,13 @@ +import Check from '@assets/img/settings/check_circle.svg'; +import PasswordInput from '@components/passwordInput'; +import BottomBar from '@components/tabBar'; +import TopRow from '@components/topRow'; +import useSeedVault from '@hooks/useSeedVault'; import { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; import toast from 'react-hot-toast'; -import styled from 'styled-components'; -import TopRow from '@components/topRow'; -import BottomBar from '@components/tabBar'; import { useTranslation } from 'react-i18next'; -import { encryptSeedPhrase } from '@utils/encryptionUtils'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { storeEncryptedSeedAction } from '@stores/wallet/actions/actionCreators'; -import { useDispatch } from 'react-redux'; -import Check from '@assets/img/settings/check_circle.svg'; -import PasswordInput from '@components/passwordInput'; -import useWalletReducer from '@hooks/useWalletReducer'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const PasswordContainer = styled.div((props) => ({ display: 'flex', @@ -36,7 +32,7 @@ const ToastContainer = styled.div((props) => ({ const ToastMessage = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, marginLeft: props.theme.spacing(7), })); @@ -47,16 +43,14 @@ const ToastDismissButton = styled.button((props) => ({ function ChangePasswordScreen() { const { t } = useTranslation('translation'); - + const { unlockVault, changePassword } = useSeedVault(); const [password, setPassword] = useState(''); + const [oldPassword, setOldPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const [currentStepIndex, setCurrentStepIndex] = useState(0); - const { seedPhrase } = useWalletSelector(); - const { unlockWallet } = useWalletReducer(); const navigate = useNavigate(); - const dispatch = useDispatch(); const handleBackButtonClick = () => { navigate('/settings'); @@ -69,7 +63,7 @@ function ChangePasswordScreen() { const handleConfirmCurrentPasswordNextClick = async () => { try { setLoading(true); - await unlockWallet(password); + await unlockVault(oldPassword); setPassword(''); setError(''); setCurrentStepIndex(1); @@ -95,8 +89,7 @@ function ChangePasswordScreen() { const handleConfirmNewPasswordNextClick = async () => { if (confirmPassword === password) { setError(''); - const encryptedSeed = await encryptSeedPhrase(seedPhrase, password); - dispatch(storeEncryptedSeedAction(encryptedSeed)); + await changePassword(oldPassword, confirmPassword); toast.custom(ToastContent); navigate('/settings'); } else { @@ -116,8 +109,8 @@ function ChangePasswordScreen() { flag - + {currency.name} {isSelected && tick} diff --git a/src/app/screens/settings/index.tsx b/src/app/screens/settings/index.tsx index c9f375768..791895106 100644 --- a/src/app/screens/settings/index.tsx +++ b/src/app/screens/settings/index.tsx @@ -1,22 +1,23 @@ -import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; -import useWalletSelector from '@hooks/useWalletSelector'; -import XverseLogo from '@assets/img/settings/logo.svg'; -import ArrowIcon from '@assets/img/settings/arrow.svg'; import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; -import BottomBar from '@components/tabBar'; -import { PRIVACY_POLICY_LINK, TERMS_LINK, SUPPORT_LINK } from '@utils/constants'; -import { useNavigate } from 'react-router-dom'; -import { useState } from 'react'; +import ArrowIcon from '@assets/img/settings/arrow.svg'; +import XverseLogo from '@assets/img/settings/logo.svg'; import PasswordInput from '@components/passwordInput'; +import BottomBar from '@components/tabBar'; +import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletReducer from '@hooks/useWalletReducer'; -import { useDispatch } from 'react-redux'; +import useWalletSelector from '@hooks/useWalletSelector'; import { ChangeActivateOrdinalsAction, ChangeActivateRareSatsAction, } from '@stores/wallet/actions/actionCreators'; -import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; +import { PRIVACY_POLICY_LINK, SUPPORT_LINK, TERMS_LINK } from '@utils/constants'; import { isLedgerAccount } from '@utils/helper'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch } from 'react-redux'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import ResetWalletPrompt from '../../components/resetWallet'; import SettingComponent from './settingComponent'; @@ -50,7 +51,7 @@ const ResetWalletContainer = styled.div((props) => ({ const LogoContainer = styled.div((props) => ({ padding: props.theme.spacing(11), - borderBottom: `1px solid ${props.theme.colors.background.elevation3}`, + borderBottom: `1px solid ${props.theme.colors.elevation3}`, })); function Setting() { @@ -69,8 +70,8 @@ function Setting() { } = useWalletSelector(); const navigate = useNavigate(); const dispatch = useDispatch(); - const { unlockWallet, resetWallet } = useWalletReducer(); - const { unspentUtxos } = useNonOrdinalUtxos(); + const { resetWallet } = useWalletReducer(); + const { unlockVault } = useSeedVault(); const openTermsOfService = () => { window.open(TERMS_LINK); @@ -131,11 +132,6 @@ function Setting() { setShowResetWalletDisplay(false); }; - const handleResetWallet = () => { - resetWallet(); - navigate('/'); - }; - const openLockCountdownScreen = () => { navigate('/lockCountdown'); }; @@ -153,10 +149,10 @@ function Setting() { const handlePasswordNextClick = async () => { try { setLoading(true); - await unlockWallet(password); + await unlockVault(password); setPassword(''); setError(''); - handleResetWallet(); + await resetWallet(); } catch (e) { setError(t('INCORRECT_PASSWORD_ERROR')); } finally { diff --git a/src/app/screens/settings/lockCountdown/index.tsx b/src/app/screens/settings/lockCountdown/index.tsx index 5f24b0749..cabb8a8e9 100644 --- a/src/app/screens/settings/lockCountdown/index.tsx +++ b/src/app/screens/settings/lockCountdown/index.tsx @@ -1,15 +1,15 @@ -import { useState } from 'react'; -import styled from 'styled-components'; -import { useNavigate } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; +import Timer from '@assets/img/settings/Timer.svg'; +import TimerFull from '@assets/img/settings/TimerFull.svg'; +import TimerHalf from '@assets/img/settings/TimerHalf.svg'; +import ActionButton from '@components/button'; +import TopRow from '@components/topRow'; import useWalletSelector from '@hooks/useWalletSelector'; import useWalletSession from '@hooks/useWalletSession'; import { WalletSessionPeriods } from '@stores/wallet/actions/types'; -import TopRow from '@components/topRow'; -import ActionButton from '@components/button'; -import TimerHalf from '@assets/img/settings/TimerHalf.svg'; -import Timer from '@assets/img/settings/Timer.svg'; -import TimerFull from '@assets/img/settings/TimerFull.svg'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -42,8 +42,8 @@ interface TimeSelectionBoxProps { const TimeSelectionBox = styled.button((props) => ({ ...props.theme.body_medium_m, backgroundColor: 'transparent', - border: `1px solid ${props.selected ? props.theme.colors.white[0] : props.theme.colors.grey}`, - color: props.theme.colors.white[0], + border: `1px solid ${props.selected ? props.theme.colors.white_0 : props.theme.colors.grey}`, + color: props.theme.colors.white_0, borderRadius: props.theme.radius(1), height: 44, display: 'flex', diff --git a/src/app/screens/settings/settingComponent/index.tsx b/src/app/screens/settings/settingComponent/index.tsx index db2df267c..db5d8ce40 100644 --- a/src/app/screens/settings/settingComponent/index.tsx +++ b/src/app/screens/settings/settingComponent/index.tsx @@ -1,5 +1,5 @@ -import styled, { useTheme } from 'styled-components'; import Switch from 'react-switch'; +import styled, { useTheme } from 'styled-components'; interface ButtonProps { border: string; @@ -52,7 +52,7 @@ const ComponentText = styled.h1((props) => ({ const ComponentDescriptionText = styled.h1((props) => ({ ...props.theme.body_bold_m, paddingTop: props.theme.spacing(8), - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const DescriptionText = styled.p((props) => ({ @@ -75,7 +75,6 @@ const DisabledOverlay = styled.div((props) => ({ left: 0, bottom: 0, right: 0, - zIndex: 10, backgroundColor: props.theme.colors.elevation0, opacity: 0.5, })); diff --git a/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx b/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx index f2b5a1e80..aa2fc09be 100644 --- a/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx +++ b/src/app/screens/signPsbtRequest/bundleItemsComponent.tsx @@ -12,7 +12,7 @@ import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '16px 16px', justifyContent: 'center', @@ -21,7 +21,7 @@ const Container = styled.div((props) => ({ const RecipientTitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: 10, })); @@ -47,18 +47,18 @@ const Icon = styled.img((props) => ({ const TitleText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, })); const ValueText = styled.h1((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); const SubValueText = styled.h1((props) => ({ ...props.theme.body_m, fontSize: 12, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, })); const InscriptionText = styled.h1((props) => ({ diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index 6efb0d39e..6dd3cf894 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -78,7 +78,7 @@ const TransparentButtonContainer = styled.div((props) => ({ const ReviewTransactionText = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(12), textAlign: 'left', })); diff --git a/src/app/screens/signatureRequest/clarityMessageView.tsx b/src/app/screens/signatureRequest/clarityMessageView.tsx index 5910d7176..b31df8c01 100644 --- a/src/app/screens/signatureRequest/clarityMessageView.tsx +++ b/src/app/screens/signatureRequest/clarityMessageView.tsx @@ -15,13 +15,13 @@ const ContentContainer = styled.div({ const ClarityValueText = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, wordWrap: 'break-word', })); const ClarityValueKey = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginRight: props.theme.spacing(4), wordWrap: 'break-word', })); diff --git a/src/app/screens/signatureRequest/collapsableContainer.tsx b/src/app/screens/signatureRequest/collapsableContainer.tsx index 1c3823626..2b7bb542c 100644 --- a/src/app/screens/signatureRequest/collapsableContainer.tsx +++ b/src/app/screens/signatureRequest/collapsableContainer.tsx @@ -1,7 +1,7 @@ -import styled from 'styled-components'; -import { animated, config, useSpring } from '@react-spring/web'; import DropDownIcon from '@assets/img/transactions/dropDownIcon.svg'; +import { animated, config, useSpring } from '@react-spring/web'; import { useEffect, useState } from 'react'; +import styled from 'styled-components'; interface Props { title: string; @@ -13,7 +13,7 @@ interface Props { const ContentContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', justifyContent: 'center', @@ -30,7 +30,7 @@ const RowContainer = styled.div({ const RequestMessageTitle = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(2), opacity: 0.7, flex: 1, @@ -57,7 +57,7 @@ const Text = styled.p((props) => ({ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(4), })); diff --git a/src/app/screens/signatureRequest/index.tsx b/src/app/screens/signatureRequest/index.tsx index 0a7628fdf..bd747c78e 100644 --- a/src/app/screens/signatureRequest/index.tsx +++ b/src/app/screens/signatureRequest/index.tsx @@ -16,22 +16,22 @@ import useSignatureRequest, { useSignMessage, } from '@hooks/useSignatureRequest'; import useWalletReducer from '@hooks/useWalletReducer'; -import { getNetworkType, isHardwareAccount, getTruncatedAddress } from '@utils/helper'; +import useWalletSelector from '@hooks/useWalletSelector'; +import Transport from '@ledgerhq/hw-transport-webusb'; import { hashMessage, signStxMessage } from '@secretkeylabs/xverse-core'; -import { useNavigate } from 'react-router-dom'; import { bip0322Hash } from '@secretkeylabs/xverse-core/connect/bip322Signature'; -import Transport from '@ledgerhq/hw-transport-webusb'; -import { handleBip322LedgerMessageSigning, signatureVrsToRsv } from '@utils/ledger'; -import useWalletSelector from '@hooks/useWalletSelector'; import { SignaturePayload, StructuredDataSignaturePayload } from '@stacks/connect'; import { bytesToHex } from '@stacks/transactions'; +import { getNetworkType, getTruncatedAddress, isHardwareAccount } from '@utils/helper'; +import { handleBip322LedgerMessageSigning, signatureVrsToRsv } from '@utils/ledger'; import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import CollapsableContainer from './collapsableContainer'; +import SignatureRequestMessage from './signatureRequestMessage'; import SignatureRequestStructuredData from './signatureRequestStructuredData'; import { finalizeMessageSignature } from './utils'; -import SignatureRequestMessage from './signatureRequestMessage'; -import CollapsableContainer from './collapsableContainer'; const OuterContainer = styled.div({ display: 'flex', @@ -39,32 +39,29 @@ const OuterContainer = styled.div({ height: '100%', }); -const InnerContainer = styled.div({ +const InnerContainer = styled.div((props) => ({ flex: 1, - overflowY: 'auto', - '&::-webkit-scrollbar': { - display: 'none', - }, -}); + ...props.theme.scrollbar, +})); -const MainContainer = styled.div((props) => ({ +export const MainContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - paddingLeft: props.theme.spacing(8), - paddingRight: props.theme.spacing(8), + paddingLeft: props.theme.spacing(4), + paddingRight: props.theme.spacing(4), })); const RequestType = styled.h1((props) => ({ ...props.theme.headline_s, marginTop: props.theme.spacing(11), - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textAlign: 'left', marginBottom: props.theme.spacing(4), })); const RequestSource = styled.h2((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, textAlign: 'left', marginBottom: props.theme.spacing(12), })); @@ -74,14 +71,14 @@ const MessageHash = styled.p((props) => ({ textAlign: 'left', lineHeight: 1.6, wordWrap: 'break-word', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(4), })); const SigningAddressContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'column', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, padding: '12px 16px', marginBottom: props.theme.spacing(6), @@ -91,7 +88,7 @@ const SigningAddressContainer = styled.div((props) => ({ const SigningAddressTitle = styled.p((props) => ({ ...props.theme.body_medium_m, wordWrap: 'break-word', - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginBottom: props.theme.spacing(4), })); @@ -105,7 +102,7 @@ const SigningAddressType = styled.p((props) => ({ ...props.theme.body_medium_m, textAlign: 'left', wordWrap: 'break-word', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(4), })); @@ -113,13 +110,13 @@ const SigningAddressValue = styled.p((props) => ({ ...props.theme.body_medium_m, textAlign: 'left', wordWrap: 'break-word', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(4), })); const ActionDisclaimer = styled.p((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(8), })); @@ -146,7 +143,7 @@ function SignatureRequest(): JSX.Element { const [isTxApproved, setIsTxApproved] = useState(false); const [isTxRejected, setIsTxRejected] = useState(false); const [isTxInvalid, setIsTxInvalid] = useState(false); - const { selectedAccount, accountsList, ledgerAccountsList, network } = useWalletSelector(); + const { selectedAccount, accountsList, network } = useWalletSelector(); const [addressType, setAddressType] = useState(''); const { switchAccount } = useWalletReducer(); const { messageType, request, payload, tabId, domain, isSignMessageBip322 } = diff --git a/src/app/screens/signatureRequest/signatureRequestMessage.tsx b/src/app/screens/signatureRequest/signatureRequestMessage.tsx index 5ea8c3573..4a53b0d08 100644 --- a/src/app/screens/signatureRequest/signatureRequestMessage.tsx +++ b/src/app/screens/signatureRequest/signatureRequestMessage.tsx @@ -1,6 +1,6 @@ import { SignaturePayload } from '@stacks/connect'; -import styled from 'styled-components'; import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; import CollapsableContainer from './collapsableContainer'; interface SignatureRequestMessageProps { @@ -11,7 +11,7 @@ const RequestMessage = styled.p((props) => ({ ...props.theme.body_medium_m, textAlign: 'left', wordWrap: 'break-word', - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, })); export default function SignatureRequestMessage(props: SignatureRequestMessageProps) { diff --git a/src/app/screens/signatureRequest/signatureRequestStructuredData.tsx b/src/app/screens/signatureRequest/signatureRequestStructuredData.tsx index e3dce075b..6004f2db8 100644 --- a/src/app/screens/signatureRequest/signatureRequestStructuredData.tsx +++ b/src/app/screens/signatureRequest/signatureRequestStructuredData.tsx @@ -1,7 +1,6 @@ import { StructuredDataSignaturePayload } from '@stacks/connect'; import { deserializeCV } from '@stacks/transactions/dist/esm/clarity'; import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; import ClarityMessageView from './clarityMessageView'; import CollapsableContainer from './collapsableContainer'; @@ -9,19 +8,6 @@ interface SignatureRequestStructuredDataProps { payload: StructuredDataSignaturePayload; } -const ContentContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - flex: 1, -}); - -const RequestMessageTitle = styled.p((props) => ({ - ...props.theme.headline_category_s, - color: props.theme.colors.white[200], - marginBottom: props.theme.spacing(2), - opacity: 0.7, -})); - export default function SignatureRequestStructuredData(props: SignatureRequestStructuredDataProps) { const { t } = useTranslation('translation', { keyPrefix: 'SIGNATURE_REQUEST' }); const { payload } = props; diff --git a/src/app/screens/stacking/index.tsx b/src/app/screens/stacking/index.tsx index b2145adb7..1aec0a572 100644 --- a/src/app/screens/stacking/index.tsx +++ b/src/app/screens/stacking/index.tsx @@ -1,11 +1,11 @@ -import { MoonLoader } from 'react-spinners'; -import { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import useStackingData from '@hooks/queries/useStackingData'; -import BottomBar from '@components/tabBar'; import AccountHeaderComponent from '@components/accountHeader'; +import BottomBar from '@components/tabBar'; +import useStackingData from '@hooks/queries/useStackingData'; import useWalletSelector from '@hooks/useWalletSelector'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { MoonLoader } from 'react-spinners'; +import styled from 'styled-components'; import StackingProgress from './stackingProgress'; import StartStacking from './startStacking'; @@ -19,7 +19,7 @@ const LoaderContainer = styled.div((props) => ({ const Text = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, marginTop: 'auto', marginBottom: 'auto', textAlign: 'center', diff --git a/src/app/screens/stacking/stackingProgress/index.tsx b/src/app/screens/stacking/stackingProgress/index.tsx index 73dc8ca8c..83bd173ce 100644 --- a/src/app/screens/stacking/stackingProgress/index.tsx +++ b/src/app/screens/stacking/stackingProgress/index.tsx @@ -19,7 +19,7 @@ const StackingDescriptionText = styled.h1((props) => ({ ...props.theme.body_m, marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(18), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); function StackingProgress() { const { t } = useTranslation('translation', { keyPrefix: 'STACKING_SCREEN' }); diff --git a/src/app/screens/stacking/stackingProgress/stackingStatusTile.tsx b/src/app/screens/stacking/stackingProgress/stackingStatusTile.tsx index c8d558564..c6392af6e 100644 --- a/src/app/screens/stacking/stackingProgress/stackingStatusTile.tsx +++ b/src/app/screens/stacking/stackingProgress/stackingStatusTile.tsx @@ -1,17 +1,17 @@ -import styled from 'styled-components'; import TokenTicker from '@assets/img/stacking/token_ticker.svg'; -import { useTranslation } from 'react-i18next'; import useStackingData from '@hooks/queries/useStackingData'; import { StackingState } from '@secretkeylabs/xverse-core/stacking'; -import { useEffect, useState } from 'react'; import { XVERSE_WEB_POOL_URL } from '@utils/constants'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Container = styled.button((props) => ({ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: props.theme.radius(2), padding: props.theme.spacing(9), })); @@ -52,18 +52,18 @@ const ColumnContainer = styled.div((props) => ({ const BoldText = styled.h1((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const SubText = styled.h1((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const StatusText = styled.h1((props) => ({ ...props.theme.body_xs, fontWeight: 500, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); function StackingStatusTile() { diff --git a/src/app/screens/stacking/startStacking/index.tsx b/src/app/screens/stacking/startStacking/index.tsx index 9308403e0..bd577a134 100644 --- a/src/app/screens/stacking/startStacking/index.tsx +++ b/src/app/screens/stacking/startStacking/index.tsx @@ -1,13 +1,13 @@ -import styled, { useTheme } from 'styled-components'; -import { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { microstacksToStx } from '@secretkeylabs/xverse-core'; -import { Pool } from '@secretkeylabs/xverse-core/types'; -import BigNumber from 'bignumber.js'; import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; import ActionButton from '@components/button'; import useStackingData from '@hooks/queries/useStackingData'; +import type { Pool } from '@secretkeylabs/xverse-core'; +import { microstacksToStx } from '@secretkeylabs/xverse-core'; import { XVERSE_WEB_POOL_URL } from '@utils/constants'; +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled, { useTheme } from 'styled-components'; import StackingInfoTile from './stackInfoTile'; const OuterContainer = styled.div({ @@ -20,7 +20,7 @@ const Container = styled.div((props) => ({ marginLeft: props.theme.spacing(8), marginRight: props.theme.spacing(8), marginBottom: props.theme.spacing(12), - borderBottom: `1px solid ${props.theme.colors.background.elevation3}`, + borderBottom: `1px solid ${props.theme.colors.elevation3}`, })); const StackingInfoContainer = styled.div((props) => ({ @@ -51,7 +51,7 @@ const StackingDescriptionText = styled.h1((props) => ({ ...props.theme.body_m, marginTop: props.theme.spacing(4), marginBottom: props.theme.spacing(12), - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); function StartStacking() { @@ -72,16 +72,10 @@ function StartStacking() { } }, [stackingData]); - function getMinimum() { + const getMinimum = () => { const min = poolAvailable ? pool!.minimum : 0; return microstacksToStx(new BigNumber(min)).toString(); - } - - function getCycles() { - const minCycles = poolAvailable ? Math.min(...pool!.available_cycle_durations) : 0; - const maxCycles = poolAvailable ? Math.max(...pool!.available_cycle_durations) : 0; - return `${minCycles}-${maxCycles}`; - } + }; const handleOnClick = () => { window.open(XVERSE_WEB_POOL_URL); diff --git a/src/app/screens/stacking/startStacking/stackInfoTile.tsx b/src/app/screens/stacking/startStacking/stackInfoTile.tsx index f9c22bd16..8f0d8322f 100644 --- a/src/app/screens/stacking/startStacking/stackInfoTile.tsx +++ b/src/app/screens/stacking/startStacking/stackInfoTile.tsx @@ -1,12 +1,12 @@ -import styled from 'styled-components'; import BarLoader from '@components/barLoader'; import { LoaderSize } from '@utils/constants'; +import styled from 'styled-components'; const TitleText = styled.h1((props) => ({ ...props.theme.headline_category_s, textTransform: 'uppercase', letterSpacing: '0.02em', - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const Container = styled.div((props) => ({ @@ -18,7 +18,7 @@ const Container = styled.div((props) => ({ const ValueText = styled.h1((props) => ({ ...props.theme.body_bold_l, marginTop: props.theme.spacing(2), - color: props.color ?? props.theme.colors.white['0'], + color: props.color ?? props.theme.colors.white_0, })); const BarLoaderContainer = styled.div((props) => ({ diff --git a/src/app/screens/swap/slippageModal/index.tsx b/src/app/screens/swap/slippageModal/index.tsx index 77113a2dc..aba99f8a1 100644 --- a/src/app/screens/swap/slippageModal/index.tsx +++ b/src/app/screens/swap/slippageModal/index.tsx @@ -1,7 +1,7 @@ +import ActionButton from '@components/button'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { useState } from 'react'; -import ActionButton from '@components/button'; const Container = styled.div` display: flex; @@ -26,17 +26,17 @@ const ResetButton = styled.button((props) => ({ const Title = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const Input = styled.input<{ error: boolean }>((props) => ({ ...props.theme.body_medium_m, height: 48, - backgroundColor: props.theme.colors.background.elevation1, + backgroundColor: props.theme.colors.elevation1, borderStyle: 'solid', borderWidth: 1, borderRadius: 8, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, padding: '14px 16px', outline: 'none', borderColor: props.error ? props.theme.colors.feedback.error_700 : 'transparent', @@ -44,7 +44,7 @@ const Input = styled.input<{ error: boolean }>((props) => ({ border: '1px solid', 'border-color': props.error ? props.theme.colors.feedback.error_700 - : props.theme.colors.background.elevation6, + : props.theme.colors.elevation6, }, })); @@ -61,7 +61,7 @@ const InputRow = styled.div((props) => ({ const Description = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const DEFAULT_SLIPPAGE = '4%'; diff --git a/src/app/screens/swap/swapConfirmation/advanceSettings/index.tsx b/src/app/screens/swap/swapConfirmation/advanceSettings/index.tsx index fdf41f4ad..c82dc940e 100644 --- a/src/app/screens/swap/swapConfirmation/advanceSettings/index.tsx +++ b/src/app/screens/swap/swapConfirmation/advanceSettings/index.tsx @@ -1,12 +1,11 @@ -import { useCallback, useState } from 'react'; -import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; +import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; import TransactionSettingAlert from '@components/transactionSetting'; -import BigNumber from 'bignumber.js'; -import { setFee, setNonce } from '@secretkeylabs/xverse-core'; import { SwapConfirmationOutput } from '@screens/swap/swapConfirmation/useConfirmSwap'; -import styled from 'styled-components'; -import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; +import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; +import BigNumber from 'bignumber.js'; +import { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Button = styled.button((props) => ({ display: 'flex', @@ -20,7 +19,7 @@ const Button = styled.button((props) => ({ const ButtonText = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', })); diff --git a/src/app/screens/swap/swapConfirmation/feesBlock/index.tsx b/src/app/screens/swap/swapConfirmation/feesBlock/index.tsx index a9d7cf882..a33f25b57 100644 --- a/src/app/screens/swap/swapConfirmation/feesBlock/index.tsx +++ b/src/app/screens/swap/swapConfirmation/feesBlock/index.tsx @@ -1,15 +1,15 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; +import useWalletSelector from '@hooks/useWalletSelector'; import { Container, TitleText } from '@screens/swap/swapConfirmation/stxInfoBlock'; import { EstimateUSDText } from '@screens/swap/swapTokenBlock'; -import useWalletSelector from '@hooks/useWalletSelector'; +import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; -const RowContainer = styled.div((props) => ({ +const RowContainer = styled.div({ display: 'flex', alignItems: 'center', justifyContent: 'space-between', -})); +}); const FeeText = styled.p((props) => ({ ...props.theme.body_m, diff --git a/src/app/screens/swap/swapConfirmation/functionBlock/index.tsx b/src/app/screens/swap/swapConfirmation/functionBlock/index.tsx index 0114cf3d5..8371d8405 100644 --- a/src/app/screens/swap/swapConfirmation/functionBlock/index.tsx +++ b/src/app/screens/swap/swapConfirmation/functionBlock/index.tsx @@ -1,11 +1,11 @@ +import { Container, TitleContainer, TitleText } from '@screens/swap/swapConfirmation/stxInfoBlock'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { Container, TitleContainer, TitleText } from '@screens/swap/swapConfirmation/stxInfoBlock'; const FunctionName = styled.div((props) => ({ ...props.theme.body_medium_m, marginLeft: 10, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textAlign: 'right', })); diff --git a/src/app/screens/swap/swapConfirmation/index.tsx b/src/app/screens/swap/swapConfirmation/index.tsx index 03ba722f4..7878ef3c5 100644 --- a/src/app/screens/swap/swapConfirmation/index.tsx +++ b/src/app/screens/swap/swapConfirmation/index.tsx @@ -1,25 +1,25 @@ -import BottomBar from '@components/tabBar'; +import SponsoredTransactionIcon from '@assets/img/transactions/CircleWavyCheck.svg'; import AccountHeaderComponent from '@components/accountHeader'; -import { Container } from '@screens/home'; -import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; -import FunctionBlock from '@screens/swap/swapConfirmation/functionBlock'; import ActionButton from '@components/button'; +import InfoContainer from '@components/infoContainer'; +import BottomBar from '@components/tabBar'; +import { Container } from '@screens/home'; +import { AdvanceSettings } from '@screens/swap/swapConfirmation/advanceSettings'; import FeesBlock from '@screens/swap/swapConfirmation/feesBlock'; +import FunctionBlock from '@screens/swap/swapConfirmation/functionBlock'; import RouteBlock from '@screens/swap/swapConfirmation/routeBlock'; import StxInfoBlock from '@screens/swap/swapConfirmation/stxInfoBlock'; -import { useCallback, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; import { useConfirmSwap } from '@screens/swap/swapConfirmation/useConfirmSwap'; -import { AdvanceSettings } from '@screens/swap/swapConfirmation/advanceSettings'; -import SponsoredTransactionIcon from '@assets/img/transactions/CircleWavyCheck.svg'; -import InfoContainer from '@components/infoContainer'; import { SUPPORT_URL_TAB_TARGET, SWAP_SPONSOR_DISABLED_SUPPORT_URL } from '@utils/constants'; +import { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const TitleText = styled.div((props) => ({ fontSize: 21, fontWeight: 700, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginBottom: props.theme.spacing(12), marginTop: props.theme.spacing(12), })); @@ -31,7 +31,7 @@ export const ButtonContainer = styled.div((props) => ({ marginTop: props.theme.spacing(8), position: 'sticky', bottom: 0, - background: props.theme.colors.background.elevation0, + background: props.theme.colors.elevation0, padding: `${props.theme.spacing(12)}px 0`, })); @@ -42,7 +42,7 @@ export const ActionButtonWrap = styled.div((props) => ({ const SponsoredTransactionText = styled.div((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginTop: props.theme.spacing(10), display: 'flex', gap: props.theme.spacing(4), diff --git a/src/app/screens/swap/swapConfirmation/routeBlock/index.tsx b/src/app/screens/swap/swapConfirmation/routeBlock/index.tsx index 3d0f5d187..3837685eb 100644 --- a/src/app/screens/swap/swapConfirmation/routeBlock/index.tsx +++ b/src/app/screens/swap/swapConfirmation/routeBlock/index.tsx @@ -1,14 +1,14 @@ +import TokenImage from '@components/tokenImage'; import { Container, FoldButton, TitleContainer, TitleText, } from '@screens/swap/swapConfirmation/stxInfoBlock'; +import { SwapConfirmationOutput } from '@screens/swap/swapConfirmation/useConfirmSwap'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { useState } from 'react'; -import { SwapConfirmationOutput } from '@screens/swap/swapConfirmation/useConfirmSwap'; -import TokenImage from '@components/tokenImage'; const RouteProgress = styled.div((props) => ({ position: 'relative', @@ -22,7 +22,7 @@ const RouteProgress = styled.div((props) => ({ })); const DashLine = styled.div((props) => ({ - borderTop: `1.5px dashed ${props.theme.colors.white[800]}`, + borderTop: `1.5px dashed ${props.theme.colors.white_800}`, width: '100%', position: 'absolute', left: 0, @@ -36,13 +36,13 @@ const ProgressItem = styled.div((props) => ({ position: 'relative', paddingRight: props.theme.spacing(3.5), paddingLeft: props.theme.spacing(3.5), - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, })); const ProgressItemText = styled.p((props) => ({ ...props.theme.body_m, fontWeight: 400, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(4), })); diff --git a/src/app/screens/swap/swapConfirmation/stxInfoBlock/index.tsx b/src/app/screens/swap/swapConfirmation/stxInfoBlock/index.tsx index fc457b162..11b6c88e3 100644 --- a/src/app/screens/swap/swapConfirmation/stxInfoBlock/index.tsx +++ b/src/app/screens/swap/swapConfirmation/stxInfoBlock/index.tsx @@ -1,22 +1,22 @@ -import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import FoldIconUp from '@assets/img/swap/fold_arrow_up.svg'; -import FoldDownIcon from '@assets/img/swap/fold_arrow_down.svg'; import AddressIcon from '@assets/img/swap/address.svg'; import CopyIcon from '@assets/img/swap/copy.svg'; -import { getTruncatedAddress } from '@utils/helper'; +import FoldDownIcon from '@assets/img/swap/fold_arrow_down.svg'; +import FoldIconUp from '@assets/img/swap/fold_arrow_up.svg'; import { StyledToolTip } from '@components/accountRow'; -import { useCallback, useState } from 'react'; -import { EstimateUSDText } from '@screens/swap/swapTokenBlock'; -import { SwapConfirmationOutput } from '@screens/swap/swapConfirmation/useConfirmSwap'; import TokenImage from '@components/tokenImage'; +import { SwapConfirmationOutput } from '@screens/swap/swapConfirmation/useConfirmSwap'; +import { EstimateUSDText } from '@screens/swap/swapTokenBlock'; +import { getTruncatedAddress } from '@utils/helper'; +import { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; export const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', padding: props.theme.spacing(10), marginBottom: props.theme.spacing(6), - background: props.theme.colors.background.elevation1, + background: props.theme.colors.elevation1, borderRadius: 12, })); @@ -29,7 +29,7 @@ export const TitleContainer = styled.div(() => ({ export const TitleText = styled.h3((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, fontSize: 14, fontWeight: 500, })); @@ -42,7 +42,7 @@ export const FoldArrow = styled.img(() => ({ const DescriptionText = styled.h3((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[400], + color: props.theme.colors.white_400, fontSize: 14, fontWeight: 500, marginTop: props.theme.spacing(8), @@ -57,7 +57,7 @@ const AmountContainer = styled.div(() => ({ const AmountLabel = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, fontSize: 14, fontWeight: 500, marginLeft: props.theme.spacing(5), @@ -82,7 +82,7 @@ const ItemsCenterContainer = styled.div(() => ({ const AddressLabelText = styled.h3((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white[200], + color: props.theme.colors.white_200, marginLeft: props.theme.spacing(5), })); diff --git a/src/app/screens/swap/swapConfirmation/useConfirmSwap.tsx b/src/app/screens/swap/swapConfirmation/useConfirmSwap.tsx index c9c917837..578fe0448 100644 --- a/src/app/screens/swap/swapConfirmation/useConfirmSwap.tsx +++ b/src/app/screens/swap/swapConfirmation/useConfirmSwap.tsx @@ -1,19 +1,20 @@ -import { Currency, SponsoredTxErrorCode, SponsoredTxError } from 'alex-sdk'; -import { useNavigate } from 'react-router-dom'; -import { SwapToken } from '@screens/swap/useSwap'; +import { TokenImageProps } from '@components/tokenImage'; +import useNetworkSelector from '@hooks/useNetwork'; +import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; +import { SwapToken } from '@screens/swap/types'; import { broadcastSignedTransaction, + microstacksToStx, signTransaction, StacksTransaction, - microstacksToStx, } from '@secretkeylabs/xverse-core'; -import { deserializeTransaction } from '@stacks/transactions'; -import useNetworkSelector from '@hooks/useNetwork'; import { ApiResponseError } from '@secretkeylabs/xverse-core/types'; -import { TokenImageProps } from '@components/tokenImage'; -import { useState } from 'react'; +import { deserializeTransaction } from '@stacks/transactions'; +import { Currency, SponsoredTxError, SponsoredTxErrorCode } from 'alex-sdk'; import BigNumber from 'bignumber.js'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useAlexSponsoredTransaction } from '../useAlexSponsoredTransaction'; import { useCurrencyConversion } from '../useCurrencyConversion'; @@ -42,12 +43,13 @@ export type SwapConfirmationOutput = Omit & }; export function useConfirmSwap(input: SwapConfirmationInput): SwapConfirmationOutput { - const { selectedAccount, seedPhrase } = useWalletSelector(); + const { selectedAccount } = useWalletSelector(); const selectedNetwork = useNetworkSelector(); const { isSponsored, sponsorTransaction, isSponsorDisabled } = useAlexSponsoredTransaction( input.userOverrideSponsorValue, ); const { currencyToToken } = useCurrencyConversion(); + const { getSeed } = useSeedVault(); const navigate = useNavigate(); const [unsignedTx, setUnsignedTx] = useState( deserializeTransaction(input.unsignedTx), @@ -71,6 +73,7 @@ export function useConfirmSwap(input: SwapConfirmationInput): SwapConfirmationOu isSponsored, isSponsorDisabled, onConfirm: async () => { + const seedPhrase = await getSeed(); const signed = await signTransaction( unsignedTx, seedPhrase, diff --git a/src/app/screens/swap/swapInfoBlock/index.tsx b/src/app/screens/swap/swapInfoBlock/index.tsx index 2a7df5571..5fec075c4 100644 --- a/src/app/screens/swap/swapInfoBlock/index.tsx +++ b/src/app/screens/swap/swapInfoBlock/index.tsx @@ -21,7 +21,7 @@ const CustomSwitch = styled(Switch)` const PoweredByAlexText = styled.span((props) => ({ ...props.theme.body_xs, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const DetailButton = styled.button((props) => ({ @@ -31,7 +31,7 @@ const DetailButton = styled.button((props) => ({ background: 'transparent', alignItems: 'center', ...props.theme.body_medium_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const DL = styled.dl((props) => ({ @@ -43,13 +43,13 @@ const DL = styled.dl((props) => ({ const DT = styled.dt((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, flex: '50%', })); const DD = styled.dd((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, flex: '50%', display: 'flex', justifyContent: 'flex-end', @@ -68,11 +68,11 @@ const SlippageImg = styled.img(() => ({ const CannotBeSponsored = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['200'], + color: props.theme.colors.white_200, })); const SponsorTransactionSwitchLabel = styled(DT)<{ disabled: boolean }>((props) => ({ - color: props.disabled ? props.theme.colors.white['400'] : props.theme.colors.white['200'], + color: props.disabled ? props.theme.colors.white_400 : props.theme.colors.white_200, })); const ToggleContainer = styled(DD)({ @@ -81,7 +81,7 @@ const ToggleContainer = styled(DD)({ const LearnMoreAnchor = styled.a((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(2), display: 'block', })); diff --git a/src/app/screens/swap/swapTokenBlock/index.tsx b/src/app/screens/swap/swapTokenBlock/index.tsx index d5dc08922..26fe27324 100644 --- a/src/app/screens/swap/swapTokenBlock/index.tsx +++ b/src/app/screens/swap/swapTokenBlock/index.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; import ChevronIcon from '@assets/img/swap/chevron.svg'; -import { SwapToken } from '@screens/swap/useSwap'; import TokenImage from '@components/tokenImage'; +import { SwapToken } from '@screens/swap/types'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; const Container = styled.div((props) => ({ display: 'flex', @@ -28,7 +28,7 @@ const Text = styled.p((props) => ({ const BalanceText = styled.label((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginRight: props.theme.spacing(2), })); @@ -36,18 +36,18 @@ const CardContainer = styled.div<{ error?: boolean }>((props) => ({ display: 'flex', flexDirection: 'column', rowGap: props.theme.spacing(3), - background: props.theme.colors.background.elevation_1, + background: props.theme.colors.elevation_n1, border: '1px solid', 'border-color': props.error ? props.theme.colors.feedback.error_700 - : props.theme.colors.background.elevation2, + : props.theme.colors.elevation2, borderRadius: 8, padding: props.theme.spacing(8), ':focus-within': { border: '1px solid', 'border-color': props.error ? props.theme.colors.feedback.error_700 - : props.theme.colors.background.elevation6, + : props.theme.colors.elevation6, }, })); @@ -78,7 +78,7 @@ export const NumberInput = styled.input` export const AmountInput = styled(NumberInput)<{ error?: boolean }>((props) => ({ ...props.theme.body_bold_l, flex: 1, - color: props.error ? props.theme.colors.feedback.error : props.theme.colors.white['0'], + color: props.error ? props.theme.colors.feedback.error : props.theme.colors.white_0, marginLeft: props.theme.spacing(2), textAlign: 'right', backgroundColor: 'transparent', @@ -88,12 +88,12 @@ export const AmountInput = styled(NumberInput)<{ error?: boolean }>((props) => ( const CoinText = styled.div((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); export const EstimateUSDText = styled.p((props) => ({ ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginLeft: 'auto', })); diff --git a/src/app/screens/swap/types.ts b/src/app/screens/swap/types.ts new file mode 100644 index 000000000..431ec592b --- /dev/null +++ b/src/app/screens/swap/types.ts @@ -0,0 +1,47 @@ +import { TokenImageProps } from '@components/tokenImage'; +import { FungibleToken } from '@secretkeylabs/xverse-core'; +import { Currency } from 'alex-sdk'; + +export type STXOrFungibleToken = 'STX' | FungibleToken; +export type Side = 'from' | 'to'; + +export type SwapToken = { + name: string; + image: TokenImageProps; + balance?: number; + amount?: number; + fiatAmount?: number; +}; + +export type UseSwap = { + coinsList: FungibleToken[]; + isLoadingWalletData: boolean; + selectedFromToken?: SwapToken; + selectedToToken?: SwapToken; + onSelectToken: (token: STXOrFungibleToken, side: Side) => void; + inputAmount: string; + inputAmountInvalid?: boolean; + onInputAmountChanged: (amount: string) => void; + handleClickDownArrow: (event: React.MouseEvent) => void; + submitError?: string; + swapInfo?: { + exchangeRate?: string; + lpFee?: string; + route?: string; + }; + slippage: number; + onSlippageChanged: (slippage: number) => void; + minReceived?: string; + onSwap?: () => Promise; + isSponsored: boolean; + isServiceRunning: boolean; + handleChangeUserOverrideSponsorValue: (checked: boolean) => void; + isSponsorDisabled: boolean; +}; + +export type SelectedCurrencyState = { + to?: Currency; + from?: Currency; + prevTo?: Currency; + prevFrom?: Currency; +}; diff --git a/src/app/screens/swap/useCurrencyConversion.tsx b/src/app/screens/swap/useCurrencyConversion.tsx index 52fa2bbeb..b912ea892 100644 --- a/src/app/screens/swap/useCurrencyConversion.tsx +++ b/src/app/screens/swap/useCurrencyConversion.tsx @@ -4,7 +4,7 @@ import { LoaderSize } from '@utils/constants'; import { ftDecimals } from '@utils/helper'; import { AlexSDK, Currency } from 'alex-sdk'; import BigNumber from 'bignumber.js'; -import { SwapToken } from './useSwap'; +import { SwapToken } from './types'; export function useCurrencyConversion() { const alexSDK = new AlexSDK(); diff --git a/src/app/screens/swap/useSwap.tsx b/src/app/screens/swap/useSwap.tsx index c6053181f..23cab0a01 100644 --- a/src/app/screens/swap/useSwap.tsx +++ b/src/app/screens/swap/useSwap.tsx @@ -1,69 +1,25 @@ -import { useEffect, useState } from 'react'; +import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { SwapConfirmationInput } from '@screens/swap/swapConfirmation/useConfirmSwap'; import { FungibleToken, getNewNonce, + getNonce, microstacksToStx, setNonce, - getNonce, } from '@secretkeylabs/xverse-core'; -import { useTranslation } from 'react-i18next'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { TokenImageProps } from '@components/tokenImage'; +import { AnchorMode, makeUnsignedContractCall, PostConditionMode } from '@stacks/transactions'; import { AlexSDK, Currency } from 'alex-sdk'; import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import { SwapConfirmationInput } from '@screens/swap/swapConfirmation/useConfirmSwap'; -import { AnchorMode, makeUnsignedContractCall, PostConditionMode } from '@stacks/transactions'; -import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; +import { SelectedCurrencyState, Side, STXOrFungibleToken, UseSwap } from './types'; import { useAlexSponsoredTransaction } from './useAlexSponsoredTransaction'; import { useCurrencyConversion } from './useCurrencyConversion'; const isNotNull = (t: T | null | undefined): t is T => t != null; -export type STXOrFungibleToken = 'STX' | FungibleToken; -export type Side = 'from' | 'to'; - -export type SwapToken = { - name: string; - image: TokenImageProps; - balance?: number; - amount?: number; - fiatAmount?: number; -}; - -export type UseSwap = { - coinsList: FungibleToken[]; - isLoadingWalletData: boolean; - selectedFromToken?: SwapToken; - selectedToToken?: SwapToken; - onSelectToken: (token: STXOrFungibleToken, side: Side) => void; - inputAmount: string; - inputAmountInvalid?: boolean; - onInputAmountChanged: (amount: string) => void; - handleClickDownArrow: (event: React.MouseEvent) => void; - submitError?: string; - swapInfo?: { - exchangeRate?: string; - lpFee?: string; - route?: string; - }; - slippage: number; - onSlippageChanged: (slippage: number) => void; - minReceived?: string; - onSwap?: () => Promise; - isSponsored: boolean; - isServiceRunning: boolean; - handleChangeUserOverrideSponsorValue: (checked: boolean) => void; - isSponsorDisabled: boolean; -}; - -export type SelectedCurrencyState = { - to?: Currency; - from?: Currency; - prevTo?: Currency; - prevFrom?: Currency; -}; - function updateOppositeCurrencyIfSameAsSelected( state: SelectedCurrencyState, { newCurrency, side }, diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index 8ea945b09..ffec77882 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -1,18 +1,22 @@ -import useDappRequest from '@hooks/useTransationRequest'; import ContractCallRequest from '@components/transactionsRequests/ContractCallRequest'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { useEffect, useState } from 'react'; -import { StacksTransaction } from '@stacks/transactions'; import ContractDeployRequest from '@components/transactionsRequests/ContractDeployTransaction'; import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; +import useNetworkSelector from '@hooks/useNetwork'; +import useDappRequest from '@hooks/useTransationRequest'; +import useWalletReducer from '@hooks/useWalletReducer'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { + Coin, + ContractFunction, + createDeployContractRequest, + extractFromPayload, +} from '@secretkeylabs/xverse-core'; +import { StacksTransaction } from '@stacks/transactions'; +import { getNetworkType, isHardwareAccount } from '@utils/helper'; +import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; import styled from 'styled-components'; -import { ContractFunction } from '@secretkeylabs/xverse-core/types/api/stacks/transaction'; -import { Coin, createDeployContractRequest, extractFromPayload } from '@secretkeylabs/xverse-core'; -import useWalletReducer from '@hooks/useWalletReducer'; -import { getNetworkType, isHardwareAccount } from '@utils/helper'; -import useNetworkSelector from '@hooks/useNetwork'; import { getContractCallPromises, getTokenTransferRequest } from './helper'; const LoaderContainer = styled.div((props) => ({ diff --git a/src/app/screens/transactionStatus/index.tsx b/src/app/screens/transactionStatus/index.tsx index fcc85233a..000f9480c 100644 --- a/src/app/screens/transactionStatus/index.tsx +++ b/src/app/screens/transactionStatus/index.tsx @@ -1,14 +1,14 @@ -import styled from 'styled-components'; -import { useTranslation } from 'react-i18next'; -import { useLocation, useNavigate } from 'react-router-dom'; -import ActionButton from '@components/button'; import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; import Success from '@assets/img/send/check_circle.svg'; import Failure from '@assets/img/send/x_circle.svg'; -import { getBtcTxStatusUrl, getStxTxStatusUrl } from '@utils/helper'; -import useWalletSelector from '@hooks/useWalletSelector'; +import ActionButton from '@components/button'; import CopyButton from '@components/copyButton'; import InfoContainer from '@components/infoContainer'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { getBtcTxStatusUrl, getStxTxStatusUrl } from '@utils/helper'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; const TxStatusContainer = styled.div({ background: 'rgba(25, 25, 48, 0.74)', @@ -85,14 +85,14 @@ const Image = styled.img({ const HeadingText = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: 'center', marginTop: props.theme.spacing(8), })); const BodyText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(8), textAlign: 'center', overflowWrap: 'break-word', @@ -104,19 +104,19 @@ const BodyText = styled.h1((props) => ({ const TxIDText = styled.h1((props) => ({ ...props.theme.headline_category_s, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(8), textTransform: 'uppercase', })); const BeforeButtonText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, })); const IDText = styled.h1((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(2), wordBreak: 'break-all', })); @@ -124,7 +124,7 @@ const IDText = styled.h1((props) => ({ const ButtonText = styled.h1((props) => ({ ...props.theme.body_m, marginRight: props.theme.spacing(2), - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, })); const ButtonImage = styled.img((props) => ({ diff --git a/src/app/screens/walletExists/index.tsx b/src/app/screens/walletExists/index.tsx index a66fb6420..a404d7fb6 100644 --- a/src/app/screens/walletExists/index.tsx +++ b/src/app/screens/walletExists/index.tsx @@ -15,7 +15,7 @@ const ContentContainer = styled.div((props) => ({ const Title = styled.h1((props) => ({ ...props.theme.headline_s, - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, marginTop: props.theme.spacing(8), textAlign: 'center', fontSize: 20, @@ -23,14 +23,14 @@ const Title = styled.h1((props) => ({ const Subtitle = styled.h2((props) => ({ ...props.theme.body_m, - color: props.theme.colors.white['400'], + color: props.theme.colors.white_400, marginTop: props.theme.spacing(8), textAlign: 'center', })); const ContinueButton = styled.button((props) => ({ ...props.theme.body_bold_m, - color: props.theme.colors.background.elevation0, + color: props.theme.colors.elevation0, backgroundColor: props.theme.colors.action.classic, borderRadius: props.theme.radius(1), marginLeft: props.theme.spacing(8), @@ -47,7 +47,7 @@ const ContinueButton = styled.button((props) => ({ }, ':disabled': { background: props.theme.colors.action.classicLight, - color: props.theme.colors.background.elevation8, + color: props.theme.colors.elevation8, cursor: 'initial', }, })); @@ -69,7 +69,7 @@ function WalletExists(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'WALLET_EXISTS_SCREEN' }); const [userAccepted, setUserAccepted] = useState(false); - const handleClose = () => { + const handleClose = async () => { window.close(); }; diff --git a/src/app/stores/index.ts b/src/app/stores/index.ts index 0435caf94..94f0fbe20 100644 --- a/src/app/stores/index.ts +++ b/src/app/stores/index.ts @@ -1,4 +1,4 @@ -import ChromeStorage from '@utils/storage'; +import { chromeLocalStorage } from '@utils/chromeStorage'; import { applyMiddleware, combineReducers, createStore } from 'redux'; import { PersistConfig, persistReducer, persistStore } from 'redux-persist'; import { createStateSyncMiddleware, initMessageListener } from 'redux-state-sync'; @@ -7,20 +7,17 @@ import * as actions from './wallet/actions/types'; import { WalletState } from './wallet/actions/types'; import walletReducer from './wallet/reducer'; -export const storage = new ChromeStorage(chrome.storage.local, chrome.runtime); - const rootPersistConfig = { version: 1, key: 'root', - storage, + storage: chromeLocalStorage, blacklist: ['walletState'], }; export const WalletPersistConfig: PersistConfig = { version: 1, key: 'walletState', - storage, - blacklist: ['seedPhrase'], + storage: chromeLocalStorage, }; const appReducer = combineReducers({ @@ -39,9 +36,8 @@ const storeMiddleware = [ // We only want to sync seedphrase data for onboarding whitelist: [ actions.StoreEncryptedSeedKey, - actions.SetWalletSeedPhraseKey, - actions.UnlockWalletKey, actions.SelectAccountKey, + actions.SetWalletUnlockedKey, actions.AddAccountKey, actions.UpdateLedgerAccountsKey, ], diff --git a/src/app/stores/wallet/actions/actionCreators.ts b/src/app/stores/wallet/actions/actionCreators.ts index 26bd7d912..cbf9a060e 100644 --- a/src/app/stores/wallet/actions/actionCreators.ts +++ b/src/app/stores/wallet/actions/actionCreators.ts @@ -1,15 +1,15 @@ import { PostGuardPing } from '@components/guards/singleTab'; -import { AccountType } from '@secretkeylabs/xverse-core'; -import { +import type { Account, + AccountType, + AppInfo, BaseWallet, Coin, - FeesMultipliers, FungibleToken, SettingsNetwork, SupportedCurrency, TransactionData, -} from '@secretkeylabs/xverse-core/types'; +} from '@secretkeylabs/xverse-core'; import BigNumber from 'bignumber.js'; import * as actions from './types'; @@ -20,21 +20,6 @@ export function setWalletAction(wallet: BaseWallet): actions.SetWallet { }; } -export function unlockWalletAction(seed: string) { - return { - type: actions.UnlockWalletKey, - seed, - }; -} - -export function lockWalletAction() { - // We post the closeWallet action to the guard so that any open tabs will close - PostGuardPing('closeWallet'); - return { - type: actions.LockWalletKey, - }; -} - export function storeEncryptedSeedAction(encryptedSeed: string): actions.StoreEncryptedSeed { return { type: actions.StoreEncryptedSeedKey, @@ -42,13 +27,6 @@ export function storeEncryptedSeedAction(encryptedSeed: string): actions.StoreEn }; } -export function setWalletSeedPhraseAction(seedPhrase: string): actions.SetWalletSeedPhrase { - return { - type: actions.SetWalletSeedPhraseKey, - seedPhrase, - }; -} - export function resetWalletAction(): actions.ResetWallet { // We post the closeWallet action to the guard so that any open tabs will close PostGuardPing('closeWallet'); @@ -117,7 +95,7 @@ export function selectAccount( }; } -export function setFeeMultiplierAction(feeMultipliers: FeesMultipliers): actions.SetFeeMultiplier { +export function setFeeMultiplierAction(feeMultipliers: AppInfo): actions.SetFeeMultiplier { return { type: actions.SetFeeMultiplierKey, feeMultipliers, @@ -277,3 +255,10 @@ export function setWalletLockPeriodAction( walletLockPeriod, }; } + +export function setWalletUnlockedAction(isUnlocked: boolean): actions.SetWalletUnlocked { + return { + type: actions.SetWalletUnlockedKey, + isUnlocked, + }; +} diff --git a/src/app/stores/wallet/actions/types.ts b/src/app/stores/wallet/actions/types.ts index 2115dfaf9..26c2db85b 100644 --- a/src/app/stores/wallet/actions/types.ts +++ b/src/app/stores/wallet/actions/types.ts @@ -1,23 +1,20 @@ -import { +import type { Account, AccountType, AppInfo, BaseWallet, Coin, - FeesMultipliers, FungibleToken, SettingsNetwork, SupportedCurrency, TransactionData, -} from '@secretkeylabs/xverse-core/types'; +} from '@secretkeylabs/xverse-core'; import BigNumber from 'bignumber.js'; export const SetWalletKey = 'SetWallet'; export const ResetWalletKey = 'ResetWallet'; export const FetchAccountKey = 'FetchAccount'; export const SelectAccountKey = 'SelectAccount'; -export const UnlockWalletKey = 'UnlockWallet'; -export const LockWalletKey = 'LockWallet'; export const StoreEncryptedSeedKey = 'StoreEncryptedSeed'; export const UpdateVisibleCoinListKey = 'UpdateVisibleCoinList'; export const AddAccountKey = 'AddAccount'; @@ -25,7 +22,6 @@ export const SetFeeMultiplierKey = 'SetFeeMultiplierKey'; export const ChangeFiatCurrencyKey = 'ChangeFiatCurrency'; export const ChangeNetworkKey = 'ChangeNetwork'; export const GetActiveAccountsKey = 'GetActiveAccounts'; -export const SetWalletSeedPhraseKey = 'SetWalletSeed'; export const FetchStxWalletDataRequestKey = 'FetchStxWalletDataRequest'; export const SetStxWalletDataKey = 'SetStxWalletDataKey'; @@ -49,6 +45,8 @@ export const SetBrcCoinsListKey = 'SetBrcCoinsList'; export const SetWalletLockPeriodKey = 'SetWalletLockPeriod'; +export const SetWalletUnlockedKey = 'SetWalletUnlocked'; + export enum WalletSessionPeriods { LOW = 1, STANDARD = 10, @@ -67,7 +65,6 @@ export interface WalletState { ledgerAccountsList: Account[]; selectedAccount: Account | null; network: SettingsNetwork; - seedPhrase: string; encryptedSeed: string; fiatCurrency: SupportedCurrency; btcFiatRate: BigNumber; @@ -92,6 +89,7 @@ export interface WalletState { accountName: string | undefined; btcApiUrl: string; walletLockPeriod: WalletSessionPeriods; + isUnlocked: boolean; } export interface SetWallet { @@ -103,24 +101,11 @@ export interface StoreEncryptedSeed { type: typeof StoreEncryptedSeedKey; encryptedSeed: string; } - -export interface SetWalletSeedPhrase { - type: typeof SetWalletSeedPhraseKey; - seedPhrase: string; -} -export interface UnlockWallet { - type: typeof UnlockWalletKey; - seed: string; -} - export interface SetFeeMultiplier { type: typeof SetFeeMultiplierKey; - feeMultipliers: FeesMultipliers; + feeMultipliers: AppInfo; } -export interface LockWallet { - type: typeof LockWalletKey; -} export interface ResetWallet { type: typeof ResetWalletKey; } @@ -240,7 +225,10 @@ export interface SetWalletLockPeriod { type: typeof SetWalletLockPeriodKey; walletLockPeriod: WalletSessionPeriods; } - +export interface SetWalletUnlocked { + type: typeof SetWalletUnlockedKey; + isUnlocked: boolean; +} export type WalletActions = | SetWallet | ResetWallet @@ -249,9 +237,6 @@ export type WalletActions = | AddLedgerAccount | SelectAccount | StoreEncryptedSeed - | SetWalletSeedPhrase - | UnlockWallet - | LockWallet | SetFeeMultiplier | SetCoinRates | SetStxWalletData @@ -262,8 +247,11 @@ export type WalletActions = | ChangeNetwork | GetActiveAccounts | ChangeActivateOrdinals + | ChangeActivateRareSats | ChangeShowBtcReceiveAlert | ChangeShowOrdinalReceiveAlert | ChangeShowDataCollectionAlert | SetBrcCoinsData - | SetWalletLockPeriod; + | SetWalletLockPeriod + | SetRareSatsNoticeDismissed + | SetWalletUnlocked; diff --git a/src/app/stores/wallet/reducer.ts b/src/app/stores/wallet/reducer.ts index 2c29a307e..6b95f5164 100644 --- a/src/app/stores/wallet/reducer.ts +++ b/src/app/stores/wallet/reducer.ts @@ -10,7 +10,6 @@ import { UpdateLedgerAccountsKey, FetchAccountKey, GetActiveAccountsKey, - LockWalletKey, ResetWalletKey, SelectAccountKey, SetBrcCoinsListKey, @@ -21,13 +20,12 @@ import { SetStxWalletDataKey, SetWalletKey, SetWalletLockPeriodKey, - SetWalletSeedPhraseKey, StoreEncryptedSeedKey, - UnlockWalletKey, UpdateVisibleCoinListKey, WalletActions, WalletSessionPeriods, WalletState, + SetWalletUnlockedKey, ChangeShowDataCollectionAlertKey, RareSatsNoticeDismissedKey, ChangeHasActivatedRareSatsKey, @@ -45,7 +43,6 @@ const initialWalletState: WalletState = { accountsList: [], ledgerAccountsList: [], selectedAccount: null, - seedPhrase: '', encryptedSeed: '', fiatCurrency: 'USD', btcFiatRate: new BigNumber(0), @@ -70,6 +67,7 @@ const initialWalletState: WalletState = { accountType: 'software', accountName: undefined, walletLockPeriod: WalletSessionPeriods.STANDARD, + isUnlocked: false, }; const walletReducer = ( @@ -81,7 +79,14 @@ const walletReducer = ( case SetWalletKey: return { ...state, - ...action.wallet, + stxAddress: action.wallet.stxAddress, + btcAddress: action.wallet.btcAddress, + ordinalsAddress: action.wallet.ordinalsAddress, + masterPubKey: action.wallet.masterPubKey, + stxPublicKey: action.wallet.stxPublicKey, + btcPublicKey: action.wallet.btcPublicKey, + ordinalsPublicKey: action.wallet.ordinalsPublicKey, + accountType: action.wallet.accountType, }; case ResetWalletKey: return { @@ -123,21 +128,6 @@ const walletReducer = ( ...state, encryptedSeed: action.encryptedSeed, }; - case SetWalletSeedPhraseKey: - return { - ...state, - seedPhrase: action.seedPhrase, - }; - case UnlockWalletKey: - return { - ...state, - seedPhrase: action.seed, - }; - case LockWalletKey: - return { - ...state, - seedPhrase: '', - }; case SetCoinRatesKey: return { ...state, @@ -230,6 +220,11 @@ const walletReducer = ( ...state, walletLockPeriod: action.walletLockPeriod, }; + case SetWalletUnlockedKey: + return { + ...state, + isUnlocked: action.isUnlocked, + }; default: return state; } diff --git a/src/app/utils/brc20.ts b/src/app/utils/brc20.ts index a8fe73293..3606f38b7 100644 --- a/src/app/utils/brc20.ts +++ b/src/app/utils/brc20.ts @@ -1,4 +1,9 @@ -import { brc20TransferEstimateFees, FungibleToken, UTXO } from '@secretkeylabs/xverse-core'; +import { + brc20TransferEstimateFees, + FungibleToken, + NetworkType, + UTXO, +} from '@secretkeylabs/xverse-core'; import BigNumber from 'bignumber.js'; export type TransferEstimateResult = Awaited>; @@ -9,6 +14,7 @@ export type Brc20TransferEstimateFeesParams = { amount: number; feeRate: number; revealAddress: string; + network: NetworkType; }; export type SendBrc20TransferState = { diff --git a/src/app/utils/storage.ts b/src/app/utils/chromeStorage.ts similarity index 80% rename from src/app/utils/storage.ts rename to src/app/utils/chromeStorage.ts index 6fbf3f214..44d4527a0 100644 --- a/src/app/utils/storage.ts +++ b/src/app/utils/chromeStorage.ts @@ -19,7 +19,7 @@ class ChromeStorage { return runtimeMap.get(this).lastError; } - setItem(key: string, item: any) { + setItem(key: string, item: any): Promise { return new Promise((resolve, reject) => { this.getDriver().set({ [key]: item }, () => { if (this.hasError()) { @@ -30,7 +30,7 @@ class ChromeStorage { }); } - getItem(key: string) { + getItem(key: string): Promise { return new Promise((resolve, reject) => { this.getDriver().get(key, (response: any) => { if (this.hasError()) { @@ -53,3 +53,5 @@ class ChromeStorage { } } export default ChromeStorage; +export const chromeSessionStorage = new ChromeStorage(chrome.storage.session, chrome.runtime); +export const chromeLocalStorage = new ChromeStorage(chrome.storage.local, chrome.runtime); diff --git a/src/app/utils/constants.ts b/src/app/utils/constants.ts index e30046dae..9af30e56d 100644 --- a/src/app/utils/constants.ts +++ b/src/app/utils/constants.ts @@ -1,11 +1,11 @@ /* eslint-disable prefer-destructuring */ +import type { NetworkType, SettingsNetwork } from '@secretkeylabs/xverse-core'; import { BTC_BASE_URI_MAINNET, BTC_BASE_URI_TESTNET, HIRO_MAINNET_DEFAULT, HIRO_TESTNET_DEFAULT, } from '@secretkeylabs/xverse-core/constant'; -import { SettingsNetwork } from '@secretkeylabs/xverse-core/types'; export const BNS_CONTRACT = 'SP000000000000000000002Q6VF78.bns::names'; export const GAMMA_URL = 'https://gamma.io/'; @@ -18,7 +18,10 @@ export const BTC_TRANSACTION_STATUS_URL = 'https://mempool.space/tx/'; export const BTC_TRANSACTION_TESTNET_STATUS_URL = 'https://mempool.space/testnet/tx/'; export const TRANSACTION_STATUS_URL = 'https://explorer.stacks.co/txid/'; export const XVERSE_WEB_POOL_URL = 'https://pool.xverse.app'; -export const XVERSE_ORDIVIEW_URL = 'https://ord.xverse.app'; + +export const XVERSE_ORDIVIEW_URL = (network: NetworkType) => + `https://ord${network === 'Mainnet' ? '' : '-testnet'}.xverse.app`; + export const MAGISAT_IO_RARITY_SCAN_URL = 'https://magisat.io/wallet?walletAddress='; export const TRANSAC_URL = 'https://global.transak.com'; diff --git a/src/app/utils/currency.ts b/src/app/utils/currency.ts index f62893cce..c146622ed 100644 --- a/src/app/utils/currency.ts +++ b/src/app/utils/currency.ts @@ -1,16 +1,16 @@ -import UsFlag from '@assets/img/settings/ic_usa.svg'; +import ARG from '@assets/img/settings/ars.svg'; +import BRL from '@assets/img/settings/brl.svg'; +import CNY from '@assets/img/settings/cny.svg'; +import GBP from '@assets/img/settings/gbp.svg'; +import HKD from '@assets/img/settings/hkd.svg'; import CanFlag from '@assets/img/settings/ic_can.svg'; import EurFlag from '@assets/img/settings/ic_eu.svg'; import JapanFlag from '@assets/img/settings/ic_jp.svg'; -import CNY from '@assets/img/settings/cny.svg'; -import ARG from '@assets/img/settings/ars.svg'; -import HKD from '@assets/img/settings/hkd.svg'; +import UsFlag from '@assets/img/settings/ic_usa.svg'; import KRW from '@assets/img/settings/krw.svg'; -import SGD from '@assets/img/settings/sgd.svg'; -import GBP from '@assets/img/settings/gbp.svg'; -import BRL from '@assets/img/settings/brl.svg'; import RUB from '@assets/img/settings/rub.svg'; -import { SupportedCurrency } from '@secretkeylabs/xverse-core/types'; +import SGD from '@assets/img/settings/sgd.svg'; +import type { SupportedCurrency } from '@secretkeylabs/xverse-core'; export interface Currency { name: SupportedCurrency; diff --git a/src/app/utils/encryptionUtils.ts b/src/app/utils/encryptionUtils.ts index 47080a5e2..e9c8095e2 100644 --- a/src/app/utils/encryptionUtils.ts +++ b/src/app/utils/encryptionUtils.ts @@ -1,17 +1,24 @@ +import argon2 from 'argon2-browser'; +import { encryptSeedPhrase, decryptSeedPhrase } from '@secretkeylabs/xverse-core/encryption'; import { - decryptMnemonicWithCallback, - encryptMnemonicWithCallback, + encryptMnemonicWithHandler, + decryptMnemonicWithHandler, } from '@secretkeylabs/xverse-core/wallet'; -import { decryptMnemonic, encryptMnemonic } from '@stacks/encryption'; -import argon2 from 'argon2-browser'; -import { getSalt, saveSalt } from './localStorage'; -function generateRandomKey(bytesCount: number): string { - const randomValues = Array.from(crypto.getRandomValues(new Uint8Array(bytesCount))); - return randomValues.map((val) => `00${val.toString(16)}`.slice(-2)).join(''); +export async function generateKeyArgon2id(password: string, salt: string): Promise { + const result = await argon2.hash({ + pass: password, + salt, + time: 3, + mem: 64 * 1024, + parallelism: 4, + hashLen: 16, + type: argon2.ArgonType.Argon2id, + }); + return result.hashHex; } -async function generateKeyArgon2(password: string, salt: string): Promise { +export async function generateKeyArgon2i(password: string, salt: string): Promise { const result = await argon2.hash({ pass: password, salt, @@ -24,40 +31,40 @@ async function generateKeyArgon2(password: string, salt: string): Promise { - return encryptMnemonicWithCallback({ +export async function encryptSeedPhraseHandler(seed: string, password: string): Promise { + return encryptMnemonicWithHandler({ seed, password, - mnemonicEncryptionHandler: encryptMnemonic, - passwordHashGenerator: generatePasswordHash, + mnemonicEncryptionHandler: encryptSeedPhrase, }); } -export async function decryptSeedPhrase(encryptedSeed: string, password: string): Promise { +export async function decryptSeedPhraseHandler( + encryptedSeed: string, + password: string, +): Promise { try { - const seedPhrase = await decryptMnemonicWithCallback({ + const seedPhrase = await decryptMnemonicWithHandler({ encryptedSeed, password, - mnemonicDecryptionHandler: decryptMnemonic, - passwordHashGenerator: generatePasswordHash, + mnemonicDecryptionHandler: decryptSeedPhrase, }); return seedPhrase; } catch (err) { diff --git a/src/app/utils/localStorage.ts b/src/app/utils/localStorage.ts index ff1cf599c..89d7e8598 100644 --- a/src/app/utils/localStorage.ts +++ b/src/app/utils/localStorage.ts @@ -1,7 +1,6 @@ const userPrefBackupRemindKey = 'UserPref:BackupRemind'; const isTermsAccepted = 'isTermsAccepted'; const hasFinishedOnboardingKey = 'hasFinishedOnboarding'; -const saltKey = 'salt'; const nonOrdinalTransferTime = 'nonOrdinalTransferTime'; export function saveMultiple(items: { [x: string]: string }) { @@ -43,14 +42,6 @@ export function getUserPrefBackupRemind(): string | null { return localStorage.getItem(userPrefBackupRemindKey); } -export function saveSalt(salt: string) { - localStorage.setItem(saltKey, salt); -} - -export function getSalt() { - return localStorage.getItem(saltKey); -} - export async function saveTimeForNonOrdinalTransferTransaction(ordinalAddress: string) { const currentTime = new Date().getTime().toString(); return localStorage.setItem(nonOrdinalTransferTime + ordinalAddress, currentTime); diff --git a/src/app/utils/mixpanel.ts b/src/app/utils/mixpanel.ts index a862fccbc..90a254ec9 100644 --- a/src/app/utils/mixpanel.ts +++ b/src/app/utils/mixpanel.ts @@ -1,6 +1,6 @@ -import mixpanel from 'mixpanel-browser'; +import { AnalyticsEvents } from '@secretkeylabs/xverse-core'; import { sha256 } from 'js-sha256'; -import { AnalyticsEvents } from '@secretkeylabs/xverse-core/types'; +import mixpanel from 'mixpanel-browser'; import { MIX_PANEL_TOKEN } from './constants'; export const isMixPanelInited = () => !!MIX_PANEL_TOKEN && !!mixpanel.config; diff --git a/src/app/utils/query.ts b/src/app/utils/query.ts index db4b2b5be..30536a666 100644 --- a/src/app/utils/query.ts +++ b/src/app/utils/query.ts @@ -15,6 +15,23 @@ export function handleRetries(failureCount: number, error: unknown): boolean { return failureCount < 3; } -export const queryClient = new QueryClient(); +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + // time before garbage collection of query data + cacheTime: 5 * 60 * 1000, // 5 min + + // increase this for specific queries to reduce refetches + staleTime: 0, + + // at least one of these are required to refetch stale queries + // refetchInterval + // refetchIntervalInBackground + refetchOnMount: true, + refetchOnWindowFocus: true, + refetchOnReconnect: true, + }, + }, +}); export const offlineStorage = createSyncStoragePersister({ storage: window.localStorage }); diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 91a7f1ecf..d7217e96c 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -198,6 +198,9 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle }; }; +const getFormattedTxIdVoutFromBundle = (bundle: Bundle) => + `${getTruncatedAddress(bundle.txid, 6)}:${bundle.vout}`; + export const getBundleId = (bundle: Bundle): string => { if ( bundle.items.length === 1 && @@ -207,7 +210,7 @@ export const getBundleId = (bundle: Bundle): string => { return bundle.items[0].number; } - return getTruncatedAddress(bundle.txid, 6); + return getFormattedTxIdVoutFromBundle(bundle); }; export const getBundleSubText = (bundle: Bundle): string => { @@ -222,7 +225,7 @@ export const getBundleSubText = (bundle: Bundle): string => { export const getBundleItemId = (bundle: Bundle, index: number): string => { const item = bundle.items[index]; if (item.type === 'unknown') { - return getTruncatedAddress(bundle.txid, 6); + return getFormattedTxIdVoutFromBundle(bundle); } if (item.type === 'inscription' || item.type === 'inscribed-sat') { return getTruncatedAddress(item.inscription.id, 6); diff --git a/src/assets/img/dashboard/swap.svg b/src/assets/img/dashboard/swap.svg deleted file mode 100644 index 8d7c39210..000000000 --- a/src/assets/img/dashboard/swap.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/assets/img/icons/ArrowSwap.svg b/src/assets/img/icons/ArrowSwap.svg new file mode 100644 index 000000000..83f58a6bc --- /dev/null +++ b/src/assets/img/icons/ArrowSwap.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/background/background.ts b/src/background/background.ts index 4c6eb5d73..36f2439fc 100755 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -5,6 +5,7 @@ import { } from '@common/utils/legacy-external-message-handler'; import { CONTENT_SCRIPT_PORT } from '@common/types/message-types'; import type { LegacyMessageFromContentScript } from '@common/types/message-types'; +import internalBackgroundMessageHandler from '@common/utils/messageHandlers'; // Listen for connection to the content-script - port for two-way communication chrome.runtime.onConnect.addListener((port) => { @@ -17,3 +18,9 @@ chrome.runtime.onConnect.addListener((port) => { } }); }); + +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + void internalBackgroundMessageHandler(message, sender, sendResponse); + // Listener fn must return `true` to indicate the response will be async + return true; +}); diff --git a/src/common/utils/messageHandlers.ts b/src/common/utils/messageHandlers.ts index 4e4bf2c59..d28e8ed64 100644 --- a/src/common/utils/messageHandlers.ts +++ b/src/common/utils/messageHandlers.ts @@ -1,4 +1,3 @@ -import { InternalMethods } from '@common/types/message-types'; import { BackgroundMessages } from 'common/types/messages'; function validateMessagesAreFromExtension(sender: chrome.runtime.MessageSender) { @@ -6,8 +5,6 @@ function validateMessagesAreFromExtension(sender: chrome.runtime.MessageSender) return sender.url?.startsWith(chrome.runtime.getURL('')); } -let inMemoryKey = ''; - async function internalBackgroundMessageHandler( message: BackgroundMessages, sender: chrome.runtime.MessageSender, @@ -16,27 +13,6 @@ async function internalBackgroundMessageHandler( if (!validateMessagesAreFromExtension(sender)) { return; } - switch (message.method) { - case InternalMethods.ShareInMemoryKeyToBackground: { - const { secretKey } = message.payload; - inMemoryKey = secretKey; - sendResponse(); - break; - } - - case InternalMethods.RequestInMemoryKeys: { - sendResponse(inMemoryKey); - break; - } - - case InternalMethods.RemoveInMemoryKeys: { - inMemoryKey = ''; - sendResponse(); - break; - } - default: - sendResponse(); - } sendResponse(); } diff --git a/src/locales/en.json b/src/locales/en.json index bfc91043e..4f09fcf17 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -269,6 +269,9 @@ "ORDINAL_NOT_OWNED": "This ordinal is not owned by your active account", "INVALID_TRANSACTION": "Invalid Transaction" }, + "INFO": { + "ADDRESS_SUPPORTS_RARE_SATS": "Make sure the recipient address supports Rare Sats." + }, "SEND_NFT": "Send NFT", "ASSOCIATED_BNS_DOMAIN": "Associated BNS Name", "SWITCH_TO": "Switch to", @@ -374,7 +377,7 @@ "SAME_FEE_ERROR": "New fee must be greater than current fee", "GREATER_FEE_ERROR": "Fee is more than available balance", "LOWER_THAN_MINIMUM": "Set fee is below minimum", - "NONCE_WARNING": "Entering an erronous nonce can result in a failed transaction. Only apply changes if you know what you are doing." + "NONCE_WARNING": "Entering an erroneous nonce can result in a failed transaction. Only apply changes if you know what you are doing." }, "TRANSACTION_STATUS": { "BROADCASTED": "Transaction Broadcasted", @@ -397,7 +400,10 @@ "TERMS_SERVICES_LINK_BUTTON": "Terms of Service", "PRIVACY_POLICY_LINK_BUTTON": "Privacy Policy", "ACCEPT_LEGAL_BUTTON": "Accept", - "AUTHORIZE_DATA_COLLECTION": "Authorize data collection" + "AUTHORIZE_DATA_COLLECTION": { + "TITLE": "Authorize data collection", + "DESCRIPTION": "We would like to collect anonymous usage data to better understand users and improve the app. You can change this setting at any time." + } }, "BACKUP_WALLET_SCREEN": { "SCREEN_TITLE": "Backup your wallet", @@ -499,7 +505,9 @@ "TITLE": "Forgot Password", "PARAGRAPH1": "Xverse does not keep a copy of your password. If you're unable to access your account, you will need to reset your wallet and input the seedphrase you used when you generated your wallet.", "PARAGRAPH2": "This will reset your wallet from this browser. Make sure you have your seed phrase backed up.", - "BACKUP_CHECKBOX_LABEL": "I backed up my seedphrase" + "BACKUP_CHECKBOX_LABEL": "I backed up my seedphrase", + "CANCEL": "Cancel", + "RESET": "Reset" }, "RESTORE_WALLET_SCREEN": { "ENTER_SEED_HEADER": "Enter your seedphrase to restore your wallet.", @@ -730,9 +738,9 @@ "THIRD_PARTY_WARNING": "You will be redirected to a third-party service provider to complete the purchase. If you encounter any issues during the process please contact the provider." }, "COIN_DASHBOARD_SCREEN": { - "SEND_COIN_BUTTON": "SEND", - "RECEIVE_COIN_BUTTON": "Receive", - "BUY_COIN_BUTTON": "Buy", + "SEND": "Send", + "RECEIVE": "Receive", + "BUY": "Buy", "TRANSACTION_HISTORY_TITLE": "Transaction history", "TRANSACTIONS_LIST_EMPTY": "No transactions found.", "TRANSACTIONS_LIST_ERROR": "Error fetching transaction history for this token", @@ -766,7 +774,6 @@ "TRANSACTIONS": "TRANSACTIONS", "CONTRACT": "CONTRACT", "COMING_SOON": "Coming soon", - "RECEIVE": "Receive", "VERIFY_ADDRESS_ON_LEDGER": "Verify address on Ledger", "VIEW_ADDRESS": "View address" }, diff --git a/src/manifest.json b/src/manifest.json index 42aba3ecd..65435f911 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -21,7 +21,7 @@ "host_permissions": ["*://*/*"], "permissions": ["storage"], "content_security_policy": { - "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; frame-src 'none'; frame-ancestors 'none';" + "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; default-src 'none'; connect-src *; style-src 'unsafe-inline'; frame-src 'none'; frame-ancestors 'none'; img-src 'self' data: https:; media-src 'self' data: https:; " }, "content_scripts": [ { diff --git a/src/pages/Options/index.tsx b/src/pages/Options/index.tsx index 3f51d54a9..e074b3451 100644 --- a/src/pages/Options/index.tsx +++ b/src/pages/Options/index.tsx @@ -1,7 +1,4 @@ import WalletCloseGuard from '@components/guards/walletCloseGuard'; -import { decryptMnemonic } from '@stacks/encryption'; -import rootStore from '@stores/index'; -import { setWalletSeedPhraseAction } from '@stores/wallet/actions/actionCreators'; import { persistQueryClient } from '@tanstack/react-query-persist-client'; import { offlineStorage, queryClient } from '@utils/query'; import { createRoot } from 'react-dom/client'; @@ -10,17 +7,8 @@ import './index.css'; declare const VERSION: string; -async function restoreSession() { - const { pHash } = await chrome.storage.session.get('pHash'); - const { walletState } = rootStore.store.getState(); - if (pHash) { - const seed = await decryptMnemonic(walletState.encryptedSeed, pHash); - rootStore.store.dispatch(setWalletSeedPhraseAction(seed)); - } -} const renderApp = async () => { - await restoreSession(); persistQueryClient({ queryClient, persister: offlineStorage, diff --git a/src/pages/Popup/index.tsx b/src/pages/Popup/index.tsx index 90eb3dfc5..3f025cce5 100644 --- a/src/pages/Popup/index.tsx +++ b/src/pages/Popup/index.tsx @@ -1,6 +1,3 @@ -import { decryptMnemonic } from '@stacks/encryption'; -import rootStore from '@stores/index'; -import { setWalletSeedPhraseAction } from '@stores/wallet/actions/actionCreators'; import { persistQueryClient } from '@tanstack/react-query-persist-client'; import { offlineStorage, queryClient } from '@utils/query'; import { createRoot } from 'react-dom/client'; @@ -9,17 +6,7 @@ import './index.css'; declare const VERSION: string; -async function restoreSession() { - const { pHash } = await chrome.storage.session.get('pHash'); - const { walletState } = rootStore.store.getState(); - if (pHash) { - const seed = await decryptMnemonic(walletState.encryptedSeed, pHash); - rootStore.store.dispatch(setWalletSeedPhraseAction(seed)); - } -} - const renderApp = async () => { - await restoreSession(); persistQueryClient({ queryClient, persister: offlineStorage, @@ -27,9 +14,6 @@ const renderApp = async () => { }); const container = document.getElementById('app'); - // We need to do this after load in order for the extension popup to have the correct height on first load - container!.style.maxHeight = '100vh'; - const root = createRoot(container!); return root.render(); }; diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 2da284a96..47da6c8e9 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -1,5 +1,8 @@ declare module '*.png'; -declare module '*.svg'; +declare module '*.svg' { + const content: string; + export default content; +} declare module '*.jpeg'; declare module '*.jpg'; declare module '*.otf'; diff --git a/src/theme/index.ts b/src/theme/index.ts index 10cd318c9..8414ae6c5 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -51,6 +51,7 @@ const Theme = { white_800: 'rgba(255, 255, 255, 0.2)', white_850: 'rgba(255, 255, 255, 0.15)', white_900: 'rgba(255, 255, 255, 0.1)', + elevation_n1: '#0C0C0C', elevation0: '#181818', elevation1: '#1E2024', @@ -61,8 +62,6 @@ const Theme = { elevation6_600: 'rgba(76, 82, 95, 0.4)', elevation6_800: 'rgba(76, 82, 95, 0.2)', elevation8: '#7A7688', - success: '#51D6A6', - error: '#D33C3C', // feedback danger_light: '#FF5A5A', @@ -78,54 +77,184 @@ const Theme = { caution: '#F2A900', caution_800: 'rgba(242, 169, 0, 0.2)', - // TODO tim: grep codebase and remove all - /* deprecated: below */ + // brand + emerald_light: '#55B86E', + emerald: '#49A15F', + emerald_dark: '#3E8A51', + tangerine_light: '#EF883B', + tangerine: '#EE7A30', + tangerine_dark: '#D96F2A', + lilac_light: '#6E54CB', + lilac: '#5E41C5', + lilac_dark: '#4F34BA', + action: { + /** + * @deprecated + */ classic: '#FFFFFF', + + /** + * @deprecated + */ classicLight: 'rgba(255, 255, 255, 0.85)', + + /** + * @deprecated + */ classic800: 'rgba(85, 101, 247, 0.2)', }, white: { + /** + * @deprecated use theme.colors.white_0 + */ 0: '#FFFFFF', + + /** + * @deprecated use theme.colors.white_200 + */ 200: 'rgba(255, 255, 255, 0.8)', + + /** + * @deprecated use theme.colors.white_400 + */ 400: 'rgba(255, 255, 255, 0.6)', + + /** + * @deprecated use theme.colors.white_600 + */ 600: 'rgba(255, 255, 255, 0.4)', + + /** + * @deprecated use theme.colors.white_800 + */ 800: 'rgba(255, 255, 255, 0.2)', + + /** + * @deprecated use theme.colors.white_850 + */ 850: 'rgba(255, 255, 255, 0.15)', + + /** + * @deprecated use theme.colors.white_900 + */ 900: 'rgba(255, 255, 255, 0.1)', }, background: { + /** + * @deprecated use theme.colors.elevation + */ elevation_n1: '#0C0C0C', + + /** + * @deprecated use theme.colors.elevation + */ elevation0: '#181818', + + /** + * @deprecated use theme.colors.elevation + */ elevation1: '#1E2024', - elevation_1: '#1E2024', // deprecated + + /** + * @deprecated use theme.colors.elevation + */ + elevation_1: '#1E2024', + + /** + * @deprecated use theme.colors.elevation + */ elevation2: '#24282F', + + /** + * @deprecated use theme.colors.elevation + */ elevation3: '#2A2F39', + + /** + * @deprecated use theme.colors.elevation + */ elevation5: '#303643', + + /** + * @deprecated use theme.colors.elevation + */ elevation6: '#4C525F', + + /** + * @deprecated use theme.colors.elevation + */ elevation6_600: 'rgba(76, 82, 95, 0.4)', + + /** + * @deprecated use theme.colors.elevation + */ elevation6_800: 'rgba(76, 82, 95, 0.2)', + + /** + * @deprecated use theme.colors.elevation + */ elevation8: '#7A7688', - elevation9: 'rgba(76, 81, 135, 0.2)', // deprecated - elevation10: 'rgba(76, 81, 135, 0.35)', // deprecated + + /** + * @deprecated + */ + elevation9: 'rgba(76, 81, 135, 0.2)', + + /** + * @deprecated + */ + elevation10: 'rgba(76, 81, 135, 0.35)', + modalBackdrop: 'rgba(18,21,30,0.6)', modalBackdrop2: 'rgba(18, 21, 30, 0.90)', selectBackground: 'linear-gradient(0deg, rgba(115, 131, 255, 0.05), rgba(115, 131, 255, 0.05)), #1D2032', }, + + /** + * @deprecated + */ border: { select: 'rgba(115, 131, 255, 0.4)', }, + feedback: { - success: '#51D6A6', + /** + * @deprecated use theme.colors.success_medium + */ + success: '#55B86E', + + /** + * @deprecated use theme.colors.caution + */ caution: '#F2A900', - error: '#D33C3C', - error_700: 'rgba(211, 60, 60, 0.3)', + + /** + * @deprecated use theme.colors.danger_medium + */ + error: '#EA4848', + + /** + * @deprecated use theme.colors.danger_dark_600 + */ + error_700: 'rgba(171, 48, 48, 0.4)', }, + + /** + * @deprecated + */ grey: '#24252C', + + /** + * @deprecated use lilac + */ purple_main: '#5E41C5', + + /** + * @deprecated use lilac + */ orange_main: '#EE7A30', - /* above: deprecated */ }, /* @@ -255,8 +384,9 @@ const Theme = { }, }, - // TODO tim: grep codebase and remove all - /* deprecated: below */ + /** + * @deprecated use theme.typography + */ headline_category_m: { fontFamily: 'DMSans-Medium', fontStyle: 'normal', @@ -265,6 +395,10 @@ const Theme = { letterSpacing: 0.02, textTransform: 'uppercase', }, + + /** + * @deprecated use theme.typography + */ headline_category_s: { fontFamily: 'DMSans-Medium', fontStyle: 'normal', @@ -272,60 +406,100 @@ const Theme = { fontSize: 11, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ body_bold_l: { fontFamily: 'DMSans-Bold', fontStyle: 'normal', fontWeight: '700', fontSize: 16, }, + + /** + * @deprecated use theme.typography + */ body_medium_l: { fontFamily: 'DMSans-Regular', fontStyle: 'normal', fontWeight: '500', fontSize: 16, }, + + /** + * @deprecated use theme.typography + */ body_l: { fontFamily: 'DMSans-Regular', fontStyle: 'normal', fontWeight: '400', fontSize: 16, }, + + /** + * @deprecated use theme.typography + */ body_bold_m: { fontFamily: 'DMSans-Bold', fontStyle: 'normal', fontWeight: '700', fontSize: 14, }, + + /** + * @deprecated use theme.typography + */ body_medium_m: { fontFamily: 'DMSans-Medium', fontStyle: 'normal', fontWeight: '500', fontSize: 14, }, + + /** + * @deprecated use theme.typography + */ body_m: { fontFamily: 'DMSans-Regular', fontStyle: 'normal', fontWeight: '400', fontSize: 14, }, + + /** + * @deprecated use theme.typography + */ body_medium_s: { fontFamily: 'DMSans-Medium', fontStyle: 'normal', fontWeight: '500', fontSize: 12, }, + + /** + * @deprecated use theme.typography + */ body_s: { fontFamily: 'DMSans-Regular', fontStyle: 'normal', fontWeight: '400', fontSize: 12, }, + + /** + * @deprecated use theme.typography.body_s + */ body_xs: { fontFamily: 'DMSans-Regular', fontStyle: 'normal', fontWeight: '400', fontSize: 12, }, + + /** + * @deprecated use theme.typography + */ headline_xl: { fontFamily: 'IBMPlexSans-Regular', fontStyle: 'normal', @@ -333,6 +507,10 @@ const Theme = { fontSize: 42, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ tile_text: { fontFamily: 'Satoshi-Regular', fontStyle: 'normal', @@ -340,6 +518,10 @@ const Theme = { fontSize: 18, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ bold_tile_text: { fontFamily: 'Satoshi-Bold', fontStyle: 'normal', @@ -347,6 +529,10 @@ const Theme = { fontSize: 18, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ headline_l: { fontFamily: 'IBMPlexSans-Bold', fontStyle: 'normal', @@ -354,6 +540,10 @@ const Theme = { fontSize: 34, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ headline_m: { fontFamily: 'IBMPlexSans-Bold', fontStyle: 'normal', @@ -361,6 +551,10 @@ const Theme = { fontSize: 24, letterSpacing: 0.02, }, + + /** + * @deprecated use theme.typography + */ headline_s: { fontFamily: 'IBMPlexSans-Medium', fontStyle: 'normal', @@ -368,7 +562,6 @@ const Theme = { fontSize: 21, letterSpacing: 0.02, }, - /* above: deprecated */ }; export type Color = keyof typeof Theme.colors | 'currentColor'; From ec8d5602c4307eda471db1341cbf38f7d5243e56 Mon Sep 17 00:00:00 2001 From: fede erbes Date: Fri, 17 Nov 2023 11:22:32 +0100 Subject: [PATCH 09/28] feat: add new sattributes to rarity scale screen (#54) * feat: add new sattributes to rarity scale screen * chore: remove PALINCEPTION and PURE_PALINCEPTION * chore: replace icons and color for epic, rare and uncommon --- .../components/rareSatIcon/rareSatIcon.tsx | 55 ++++++++++++- .../nftDashboard/supportedRarities/index.tsx | 19 +++-- .../supportedRarities/rarityTile.tsx | 40 ++-------- src/app/utils/constants.ts | 2 - src/app/utils/rareSats.ts | 62 ++++++++++++--- .../img/nftDashboard/rareSats/1d_pali.svg | 9 +++ .../img/nftDashboard/rareSats/2d_pali.svg | 9 +++ .../img/nftDashboard/rareSats/3d_pali.svg | 9 +++ .../img/nftDashboard/rareSats/alpha.svg | 9 +++ .../img/nftDashboard/rareSats/black_epic.svg | 9 +++ .../nftDashboard/rareSats/black_legendary.svg | 10 +++ .../img/nftDashboard/rareSats/black_rare.svg | 7 ++ .../nftDashboard/rareSats/black_uncommon.svg | 8 ++ .../img/nftDashboard/rareSats/block_78.svg | 9 +++ .../img/nftDashboard/rareSats/block_9.svg | 9 +++ .../img/nftDashboard/rareSats/block_pali.svg | 9 +++ src/assets/img/nftDashboard/rareSats/epic.svg | 16 ++-- .../rareSats/fibonacci_sequence.svg | 9 +++ .../rareSats/first_transaction_silkroad.svg | 9 +++ .../img/nftDashboard/rareSats/hitman.svg | 9 +++ src/assets/img/nftDashboard/rareSats/jpeg.svg | 9 +++ .../img/nftDashboard/rareSats/nakamoto.svg | 6 ++ .../img/nftDashboard/rareSats/omega.svg | 4 + .../nftDashboard/rareSats/palinception.svg | 9 +++ .../img/nftDashboard/rareSats/palindrome.svg | 17 ++++ .../img/nftDashboard/rareSats/pizza.svg | 20 +++++ src/assets/img/nftDashboard/rareSats/rare.svg | 12 +-- .../nftDashboard/rareSats/sequence_pali.svg | 9 +++ .../img/nftDashboard/rareSats/uncommon.svg | 14 ++-- .../img/nftDashboard/rareSats/vintage.svg | 22 ++++++ src/locales/en.json | 79 +++++++++++++++---- 31 files changed, 422 insertions(+), 97 deletions(-) create mode 100644 src/assets/img/nftDashboard/rareSats/1d_pali.svg create mode 100644 src/assets/img/nftDashboard/rareSats/2d_pali.svg create mode 100644 src/assets/img/nftDashboard/rareSats/3d_pali.svg create mode 100644 src/assets/img/nftDashboard/rareSats/alpha.svg create mode 100644 src/assets/img/nftDashboard/rareSats/black_epic.svg create mode 100644 src/assets/img/nftDashboard/rareSats/black_legendary.svg create mode 100644 src/assets/img/nftDashboard/rareSats/black_rare.svg create mode 100644 src/assets/img/nftDashboard/rareSats/black_uncommon.svg create mode 100644 src/assets/img/nftDashboard/rareSats/block_78.svg create mode 100644 src/assets/img/nftDashboard/rareSats/block_9.svg create mode 100644 src/assets/img/nftDashboard/rareSats/block_pali.svg create mode 100644 src/assets/img/nftDashboard/rareSats/fibonacci_sequence.svg create mode 100644 src/assets/img/nftDashboard/rareSats/first_transaction_silkroad.svg create mode 100644 src/assets/img/nftDashboard/rareSats/hitman.svg create mode 100644 src/assets/img/nftDashboard/rareSats/jpeg.svg create mode 100644 src/assets/img/nftDashboard/rareSats/nakamoto.svg create mode 100644 src/assets/img/nftDashboard/rareSats/omega.svg create mode 100644 src/assets/img/nftDashboard/rareSats/palinception.svg create mode 100644 src/assets/img/nftDashboard/rareSats/palindrome.svg create mode 100644 src/assets/img/nftDashboard/rareSats/pizza.svg create mode 100644 src/assets/img/nftDashboard/rareSats/sequence_pali.svg create mode 100644 src/assets/img/nftDashboard/rareSats/vintage.svg diff --git a/src/app/components/rareSatIcon/rareSatIcon.tsx b/src/app/components/rareSatIcon/rareSatIcon.tsx index def1d41f5..43146eab1 100644 --- a/src/app/components/rareSatIcon/rareSatIcon.tsx +++ b/src/app/components/rareSatIcon/rareSatIcon.tsx @@ -1,9 +1,31 @@ +import OneDPali from '@assets/img/nftDashboard/rareSats/1d_pali.svg'; +import TwoDPali from '@assets/img/nftDashboard/rareSats/2d_pali.svg'; +import ThreeDPali from '@assets/img/nftDashboard/rareSats/3d_pali.svg'; +import Alpha from '@assets/img/nftDashboard/rareSats/alpha.svg'; +import BlackEpic from '@assets/img/nftDashboard/rareSats/black_epic.svg'; +import BlackLegendary from '@assets/img/nftDashboard/rareSats/black_legendary.svg'; +import BlackRare from '@assets/img/nftDashboard/rareSats/black_rare.svg'; +import BlackUncommon from '@assets/img/nftDashboard/rareSats/black_uncommon.svg'; +import Block78 from '@assets/img/nftDashboard/rareSats/block_78.svg'; +import Block9 from '@assets/img/nftDashboard/rareSats/block_9.svg'; +import BlockPali from '@assets/img/nftDashboard/rareSats/block_pali.svg'; import Epic from '@assets/img/nftDashboard/rareSats/epic.svg'; +import FibonacciSequence from '@assets/img/nftDashboard/rareSats/fibonacci_sequence.svg'; +import FirstTransactionSilkroad from '@assets/img/nftDashboard/rareSats/first_transaction_silkroad.svg'; +import Hitman from '@assets/img/nftDashboard/rareSats/hitman.svg'; +import Jpeg from '@assets/img/nftDashboard/rareSats/jpeg.svg'; import Legendary from '@assets/img/nftDashboard/rareSats/legendary.svg'; import Mythic from '@assets/img/nftDashboard/rareSats/mythic.svg'; +import Nakamoto from '@assets/img/nftDashboard/rareSats/nakamoto.svg'; +import Omega from '@assets/img/nftDashboard/rareSats/omega.svg'; +import Palinception from '@assets/img/nftDashboard/rareSats/palinception.svg'; +import Palindrome from '@assets/img/nftDashboard/rareSats/palindrome.svg'; +import Pizza from '@assets/img/nftDashboard/rareSats/pizza.svg'; import Rare from '@assets/img/nftDashboard/rareSats/rare.svg'; +import SequencePali from '@assets/img/nftDashboard/rareSats/sequence_pali.svg'; import Uncommon from '@assets/img/nftDashboard/rareSats/uncommon.svg'; import Unknown from '@assets/img/nftDashboard/rareSats/unknown.svg'; +import Vintage from '@assets/img/nftDashboard/rareSats/vintage.svg'; import { getRareSatsColorsByRareSatsType, RareSatsType } from '@utils/rareSats'; import styled from 'styled-components'; @@ -77,9 +99,40 @@ function RareSatIcon({ rare: Rare, uncommon: Uncommon, unknown: Unknown, + BLACK_LEGENDARY: BlackLegendary, + BLACK_EPIC: BlackEpic, + BLACK_RARE: BlackRare, + BLACK_UNCOMMON: BlackUncommon, + FIBONACCI: FibonacciSequence, + '1D_PALINDROME': OneDPali, + '2D_PALINDROME': TwoDPali, + '3D_PALINDROME': ThreeDPali, + SEQUENCE_PALINDROME: SequencePali, + PERFECT_PALINCEPTION: Palinception, + PALIBLOCK_PALINDROME: BlockPali, + PALINDROME: Palindrome, + NAME_PALINDROME: Palindrome, + ALPHA: Alpha, + OMEGA: Omega, + FIRST_TRANSACTION: FirstTransactionSilkroad, + BLOCK9: Block9, + BLOCK78: Block78, + NAKAMOTO: Nakamoto, + VINTAGE: Vintage, + PIZZA: Pizza, + JPEG: Jpeg, + HITMAN: Hitman, + SILK_ROAD: FirstTransactionSilkroad, }[type]; + if (!src) { + return null; + } const backgroundColor = bgColor ? Theme.colors.background[bgColor] : 'transparent'; - const { color, backgroundColor: outerColor } = getRareSatsColorsByRareSatsType(type); + const { color, backgroundColor: outerColor } = getRareSatsColorsByRareSatsType(type) ?? { + color: 'transparent', + backgroundColor: 'transparent', + }; + return ( diff --git a/src/app/screens/nftDashboard/supportedRarities/index.tsx b/src/app/screens/nftDashboard/supportedRarities/index.tsx index 43cd55e69..8b429aecc 100644 --- a/src/app/screens/nftDashboard/supportedRarities/index.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/index.tsx @@ -1,12 +1,11 @@ -import { useTranslation } from 'react-i18next'; -import { ArrowUpRight } from '@phosphor-icons/react'; -import styled from 'styled-components'; import TopRow from '@components/topRow'; -import { useNavigate } from 'react-router-dom'; +import { ArrowUpRight } from '@phosphor-icons/react'; import { StyledP } from '@ui-library/common.styled'; -import { RareSats } from '@utils/rareSats'; -import { useMemo } from 'react'; import { BLOG_LINK } from '@utils/constants'; +import { RareSats } from '@utils/rareSats'; +import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; import Theme from 'theme'; import RarityTile from './rarityTile'; @@ -51,16 +50,16 @@ const MainContainer = styled.div({ flexDirection: 'column', alignItems: 'center', width: '100%', - height: '100%', + backgroundColor: Theme.colors.elevation0, }); const rarityTypes = RareSats.filter((rareSat) => rareSat !== 'common'); function SupportedRarities() { const navigate = useNavigate(); - const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); + const { t } = useTranslation('translation', { keyPrefix: 'RARE_SATS' }); - const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const openLearnMoreLink = () => window.open(`${BLOG_LINK}/rare-satoshis`, '_blank', 'noopener,noreferrer'); @@ -80,7 +79,7 @@ function SupportedRarities() { {t('RARITY_DETAIL.LEARN_MORE')} - + diff --git a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx index dd5acb1a2..bc7e2c2df 100644 --- a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx @@ -1,11 +1,7 @@ +import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; +import { getRareSatsLabelByType, RareSatsType } from '@utils/rareSats'; import { useTranslation } from 'react-i18next'; -import { ArrowUpRight } from '@phosphor-icons/react'; import styled from 'styled-components'; -import { RareSatsType } from '@utils/rareSats'; -import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { MAGISAT_IO_RARITY_SCAN_URL } from '@utils/constants'; -import Theme from 'theme'; const Container = styled.div((props) => ({ display: 'flex', @@ -25,27 +21,13 @@ const TextsColumn = styled.div((props) => ({ const RarityText = styled.p((props) => ({ ...props.theme.typography.body_bold_m, - color: props.theme.colors.white[0], + color: props.theme.colors.white_0, textTransform: 'capitalize', })); const RarityDetailText = styled.p((props) => ({ ...props.theme.typography.body_medium_m, - color: props.theme.colors.white[200], -})); - -const ButtonText = styled.p((props) => ({ - ...props.theme.typography.body_medium_m, - color: props.theme.colors.orange_main, - marginRight: props.theme.spacing(2), -})); - -const ButtonImage = styled.button((props) => ({ - backgroundColor: 'transparent', - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - marginTop: props.theme.spacing(2), + color: props.theme.colors.white_200, })); interface Props { @@ -53,24 +35,14 @@ interface Props { } function RarityTile({ type }: Props) { - const { ordinalsAddress } = useWalletSelector(); - const { t } = useTranslation('translation', { keyPrefix: 'NFT_DASHBOARD_SCREEN' }); - - const openScanLink = () => - window.open(`${MAGISAT_IO_RARITY_SCAN_URL}${ordinalsAddress}`, '_blank', 'noopener,noreferrer'); + const { t } = useTranslation('translation', { keyPrefix: 'RARE_SATS' }); return ( - {type} + {getRareSatsLabelByType(type)} {t(`RARITY_DETAIL.${type.toUpperCase()}`)} - {type === 'unknown' && ( - - {t('RARITY_DETAIL.SCAN')} - - - )} ); diff --git a/src/app/utils/constants.ts b/src/app/utils/constants.ts index 9af30e56d..b8a63a8d3 100644 --- a/src/app/utils/constants.ts +++ b/src/app/utils/constants.ts @@ -22,8 +22,6 @@ export const XVERSE_WEB_POOL_URL = 'https://pool.xverse.app'; export const XVERSE_ORDIVIEW_URL = (network: NetworkType) => `https://ord${network === 'Mainnet' ? '' : '-testnet'}.xverse.app`; -export const MAGISAT_IO_RARITY_SCAN_URL = 'https://magisat.io/wallet?walletAddress='; - export const TRANSAC_URL = 'https://global.transak.com'; export const TRANSAC_API_KEY = process.env.TRANSAC_API_KEY; export const MOON_PAY_URL = 'https://buy.moonpay.com'; diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index d7217e96c..0e883eef2 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -1,14 +1,50 @@ import { t } from 'i18next'; import { getTruncatedAddress } from './helper'; -const RoadArmorRareSats = ['uncommon', 'rare', 'epic', 'legendary', 'mythic', 'common'] as const; +export const RoadArmorRareSats = [ + 'mythic', + 'legendary', + 'epic', + 'rare', + 'uncommon', + 'common', +] as const; export type RoadArmorRareSatsType = (typeof RoadArmorRareSats)[number]; -export const RareSats = ['unknown', ...RoadArmorRareSats] as const; +export const Sattributes = [ + 'BLACK_LEGENDARY', + 'BLACK_EPIC', + 'BLACK_RARE', + 'BLACK_UNCOMMON', + 'FIBONACCI', + '1D_PALINDROME', + '2D_PALINDROME', + '3D_PALINDROME', + 'SEQUENCE_PALINDROME', + 'PERFECT_PALINCEPTION', + 'PALIBLOCK_PALINDROME', + 'PALINDROME', + 'NAME_PALINDROME', + 'ALPHA', + 'OMEGA', + 'FIRST_TRANSACTION', + 'BLOCK9', + 'BLOCK78', + 'NAKAMOTO', + 'VINTAGE', + 'PIZZA', + 'JPEG', + 'HITMAN', + 'SILK_ROAD', +] as const; +export type SattributesType = (typeof Sattributes)[number]; + +// TODO: remove unknown and unify with common +export const RareSats = [...RoadArmorRareSats, 'unknown', ...Sattributes] as const; export type RareSatsType = (typeof RareSats)[number]; export const getRareSatsLabelByType = (type: RareSatsType) => - t(`RARE_SATS.RARE_TYPES.${type.toUpperCase()}`); + t(`RARE_SATS.RARITY_LABEL.${type.toUpperCase()}`); export type SatType = 'inscription' | 'rare-sat' | 'inscribed-sat' | 'unknown'; @@ -45,31 +81,31 @@ export const getRareSatsColorsByRareSatsType = (rareSatsType: RareSatsType) => ({ unknown: { color: 'rgb(175,186,189)', - backgroundColor: 'rgba(175,186,189,0.15)', + backgroundColor: 'rgba(175,186,189,0.20)', }, uncommon: { - color: 'rgb(0,218,182)', - backgroundColor: 'rgba(0,218,182,0.15)', + color: 'rgb(215, 105, 254)', + backgroundColor: 'rgba(215, 105, 254, 0.20)', }, rare: { - color: 'rgb(100,196,246)', - backgroundColor: 'rgba(100,196,246,0.15)', + color: 'rgb(131, 113, 242)', + backgroundColor: 'rgba(131, 113, 242, 0.20)', }, epic: { - color: 'rgb(182,105,254)', - backgroundColor: 'rgba(182,105,254,0.15)', + color: 'rgb(145, 226, 96)', + backgroundColor: 'rgba(145, 226, 96, 0.20)', }, legendary: { color: 'rgb(255,205,120)', - backgroundColor: 'rgba(255,205,120,0.15)', + backgroundColor: 'rgba(255,205,120,0.20)', }, mythic: { color: 'rgb(255,244,203)', - backgroundColor: 'rgba(255,244,203, 0.15)', + backgroundColor: 'rgba(255,244,203, 0.20)', }, common: { color: 'rgb(216,216,216)', - backgroundColor: 'rgba(216,216,216,0.15)', + backgroundColor: 'rgba(216,216,216,0.20)', }, }[rareSatsType ?? 'common']); diff --git a/src/assets/img/nftDashboard/rareSats/1d_pali.svg b/src/assets/img/nftDashboard/rareSats/1d_pali.svg new file mode 100644 index 000000000..d8b6cceec --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/1d_pali.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/2d_pali.svg b/src/assets/img/nftDashboard/rareSats/2d_pali.svg new file mode 100644 index 000000000..29117d3f1 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/2d_pali.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/3d_pali.svg b/src/assets/img/nftDashboard/rareSats/3d_pali.svg new file mode 100644 index 000000000..122851258 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/3d_pali.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/alpha.svg b/src/assets/img/nftDashboard/rareSats/alpha.svg new file mode 100644 index 000000000..612fb5d2b --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/alpha.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/black_epic.svg b/src/assets/img/nftDashboard/rareSats/black_epic.svg new file mode 100644 index 000000000..fa2dc2102 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/black_epic.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/black_legendary.svg b/src/assets/img/nftDashboard/rareSats/black_legendary.svg new file mode 100644 index 000000000..f5f6ba4ef --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/black_legendary.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/black_rare.svg b/src/assets/img/nftDashboard/rareSats/black_rare.svg new file mode 100644 index 000000000..292974198 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/black_rare.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/black_uncommon.svg b/src/assets/img/nftDashboard/rareSats/black_uncommon.svg new file mode 100644 index 000000000..016063156 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/black_uncommon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/block_78.svg b/src/assets/img/nftDashboard/rareSats/block_78.svg new file mode 100644 index 000000000..df22e9a77 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/block_78.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/block_9.svg b/src/assets/img/nftDashboard/rareSats/block_9.svg new file mode 100644 index 000000000..1ca053006 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/block_9.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/block_pali.svg b/src/assets/img/nftDashboard/rareSats/block_pali.svg new file mode 100644 index 000000000..453c76441 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/block_pali.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/epic.svg b/src/assets/img/nftDashboard/rareSats/epic.svg index 5efdf652e..b5267895a 100644 --- a/src/assets/img/nftDashboard/rareSats/epic.svg +++ b/src/assets/img/nftDashboard/rareSats/epic.svg @@ -1,9 +1,9 @@ - - - - - - - - + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/fibonacci_sequence.svg b/src/assets/img/nftDashboard/rareSats/fibonacci_sequence.svg new file mode 100644 index 000000000..20d232759 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/fibonacci_sequence.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/first_transaction_silkroad.svg b/src/assets/img/nftDashboard/rareSats/first_transaction_silkroad.svg new file mode 100644 index 000000000..da992764c --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/first_transaction_silkroad.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/hitman.svg b/src/assets/img/nftDashboard/rareSats/hitman.svg new file mode 100644 index 000000000..544415779 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/hitman.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/jpeg.svg b/src/assets/img/nftDashboard/rareSats/jpeg.svg new file mode 100644 index 000000000..537c084dc --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/jpeg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/nakamoto.svg b/src/assets/img/nftDashboard/rareSats/nakamoto.svg new file mode 100644 index 000000000..82cce4dc7 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/nakamoto.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/omega.svg b/src/assets/img/nftDashboard/rareSats/omega.svg new file mode 100644 index 000000000..b356cc15b --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/omega.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/img/nftDashboard/rareSats/palinception.svg b/src/assets/img/nftDashboard/rareSats/palinception.svg new file mode 100644 index 000000000..c51b51469 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/palinception.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/palindrome.svg b/src/assets/img/nftDashboard/rareSats/palindrome.svg new file mode 100644 index 000000000..ac568fc3c --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/palindrome.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/pizza.svg b/src/assets/img/nftDashboard/rareSats/pizza.svg new file mode 100644 index 000000000..122cc7204 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/pizza.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/rare.svg b/src/assets/img/nftDashboard/rareSats/rare.svg index 452b9a55c..4b00d56d9 100644 --- a/src/assets/img/nftDashboard/rareSats/rare.svg +++ b/src/assets/img/nftDashboard/rareSats/rare.svg @@ -1,7 +1,7 @@ - - - - - - + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/sequence_pali.svg b/src/assets/img/nftDashboard/rareSats/sequence_pali.svg new file mode 100644 index 000000000..e5168f27d --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/sequence_pali.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/uncommon.svg b/src/assets/img/nftDashboard/rareSats/uncommon.svg index 257ee10ba..9582059b4 100644 --- a/src/assets/img/nftDashboard/rareSats/uncommon.svg +++ b/src/assets/img/nftDashboard/rareSats/uncommon.svg @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + diff --git a/src/assets/img/nftDashboard/rareSats/vintage.svg b/src/assets/img/nftDashboard/rareSats/vintage.svg new file mode 100644 index 000000000..51ad3ade9 --- /dev/null +++ b/src/assets/img/nftDashboard/rareSats/vintage.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/locales/en.json b/src/locales/en.json index 4f09fcf17..efbc22bb8 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -565,19 +565,6 @@ "VERIFY_ADDRESS_ON_LEDGER": "Verify address on Ledger", "VIEW_ADDRESS": "View address", "ADD_STACKS_ADDRESS": "Add a Stacks address", - "RARITY_DETAIL": { - "TOP_TEXT": "Currently, only the default rarity scale is supported. Your sats could have other attributes.", - "LEARN_MORE": "Learn more", - "UNKNOWN": "A sat of unknown rarity.", - "UNCOMMON": "The first sat of each block.", - "RARE": "The first sat of each difficulty adjustment period.", - "EPIC": "The first sat of each halving epoch.", - "LEGENDARY": "The first sat of each cycle.", - "MYTHIC": "The first sat of the genesis block.", - "SCAN": "Scan for custom attributes", - "SUPPORTED_RARITIES": "Supported rarities", - "RARITY_INFO": "Currently, only the default rarity scale is supported. Your sats could have other attributes." - }, "NFTS": "NFTs", "RARE_SATS": "Rare Sats", "NEW_FEATURE": "New Feature, Rare Sats", @@ -1081,14 +1068,74 @@ "LEARN_MORE": "Learn more" }, "RARE_SATS": { - "RARE_TYPES": { - "UNKNOWN": "Unknown", + "RARITY_LABEL": { + "UNKNOWN": "Common/Unknown", "UNCOMMON": "Uncommon", "COMMON": "Common", "RARE": "Rare", "EPIC": "Epic", "LEGENDARY": "Legendary", - "MYTHIC": "Mythic" + "MYTHIC": "Mythic", + "BLACK_LEGENDARY": "Black Legendary", + "BLACK_EPIC": "Black Epic", + "BLACK_RARE": "Black Rare", + "BLACK_UNCOMMON": "Black Uncommon", + "FIBONACCI": "Fibonacci Sequence", + "1D_PALINDROME": "1D Pali", + "2D_PALINDROME": "2D Pali", + "3D_PALINDROME": "3D Pali", + "SEQUENCE_PALINDROME": "Sequence Pali", + "PERFECT_PALINCEPTION": "Perfect Paliception", + "PALIBLOCK_PALINDROME": "Block Pali", + "PALINDROME": "Palindrome", + "NAME_PALINDROME": "Name Palindrome", + "ALPHA": "Alpha", + "OMEGA": "Omega", + "FIRST_TRANSACTION": "First transaction", + "BLOCK9": "Block 9", + "BLOCK78": "Block 78", + "NAKAMOTO": "Nakamoto", + "VINTAGE": "Vintage", + "PIZZA": "Pizza", + "JPEG": "Jpeg", + "HITMAN": "Hitman", + "SILK_ROAD": "Silkroad" + }, + "RARITY_DETAIL": { + "TOP_TEXT": "Currently, only the default rarity scale is supported. Your sats could have other attributes.", + "LEARN_MORE": "Learn more", + "RARITY_INFO": "Currently, only the default rarity scale is supported. Your sats could have other attributes.", + "SUPPORTED_RARITIES": "Supported rarities", + "MYTHIC": "The first sat of the genesis block.", + "LEGENDARY": "The first sat of each cycle.", + "EPIC": "The first sat of each halving epoch.", + "RARE": "The first sat of each difficulty adjustment period.", + "UNCOMMON": "The first sat of each block.", + "UNKNOWN": "A sat of unknown rarity.", + "BLACK_LEGENDARY": "The last sat of each cycle.", + "BLACK_EPIC": "The last sat of each halving epoch.", + "BLACK_RARE": "The last sat of each difficulty adjustment period.", + "BLACK_UNCOMMON": "The last sat of each block.", + "FIBONACCI": "Sats with IDs that follow the Fibonacci Sequence.", + "1D_PALINDROME": "Sats with number composed of only 1 digit (ex: 888888888888).", + "2D_PALINDROME": "Sats with palindromic number, composed of only 2 digit (ex: 8888822288888).", + "3D_PALINDROME": "Sats with palindromic number, composed of only 3 digit (ex: 8885522255888).", + "SEQUENCE_PALINDROME": "Sats with palindromic number, and a sequence of at least 3 consecutive identical digits (ex: 3275433345723).", + "PERFECT_PALINCEPTION": "Sats with palindromic number made of a subsequence which is also a palindrome of at least 2 distinct digits", + "PALIBLOCK_PALINDROME": "Sats with palindromic number, in a block with a palindromic number.", + "PALINDROME": "Sats with palindromic number (ex: 3275431345723)", + "NAME_PALINDROME": "Sats with palindromic names (ex: abcba)", + "ALPHA": "The first sats in each bitcoin. They always end in at least 8 zeros.", + "OMEGA": "The last sats in each bitcoin. They always end in at least 8 nines.", + "FIRST_TRANSACTION": "Sats from the 10 bitcoins Satoshi Nakamoto sent Hal Finney in the first bitcoin transaction.", + "BLOCK9": "Sats mined in Block 9 (the first block with sats circulating today).", + "BLOCK78": "Sats mined by Hal Finney in Block 78 (the first block mined by someone other than Satoshi).", + "NAKAMOTO": "Sats mined by Satoshi Nakamoto himself.", + "VINTAGE": "Sats mined in the first 1000 bitcoin blocks.", + "PIZZA": "Sats involved in the famous pizza transaction from 2010.", + "JPEG": "Sats involved in the possible first bitcoin trade for an image on February 24, 2010.", + "HITMAN": "Sats involved the transaction made by Ross Ulbricht to hire a hitman.", + "SILK_ROAD": "Sats seized from Silk Road and auctioned off on June 27, 2014 by US Marshals." }, "SAT_TYPES": { "RARE_SAT": "{{type}} Sat", From 2fd63a5e4b6f0305ac91cdacb5436c558a9cd6ab Mon Sep 17 00:00:00 2001 From: fede erbes Date: Tue, 21 Nov 2023 18:33:11 +0100 Subject: [PATCH 10/28] chore: add mock data and local storage values for testing and mapRareSatsAPIResponseToRareSatsV2 method to map the response for v2 api (#56) * chore: add mock data and local storage values for testing and mapRareSatsAPIResponseToRareSatsV2 method to map the response for v2 api * chore: add localstorage value to use prod api * feat: rare sats tab UI (#57) * feat: rare sats tab UI * fix: gallery view UI * fix: icons * fix: thousand separator --------- Co-authored-by: Abdul Haseeb --- .../components/rareSatAsset/rareSatAsset.tsx | 2 +- .../components/rareSatIcon/rareSatIcon.tsx | 14 +- .../ordinals/tempAddressRareSatsMock.ts | 280 ++++++++++++++++++ .../queries/ordinals/useAddressRareSats.ts | 103 ++++++- .../screens/nftDashboard/collectiblesTabs.tsx | 25 +- src/app/screens/nftDashboard/index.tsx | 6 +- .../nftDashboard/inscriptionsTabGridItem.tsx | 2 +- .../nftDashboard/rareSatsTabGridItem.tsx | 167 ++++++++--- src/app/utils/inscriptions.ts | 2 +- src/app/utils/rareSats.ts | 142 +++++++-- src/assets/img/rareSats/ic_ordinal_small.svg | 6 + 11 files changed, 677 insertions(+), 72 deletions(-) create mode 100644 src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts create mode 100644 src/assets/img/rareSats/ic_ordinal_small.svg diff --git a/src/app/components/rareSatAsset/rareSatAsset.tsx b/src/app/components/rareSatAsset/rareSatAsset.tsx index 2915738ae..62e05b485 100644 --- a/src/app/components/rareSatAsset/rareSatAsset.tsx +++ b/src/app/components/rareSatAsset/rareSatAsset.tsx @@ -55,7 +55,7 @@ function RareSatAsset({ item, isCollage = false }: Props) { {isInscription ? ( - {!isCollage && !!item.rarity_ranking && item.rarity_ranking !== 'common' && ( + {!isCollage && !!item.rarity_ranking && item.rarity_ranking !== 'COMMON' && ( 360; const src = { - epic: Epic, - legendary: Legendary, - mythic: Mythic, - rare: Rare, - uncommon: Uncommon, - unknown: Unknown, + EPIC: Epic, + LEGENDARY: Legendary, + MYTHIC: Mythic, + RARE: Rare, + UNCOMMON: Uncommon, + UNKNOWN: Unknown, BLACK_LEGENDARY: BlackLegendary, BLACK_EPIC: BlackEpic, BLACK_RARE: BlackRare, @@ -136,7 +136,7 @@ function RareSatIcon({ return ( - {glow && type !== 'unknown' && ( + {glow && type !== 'UNKNOWN' && ( )} diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts new file mode 100644 index 000000000..13dba0e25 --- /dev/null +++ b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts @@ -0,0 +1,280 @@ +import { ApiBundleV2 } from '@utils/rareSats'; + +export type Response = { + xVersion: number; + limit: number; + offset: number; + total: number; + results: ApiBundleV2[]; +}; + +export const mockData: Response = { + xVersion: 1, + limit: 30, + offset: 0, + total: 1, + results: [ + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c7', + value: 21000, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320010000', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 10000, + range: { + start: '34234320010001', + end: '34234320010002', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [ + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + }, + ], + }, + { + year_mined: 2009, + block: 9, + offset: 10002, + range: { + start: '34234320010002', + end: '34234320020000', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 20001, + range: { + start: '45000000001', + end: '45000000999', + }, + satributes: ['BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], + inscriptions: [], + }, + ], + }, + ], +}; + +// TestCase 1 - Empty response +export const mockTestCase1: Response = { + xVersion: 1, + limit: 30, + offset: 0, + total: 0, + results: [], +}; + +// TestCase 2 - 3 bundles +export const mockTestCase3: Response = { + xVersion: 1, + limit: 30, + offset: 0, + total: 1, + results: [ + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c7', + value: 20997, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320010000', + }, + satributes: ['RARE', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 10000, + range: { + start: '34234320010001', + end: '34234320010002', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [ + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + }, + ], + }, + { + year_mined: 2009, + block: 9, + offset: 10002, + range: { + start: '34234320010002', + end: '34234320020000', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 20001, + range: { + start: '45000000001', + end: '45000000999', + }, + satributes: ['BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], + inscriptions: [], + }, + ], + }, + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c8', + value: 21000, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320010000', + }, + satributes: ['BLOCK78'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 10000, + range: { + start: '34234320010001', + end: '34234320010001', + }, + satributes: ['PIZZA'], + inscriptions: [ + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + }, + ], + }, + { + year_mined: 2009, + block: 9, + offset: 10002, + range: { + start: '34234320010002', + end: '34234320020000', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 20001, + range: { + start: '45000000001', + end: '45000000999', + }, + satributes: ['BLOCK9', 'NAKAMOTO'], + inscriptions: [], + }, + ], + }, + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c9', + value: 21000, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 3, + range: { + start: '34234320010001', + end: '34234320010001', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [ + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + }, + ], + }, + { + year_mined: 2009, + block: 9, + offset: 4, + range: { + start: '34234320010002', + end: '34234320010003', + }, + satributes: ['HITMAN', 'NAME_PALINDROME', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], + inscriptions: [], + }, + ], + }, + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d1', + value: 100, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + ], + }, + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d2', + value: 100, + vout: 0, + sat_ranges: [], + }, + ], +}; diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 547cd9cf6..f4b88fd20 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -1,11 +1,112 @@ import useWalletSelector from '@hooks/useWalletSelector'; -import { getAddressUtxoOrdinalBundles, getUtxoOrdinalBundle } from '@secretkeylabs/xverse-core'; +import { + getAddressUtxoOrdinalBundles, + getUtxoOrdinalBundle, + NetworkType, +} from '@secretkeylabs/xverse-core'; +import { XVERSE_API_BASE_URL } from '@secretkeylabs/xverse-core/constant'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; import { handleRetries, InvalidParamsError } from '@utils/query'; import { mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import axios from 'axios'; +import { mockData, mockTestCase1, mockTestCase3, Response } from './tempAddressRareSatsMock'; const PAGE_SIZE = 30; +// TODO: move this to xverse-core +export const getAddressUtxoOrdinalBundlesV2 = async ( + network: NetworkType, + address: string, + offset: number, + limit: number, + options?: { + /** Filter out unconfirmed UTXOs */ + hideUnconfirmed?: boolean; + /** Filter out UTXOs that only have one or more inscriptions (and no rare sats) */ + hideInscriptionOnly?: boolean; + }, +) => { + const params: Record = { + offset, + limit, + }; + + if (options?.hideUnconfirmed) { + params.hideUnconfirmed = 'true'; + } + if (options?.hideInscriptionOnly) { + params.hideInscriptionOnly = 'true'; + } + + const response = await axios.get( + `${XVERSE_API_BASE_URL(network)}/v2/address/${address}/ordinal-utxo`, + { + params, + }, + ); + + return response.data; +}; + +export const useAddressRareSatsV2 = () => { + const { ordinalsAddress, network } = useWalletSelector(); + + const getRareSatsByAddress = async ({ pageParam = 0 }) => { + if (!ordinalsAddress) { + throw new InvalidParamsError('ordinalsAddress is required'); + } + + // custom ordinal address takes precedence over mocks + const customOrdinalAddress = localStorage.getItem('ordinalAddress'); + const useProdApi = localStorage.getItem('useProdApi'); + + if (!(useProdApi || customOrdinalAddress)) { + // EMPTY RESPONSE + const testcase1 = localStorage.getItem('testcase1'); + if (testcase1) { + return mockTestCase1; + } + + // ERROR RESPONSE + const testcase2 = localStorage.getItem('testcase2'); + if (testcase2) { + throw new Error('Error response from API'); + } + + // 1 BUNDLE with 4 sat ranges + const testcase3 = localStorage.getItem('testcase3'); + if (testcase3) { + return mockTestCase3; + } + + return mockData; + } + + const bundleResponse = await getAddressUtxoOrdinalBundlesV2( + network.type, + customOrdinalAddress ?? ordinalsAddress, + pageParam, + PAGE_SIZE, + { + hideUnconfirmed: true, + hideInscriptionOnly: true, + }, + ); + return bundleResponse; + }; + + return useInfiniteQuery(['rare-sats', ordinalsAddress], getRareSatsByAddress, { + retry: handleRetries, + getNextPageParam: (lastPage, allPages) => { + const currentLength = allPages.map((page) => page.results).flat().length; + if (currentLength < lastPage.total) { + return currentLength; + } + }, + staleTime: 1 * 60 * 1000, // 1 min + }); +}; + export const useAddressRareSats = () => { const { ordinalsAddress, network } = useWalletSelector(); diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx index a1ab7d94c..3dacb3b15 100644 --- a/src/app/screens/nftDashboard/collectiblesTabs.tsx +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -1,7 +1,7 @@ import ActionButton from '@components/button'; import WrenchErrorMessage from '@components/wrenchErrorMessage'; import { StyledP, StyledTab, StyledTabList } from '@ui-library/common.styled'; -import { ApiBundle, Bundle, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { ApiBundleV2, BundleV2, mapRareSatsAPIResponseToRareSatsV2 } from '@utils/rareSats'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useSearchParams } from 'react-router-dom'; @@ -12,6 +12,9 @@ import { StyledBarLoader, TilesSkeletonLoader } from '../../components/tilesSkel import Notice from './notice'; import RareSatsTabGridItem from './rareSatsTabGridItem'; +const MAX_SATS_ITEMS_EXTENSION = 6; +const MAX_SATS_ITEMS_GALLERY = 20; + export const GridContainer = styled.div<{ isGalleryOpen: boolean; }>((props) => ({ @@ -24,6 +27,12 @@ export const GridContainer = styled.div<{ : 'repeat(auto-fill,minmax(150px,1fr))', })); +export const RareSatsTabContainer = styled.div<{ + isGalleryOpen: boolean; +}>((props) => ({ + marginTop: props.theme.space.l, +})); + const StyledTotalItems = styled(StyledP)` margin-top: ${(props) => props.theme.space.s}; `; @@ -219,17 +228,21 @@ export default function CollectiblesTabs({ {rareSatsQuery.isLoading ? ( ) : ( - + {!rareSatsQuery.error && !rareSatsQuery.isLoading && rareSatsQuery.data?.pages ?.map((page) => page?.results) .flat() - .map((utxo: ApiBundle) => mapRareSatsAPIResponseToRareSats(utxo)) - .map((bundle: Bundle) => ( - + .map((utxo: ApiBundleV2) => mapRareSatsAPIResponseToRareSatsV2(utxo)) + .map((bundle: BundleV2) => ( + ))} - + )} {rareSatsQuery.hasNextPage && ( diff --git a/src/app/screens/nftDashboard/index.tsx b/src/app/screens/nftDashboard/index.tsx index ccd04392e..60b19f3a4 100644 --- a/src/app/screens/nftDashboard/index.tsx +++ b/src/app/screens/nftDashboard/index.tsx @@ -5,7 +5,7 @@ import ShowOrdinalReceiveAlert from '@components/showOrdinalReceiveAlert'; import BottomTabBar from '@components/tabBar'; import WebGalleryButton from '@components/webGalleryButton'; import useAddressInscriptionCollections from '@hooks/queries/ordinals/useAddressInscriptionCollections'; -import { useAddressRareSats } from '@hooks/queries/ordinals/useAddressRareSats'; +import { useAddressRareSatsV2 } from '@hooks/queries/ordinals/useAddressRareSats'; import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowDown, Wrench } from '@phosphor-icons/react'; @@ -131,7 +131,7 @@ export type NftDashboardState = { isOrdinalReceiveAlertVisible: boolean; stacksNftsQuery: ReturnType; inscriptionsQuery: ReturnType; - rareSatsQuery: ReturnType; + rareSatsQuery: ReturnType; openInGalleryView: () => void; onReceiveModalOpen: () => void; onReceiveModalClose: () => void; @@ -162,7 +162,7 @@ const useNftDashboard = (): NftDashboardState => { const [isOrdinalReceiveAlertVisible, setIsOrdinalReceiveAlertVisible] = useState(false); const stacksNftsQuery = useStacksCollectibles(); const inscriptionsQuery = useAddressInscriptionCollections(); - const rareSatsQuery = useAddressRareSats(); + const rareSatsQuery = useAddressRareSatsV2(); const ordinalsLength = inscriptionsQuery.data?.pages?.[0]?.total ?? 0; const totalNfts = stacksNftsQuery.data?.pages?.[0]?.total ?? 0; diff --git a/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx b/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx index 91a273407..02b20811b 100644 --- a/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/inscriptionsTabGridItem.tsx @@ -73,7 +73,7 @@ export function InscriptionsTabGridItem({ onClick={isCollection(collection) ? handleClickCollectionId : handleClickInscriptionId} > {!collection.thumbnail_inscriptions ? ( // eslint-disable-line no-nested-ternary - + ) : !isCollection(collection) || collection.thumbnail_inscriptions.length === 1 ? ( // eslint-disable-line no-nested-ternary props.theme.space.m}; +`; + +const IconsContainer = styled.div` + flex: 1; + display: flex; + flex-direction: row; + justify-content: flex-end; `; const StyledBundleId = styled(StyledP)` - text-align: left; text-wrap: nowrap; overflow: hidden; + text-overflow: ellipsis; width: 100%; `; -const StyledBundleSub = styled(StyledP)` - text-align: left; - text-overflow: ellipsis; +const InscriptionText = styled(StyledP)` text-wrap: nowrap; overflow: hidden; + text-overflow: ellipsis; width: 100%; + margin-left: 4px; + width: 80px; `; -const GridItemContainer = styled.button` - display: flex; - flex-direction: column; - background: transparent; - gap: ${(props) => props.theme.space.s}; +const StyledBundleSub = styled(StyledP)` + text-align: left; width: 100%; `; -function RareSatsTabGridItem({ bundle }: { bundle: Bundle }) { - const navigate = useNavigate(); - const { setSelectedSatBundleDetails, setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); - const isMoreThanOneItem = bundle.items?.length > 1; +const TileText = styled(StyledP)` + text-align: center; + color: ${(props) => props.theme.colors.white_200}; + padding: 2px 3px; +`; + +const ItemContainer = styled.div` + display: flex; + align-items: center; + flex-direction: row; + flex: 1; + padding: ${(props) => props.theme.space.m}; + margin-bottom: ${(props) => props.theme.space.s}; + border-radius: ${(props) => props.theme.space.xs}; + background-color: ${(props) => props.theme.colors.elevation1}; + justify-content: space-between; +`; + +const Range = styled.div` + display: flex; + flex-direction: row; + border-radius: 6px; + border: 1px solid var(--white-800, rgba(255, 255, 255, 0.2)); + margin-left: 2px; + align-items: center; + padding: 1px; +`; + +const Row = styled.div` + display: flex; + flex-direction: row; + align-items: center; + flex-direction: row; +`; + +function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: number }) { + // const navigate = useNavigate(); + // const { setSelectedSatBundleDetails, setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); + + const { t } = useTranslation('translation', { keyPrefix: 'RARE_SATS' }); const handleOnClick = () => { - setSelectedSatBundleDetails(bundle); - if (isMoreThanOneItem) { - return navigate('/nft-dashboard/rare-sats-bundle'); - } + // TODO: handle UI changes before navigate to this screens + // const isMoreThanOneItem = bundle.satRanges.length > 1; + // setSelectedSatBundleDetails(bundle); + // if (isMoreThanOneItem) { + // return navigate('/nft-dashboard/rare-sats-bundle'); + // } + // setSelectedSatBundleItemIndex(0); + // navigate('/nft-dashboard/rare-sats-detail'); + }; - setSelectedSatBundleItemIndex(0); - navigate('/nft-dashboard/rare-sats-detail'); + const renderedIcons = () => { + let totalIconsDisplayed = 0; + let totalTilesDisplayed = 0; + + return bundle.satributes.map((sats, index) => { + if (totalIconsDisplayed > maxItems) { + return null; + } + + if (totalIconsDisplayed >= maxItems - 1) { + totalIconsDisplayed += 1; + return ( + + + +{bundle.satributes.length - totalTilesDisplayed} + + + ); + } + totalTilesDisplayed += 1; + return ( + + {sats.map((sattribute, indexSattributes) => { + totalIconsDisplayed += 1; + if (totalIconsDisplayed >= maxItems - 1) { + return null; + } + // eslint-disable-next-line react/no-array-index-key + return ; + })} + {totalIconsDisplayed > maxItems - 2 ? ( + + ) : null} + + ); + }); }; - const bundleId = getBundleId(bundle); - const bundleSubText = getBundleSubText(bundle); + const bundleId = getFormattedTxIdVoutFromBundle(bundle); return ( - - + {bundleId} - - {bundleSubText} - + ( + + {value} + + )} + /> + + {bundle.inscriptions.map((inscription) => ( + + ordinal + + {inscription.id} + + + ))} - + {renderedIcons()} + ); } export default RareSatsTabGridItem; diff --git a/src/app/utils/inscriptions.ts b/src/app/utils/inscriptions.ts index 2afc4b87c..76a48e7ab 100644 --- a/src/app/utils/inscriptions.ts +++ b/src/app/utils/inscriptions.ts @@ -51,5 +51,5 @@ export const mapCondensedInscriptionToBundleItem = ( ): BundleItem => ({ inscription, type: 'inscription', - rarity_ranking: 'common', // TODO eventually want to fetch this rarity and display it + rarity_ranking: 'COMMON', // TODO eventually want to fetch this rarity and display it }); diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 0e883eef2..749530928 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -2,12 +2,12 @@ import { t } from 'i18next'; import { getTruncatedAddress } from './helper'; export const RoadArmorRareSats = [ - 'mythic', - 'legendary', - 'epic', - 'rare', - 'uncommon', - 'common', + 'MYTHIC', + 'LEGENDARY', + 'EPIC', + 'RARE', + 'UNCOMMON', + 'COMMON', ] as const; export type RoadArmorRareSatsType = (typeof RoadArmorRareSats)[number]; @@ -40,11 +40,10 @@ export const Sattributes = [ export type SattributesType = (typeof Sattributes)[number]; // TODO: remove unknown and unify with common -export const RareSats = [...RoadArmorRareSats, 'unknown', ...Sattributes] as const; +export const RareSats = [...RoadArmorRareSats, 'UNKNOWN', ...Sattributes] as const; export type RareSatsType = (typeof RareSats)[number]; -export const getRareSatsLabelByType = (type: RareSatsType) => - t(`RARE_SATS.RARITY_LABEL.${type.toUpperCase()}`); +export const getRareSatsLabelByType = (type: RareSatsType) => t(`RARE_SATS.RARITY_LABEL.${type}`); export type SatType = 'inscription' | 'rare-sat' | 'inscribed-sat' | 'unknown'; @@ -58,10 +57,10 @@ export const getBundleItemSubText = ({ ({ inscription: t('COMMON.INSCRIPTION'), 'rare-sat': t('RARE_SATS.SAT_TYPES.RARE_SAT', { - type: getRareSatsLabelByType(rareSatsType ?? 'unknown'), + type: getRareSatsLabelByType(rareSatsType ?? 'UNKNOWN'), }), 'inscribed-sat': t('RARE_SATS.SAT_TYPES.INSCRIBED_RARE_SAT', { - type: getRareSatsLabelByType(rareSatsType ?? 'unknown'), + type: getRareSatsLabelByType(rareSatsType ?? 'UNKNOWN'), }), unknown: t('RARE_SATS.SAT_TYPES.UNKNOWN_RARE_SAT'), }[satType]); @@ -115,7 +114,7 @@ type SatInscription = { content_type: string; }; -type Sat = { number: string; offset: number; rarity_ranking: RoadArmorRareSatsType }; +type Sat = { number: string; offset: number; rarity_ranking: Lowercase }; export type ApiBundle = { txid: string; @@ -151,7 +150,7 @@ export type BundleItem = } | { type: 'unknown'; - rarity_ranking: 'unknown'; + rarity_ranking: 'UNKNOWN'; }; export type Bundle = Omit & { @@ -168,7 +167,7 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle // unknown if (!apiBundles.sats.length && !apiBundles.inscriptions.length) { - return { ...generalBundleInfo, items: [{ type: 'unknown', rarity_ranking: 'unknown' }] }; + return { ...generalBundleInfo, items: [{ type: 'unknown', rarity_ranking: 'UNKNOWN' }] }; } // only rare sats @@ -177,7 +176,7 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle ...generalBundleInfo, items: apiBundles.sats.map((sat) => ({ type: 'rare-sat', - rarity_ranking: sat.rarity_ranking, + rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, number: sat.number, })), }; @@ -200,7 +199,7 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle } items.push({ type: 'inscription', - rarity_ranking: 'common', + rarity_ranking: 'COMMON', inscription: { id: inscription.id, content_type: inscription.content_type, @@ -213,13 +212,13 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle if (!inscription) { return items.push({ type: 'rare-sat', - rarity_ranking: sat.rarity_ranking, + rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, number: sat.number, }); } items.push({ type: 'inscribed-sat', - rarity_ranking: sat.rarity_ranking, + rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, number: sat.number, inscription: { id: inscription.id, @@ -234,7 +233,7 @@ export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle }; }; -const getFormattedTxIdVoutFromBundle = (bundle: Bundle) => +export const getFormattedTxIdVoutFromBundle = (bundle: Bundle | BundleV2) => `${getTruncatedAddress(bundle.txid, 6)}:${bundle.vout}`; export const getBundleId = (bundle: Bundle): string => { @@ -268,3 +267,108 @@ export const getBundleItemId = (bundle: Bundle, index: number): string => { } return item.number; }; + +// TODO: once we define the layout changes for inscriptions and buy/sell confirmation screen we can remove old implementation and remove the v2 from here +type Inscription = { + id: string; + content_type: string; +}; + +type BundleSatRange = Omit & { + totalSats: number; + yearMined: number; +}; + +export type BundleV2 = Omit & { + satRanges: BundleSatRange[]; + inscriptions: Inscription[]; + satributes: RareSatsType[][]; +}; + +export type ApiBundleSatRange = { + range: { + start: string; + end: string; + }; + year_mined: number; + block: number; + offset: number; + satributes: RareSatsType[]; + inscriptions: Inscription[]; +}; + +export type ApiBundleV2 = { + txid: string; + vout: number; + block_height?: number; + value: number; + sat_ranges: ApiBundleSatRange[]; +}; + +export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): BundleV2 => { + const generalBundleInfo = { + txid: apiBundle.txid, + vout: apiBundle.vout, + block_height: apiBundle.block_height, + value: apiBundle.value, + }; + + const commonUnknownRange: BundleSatRange = { + range: { + start: '0', + end: '0', + }, + yearMined: 0, + block: 0, + offset: 0, + satributes: ['UNKNOWN'], + inscriptions: [], + totalSats: apiBundle.value, + }; + + // if bundle has and empty sat ranges, it means that it's a common/unknown bundle + if (!apiBundle.sat_ranges.length) { + return { + ...generalBundleInfo, + satRanges: [commonUnknownRange], + inscriptions: [], + satributes: [['UNKNOWN']], + }; + } + + const satRanges = apiBundle.sat_ranges.map((satRange) => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const { year_mined, ...satRangeProps } = satRange; + return { + ...satRangeProps, + totalSats: Number(BigInt(satRange.range.end) - BigInt(satRange.range.start)), + yearMined: year_mined, + }; + }); + + // we map this previous to a possible push of a common unknown range cause we don't need to show the icon rare sats tab. We only show it if the bundle is fully common/unknown + const inscriptions = satRanges.reduce( + (acc, curr) => [...acc, ...curr.inscriptions], + [] as BundleV2['satRanges'][0]['inscriptions'], + ); + const satributes = satRanges.reduce( + (acc, curr) => [...acc, curr.satributes], + [] as RareSatsType[][], + ); + + // if totalExotics doesn't match the value of the bundle, it means that the bundle is not fully exotic and we need to add a common unknown sat range more + const totalExotics = satRanges.reduce((acc, curr) => acc + curr.totalSats, 0); + if (totalExotics !== apiBundle.value) { + satRanges.push({ + ...commonUnknownRange, + totalSats: apiBundle.value - totalExotics, + }); + } + + return { + ...generalBundleInfo, + satRanges, + inscriptions, + satributes, + }; +}; diff --git a/src/assets/img/rareSats/ic_ordinal_small.svg b/src/assets/img/rareSats/ic_ordinal_small.svg new file mode 100644 index 000000000..cb9e95ff4 --- /dev/null +++ b/src/assets/img/rareSats/ic_ordinal_small.svg @@ -0,0 +1,6 @@ + + + + + + From d42dbdb75f75710dee7b63d8084270d174d85a03 Mon Sep 17 00:00:00 2001 From: fede erbes Date: Wed, 22 Nov 2023 14:31:17 +0100 Subject: [PATCH 11/28] feat: tweak rare sats bundle screen to support new satributes (#58) * feat: tweak rare sats bundle screen to support new satributes * chore: move ExoticSatsRow to component folder --- .../exoticSatsRow/exoticSatsRow.tsx | 107 ++++++++++++++ .../ordinals/tempAddressRareSatsMock.ts | 19 ++- .../nftDashboard/rareSatsTabGridItem.tsx | 135 ++++-------------- src/app/screens/rareSatsBundle/index.tsx | 131 +++++++++++------ .../rareSatsBundle/rareSatsBundleGridItem.tsx | 125 +++++++--------- src/app/stores/nftData/actions/types.ts | 4 +- src/app/utils/rareSats.ts | 14 +- src/locales/en.json | 4 +- 8 files changed, 307 insertions(+), 232 deletions(-) create mode 100644 src/app/components/exoticSatsRow/exoticSatsRow.tsx diff --git a/src/app/components/exoticSatsRow/exoticSatsRow.tsx b/src/app/components/exoticSatsRow/exoticSatsRow.tsx new file mode 100644 index 000000000..2ba9b4740 --- /dev/null +++ b/src/app/components/exoticSatsRow/exoticSatsRow.tsx @@ -0,0 +1,107 @@ +import OrdinalIcon from '@assets/img/rareSats/ic_ordinal_small.svg'; +import { StyledP } from '@ui-library/common.styled'; +import { Inscription } from '@utils/rareSats'; +import { ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; +import styled from 'styled-components'; + +const InfoContainer = styled.div` + display: flex; + flex: 1; + flex-direction: column; + align-items: flex-start; + margin-right: ${(props) => props.theme.space.m}; +`; + +const IconsContainer = styled.div` + flex: 1; + display: flex; + flex-direction: row; + justify-content: flex-end; +`; + +const StyledBundleId = styled(StyledP)` + text-wrap: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + text-align: left; +`; + +const InscriptionText = styled(StyledP)` + text-wrap: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + margin-left: 4px; + text-align: left; +`; + +const StyledBundleSub = styled(StyledP)` + text-align: left; + width: 100%; +`; + +const ItemContainer = styled.div` + display: flex; + align-items: center; + flex-direction: row; + flex: 1; + padding: ${(props) => props.theme.space.m}; + border-radius: ${(props) => props.theme.space.xs}; + background-color: ${(props) => props.theme.colors.elevation1}; + justify-content: space-between; +`; + +const Row = styled.div` + display: flex; + flex-direction: row; + align-items: center; + flex-direction: row; +`; + +function ExoticSatsRow({ + title, + satAmount, + inscriptions, + icons, +}: { + title: string; + satAmount: number; + inscriptions: Inscription[]; + icons: ReactNode; +}) { + const { t } = useTranslation('translation', { keyPrefix: 'COMMON' }); + return ( + + + + {title} + + ( + + {value} + + )} + /> + {inscriptions.map((inscription) => ( + + ordinal + + {inscription.inscription_number} + + + ))} + + {icons} + + ); +} + +export default ExoticSatsRow; diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts index 13dba0e25..83670d08a 100644 --- a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts +++ b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts @@ -44,6 +44,7 @@ export const mockData: Response = { { content_type: 'text/plain;charset=utf-8', id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141212, }, ], }, @@ -88,7 +89,7 @@ export const mockTestCase3: Response = { xVersion: 1, limit: 30, offset: 0, - total: 1, + total: 5, results: [ { block_height: 803128, @@ -120,6 +121,7 @@ export const mockTestCase3: Response = { { content_type: 'text/plain;charset=utf-8', id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141212, }, ], }, @@ -161,7 +163,7 @@ export const mockTestCase3: Response = { start: '34234320000000', end: '34234320010000', }, - satributes: ['BLOCK78'], + satributes: ['MYTHIC', 'BLOCK78'], inscriptions: [], }, { @@ -177,6 +179,7 @@ export const mockTestCase3: Response = { { content_type: 'text/plain;charset=utf-8', id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141212, }, ], }, @@ -234,6 +237,7 @@ export const mockTestCase3: Response = { { content_type: 'text/plain;charset=utf-8', id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141212, }, ], }, @@ -245,7 +249,16 @@ export const mockTestCase3: Response = { start: '34234320010002', end: '34234320010003', }, - satributes: ['HITMAN', 'NAME_PALINDROME', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], + satributes: [ + 'HITMAN', + 'NAME_PALINDROME', + 'NAKAMOTO', + 'VINTAGE', + 'FIRST_TRANSACTION', + '2D_PALINDROME', + 'BLOCK78', + 'BLOCK9', + ], inscriptions: [], }, ], diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx index 1a9fe9112..81ac6fa62 100644 --- a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -1,68 +1,13 @@ +import ExoticSatsRow from '@components/exoticSatsRow/exoticSatsRow'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -// import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; +import { DotsThree } from '@phosphor-icons/react'; import { StyledP } from '@ui-library/common.styled'; import { BundleV2, getFormattedTxIdVoutFromBundle } from '@utils/rareSats'; -// import { useNavigate } from 'react-router-dom'; -import OrdinalIcon from '@assets/img/rareSats/ic_ordinal_small.svg'; -import { DotsThree } from '@phosphor-icons/react'; -import { useTranslation } from 'react-i18next'; -import { NumericFormat } from 'react-number-format'; +import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import Theme from 'theme'; -const InfoContainer = styled.div` - flex: 1, - flex-direction: column; - align-items: flex-start; - margin-right: ${(props) => props.theme.space.m}; -`; - -const IconsContainer = styled.div` - flex: 1; - display: flex; - flex-direction: row; - justify-content: flex-end; -`; - -const StyledBundleId = styled(StyledP)` - text-wrap: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; -`; - -const InscriptionText = styled(StyledP)` - text-wrap: nowrap; - overflow: hidden; - text-overflow: ellipsis; - width: 100%; - margin-left: 4px; - width: 80px; -`; - -const StyledBundleSub = styled(StyledP)` - text-align: left; - width: 100%; -`; - -const TileText = styled(StyledP)` - text-align: center; - color: ${(props) => props.theme.colors.white_200}; - padding: 2px 3px; -`; - -const ItemContainer = styled.div` - display: flex; - align-items: center; - flex-direction: row; - flex: 1; - padding: ${(props) => props.theme.space.m}; - margin-bottom: ${(props) => props.theme.space.s}; - border-radius: ${(props) => props.theme.space.xs}; - background-color: ${(props) => props.theme.colors.elevation1}; - justify-content: space-between; -`; - const Range = styled.div` display: flex; flex-direction: row; @@ -73,28 +18,26 @@ const Range = styled.div` padding: 1px; `; -const Row = styled.div` - display: flex; - flex-direction: row; - align-items: center; - flex-direction: row; +const TileText = styled(StyledP)` + text-align: center; + color: ${(props) => props.theme.colors.white_200}; + padding: 2px 3px; `; -function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: number }) { - // const navigate = useNavigate(); - // const { setSelectedSatBundleDetails, setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); +const Pressable = styled.button((props) => ({ + background: 'transparent', + width: '100%', + marginBottom: props.theme.space.s, +})); - const { t } = useTranslation('translation', { keyPrefix: 'RARE_SATS' }); +function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: number }) { + const navigate = useNavigate(); + const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); const handleOnClick = () => { - // TODO: handle UI changes before navigate to this screens - // const isMoreThanOneItem = bundle.satRanges.length > 1; - // setSelectedSatBundleDetails(bundle); - // if (isMoreThanOneItem) { - // return navigate('/nft-dashboard/rare-sats-bundle'); - // } - // setSelectedSatBundleItemIndex(0); - // navigate('/nft-dashboard/rare-sats-detail'); + // exotics v1 wont show rage details only bundle details + setSelectedSatBundleDetails(bundle); + navigate('/nft-dashboard/rare-sats-bundle'); }; const renderedIcons = () => { @@ -109,7 +52,7 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: if (totalIconsDisplayed >= maxItems - 1) { totalIconsDisplayed += 1; return ( - + +{bundle.satributes.length - totalTilesDisplayed} @@ -118,7 +61,7 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: } totalTilesDisplayed += 1; return ( - + {sats.map((sattribute, indexSattributes) => { totalIconsDisplayed += 1; if (totalIconsDisplayed >= maxItems - 1) { @@ -138,34 +81,14 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: const bundleId = getFormattedTxIdVoutFromBundle(bundle); return ( - - - - {bundleId} - - ( - - {value} - - )} - /> - - {bundle.inscriptions.map((inscription) => ( - - ordinal - - {inscription.id} - - - ))} - - {renderedIcons()} - + + + ); } export default RareSatsTabGridItem; diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx index ed00dc4ef..57def7c76 100644 --- a/src/app/screens/rareSatsBundle/index.tsx +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -12,10 +12,9 @@ import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; -import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; import { StyledHeading, StyledP } from '@ui-library/common.styled'; -import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; -import { BundleItem } from '@utils/rareSats'; +import { getBtcTxStatusUrl, getTruncatedAddress, isLedgerAccount } from '@utils/helper'; +import { BundleSatRange } from '@utils/rareSats'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -33,7 +32,7 @@ const Container = styled.div` `; const PageHeader = styled.div` - padding: ${(props) => props.theme.space.m}; + padding: ${(props) => (props.isGalleryOpen ? props.theme.space.m : 0)}; padding-top: 0; max-width: 1224px; margin-top: ${(props) => (props.isGalleryOpen ? props.theme.space.xxl : props.theme.space.l)}; @@ -47,27 +46,17 @@ const PageHeaderContent = styled.div` display: flex; flex-direction: ${(props) => (props.isGalleryOpen ? 'row' : 'column')}; justify-content: ${(props) => (props.isGalleryOpen ? 'space-between' : 'initial')}; - row-gap: ${(props) => props.theme.space.xl}; `; -const AttributesContainer = styled.div` - max-width: 285px; -`; +const AttributesContainer = styled.div((props) => ({ + maxWidth: props.isGalleryOpen ? '285px' : '100%', + padding: props.isGalleryOpen ? 0 : `0 ${props.theme.space.m}`, +})); const StyledSeparator = styled(Separator)` margin-bottom: ${(props) => props.theme.space.xxl}; `; -const StyledGridContainer = styled(GridContainer)` - margin-top: ${(props) => props.theme.spacing(8)}px; - padding: 0 ${(props) => props.theme.space.m}; - padding-bottom: ${(props) => props.theme.space.xl}; - max-width: 1224px; - margin-left: auto; - margin-right: auto; - width: 100%; -`; - /* components */ const StyledWebGalleryButton = styled(WebGalleryButton)` @@ -138,10 +127,36 @@ const NoCollectiblesText = styled.p((props) => ({ textAlign: 'center', })); +const Header = styled.div<{ isGalleryOpen: boolean }>((props) => ({ + display: props.isGalleryOpen ? 'block' : 'flex', + flexDirection: props.isGalleryOpen ? 'row' : 'column', + alignItems: props.isGalleryOpen ? 'flex-start' : 'center', +})); + +const SatRangeContainer = styled.div((props) => ({ + marginTop: props.isGalleryOpen ? 0 : props.theme.space.xl, + maxWidth: '1224px', + marginLeft: 'auto', + marginRight: 'auto', + width: '100%', +})); + +const DetailSection = styled.div((props) => ({ + display: 'flex', + flexDirection: props.isGalleryOpen ? 'column' : 'row', + justifyContent: 'space-between', + columnGap: props.theme.space.m, + width: '100%', +})); + +const SeeRarityContainer = styled.div` + padding: ${(props) => props.theme.space.l} ${(props) => props.theme.space.m}; +`; + function RareSatsBundle() { const { t } = useTranslation('translation'); const navigate = useNavigate(); - const { network, selectedAccount } = useWalletSelector(); + const { network, selectedAccount, ordinalsAddress } = useWalletSelector(); const { selectedSatBundle: bundle } = useNftDataSelector(); const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle?.txid); const [showSendOrdinalsAlert, setShowSendOrdinalsAlert] = useState(false); @@ -191,7 +206,7 @@ function RareSatsBundle() { navigate('/nft-dashboard/supported-rarity-scale'); }; - const isEmpty = !bundle?.items?.length; + const isEmpty = !bundle?.satRanges?.length; return ( <> @@ -215,12 +230,12 @@ function RareSatsBundle() { )} -
+
- {t('RARE_SATS.RARE_SATS_BUNDLE')} + {t('NFT_DASHBOARD_SCREEN.RARE_SATS')} - {t('NFT_DASHBOARD_SCREEN.TOTAL_ITEMS', { total: bundle?.items?.length })} + {bundle?.totalExoticSats} {!isGalleryOpen && } @@ -230,19 +245,47 @@ function RareSatsBundle() { onPress={handleSendOrdinal} /> - - - {t('RARE_SATS.RARITY_LINK_TEXT')} - - - -
- - + {isGalleryOpen && ( + + + {t('RARE_SATS.RARITY_LINK_TEXT')} + + + + )} + + {isEmpty && ( + {t('NFT_DASHBOARD_SCREEN.NO_COLLECTIBLES')} + )} + {!isGalleryOpen && ( + + {bundle?.satRanges.map((item: BundleSatRange) => ( + + ))} + + )} + {!isGalleryOpen && ( + + + + )} + + + + + {t('NFT_DASHBOARD_SCREEN.NO_COLLECTIBLES')} )} - - {bundle?.items?.map((item: BundleItem, index) => ( - - ))} - + {isGalleryOpen && ( + + {bundle?.satRanges.map((item: BundleSatRange) => ( + + ))} + + )} {showSendOrdinalsAlert && ( ({ + marginBottom: props.theme.space.s, + padding: `0 ${props.theme.space.m}`, +})); -const ImageContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - aspect-ratio: 1; - overflow: hidden; - border-radius: ${(props) => props.theme.radius(3)}px; - background: ${(props) => props.theme.colors.elevation1}; -`; +export function RareSatsBundleGridItem({ item }: { item: BundleSatRange }) { + const { t } = useTranslation('translation'); -const GridItemContainer = styled.button` - display: flex; - flex-direction: column; - background: transparent; - gap: ${(props) => props.theme.space.s}; -`; + const getSatLabel = (satributes: RareSatsType[]) => { + const isLengthGrateThanTwo = satributes.length > 2; + if (satributes.length === 1) { + return getRareSatsLabelByType(satributes[0]); + } -export function RareSatsBundleGridItem({ - item, - itemIndex, -}: { - item: BundleItem; - itemIndex: number; -}) { - const navigate = useNavigate(); - const { setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); - const { selectedSatBundle } = useNftDataSelector(); + // we expect to roadarmor sats be in the first position + if (RoadArmorRareSats.includes(satributes[0] as RoadArmorRareSatsType)) { + return `${getRareSatsLabelByType(satributes[0])} ${t( + isLengthGrateThanTwo ? 'COMMON.COMBO' : `RARE_SATS.RARITY_LABEL.${satributes[1]}`, + )}`; + } - const handleOnClick = () => { - setSelectedSatBundleItemIndex(itemIndex); - navigate('/nft-dashboard/rare-sats-detail'); + return isLengthGrateThanTwo + ? t('COMMON.COMBO') + : `${getRareSatsLabelByType(satributes[0])} ${getRareSatsLabelByType(satributes[1])}`; }; - const itemId = getBundleItemId(selectedSatBundle!, itemIndex); - const itemSubText = getBundleItemSubText({ - satType: item.type, - rareSatsType: item.rarity_ranking, - }); - return ( - - - - - - - {itemId} - - - {itemSubText} - - - + + + + {item.satributes.map((satribute) => ( + + ))} + + + } + /> + ); } export default RareSatsBundleGridItem; diff --git a/src/app/stores/nftData/actions/types.ts b/src/app/stores/nftData/actions/types.ts index 7c76f3b7f..b3c98109f 100644 --- a/src/app/stores/nftData/actions/types.ts +++ b/src/app/stores/nftData/actions/types.ts @@ -1,11 +1,11 @@ import { Inscription } from '@secretkeylabs/xverse-core/types/api/ordinals'; import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; -import { Bundle } from '@utils/rareSats'; +import { BundleV2 } from '@utils/rareSats'; export interface NftDataState { nftData: NftData[]; selectedOrdinal: Inscription | null; - selectedSatBundle: Bundle | null; + selectedSatBundle: BundleV2 | null; selectedSatBundleItemIndex: number | null; } diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 749530928..73f984764 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -269,12 +269,13 @@ export const getBundleItemId = (bundle: Bundle, index: number): string => { }; // TODO: once we define the layout changes for inscriptions and buy/sell confirmation screen we can remove old implementation and remove the v2 from here -type Inscription = { +export type Inscription = { id: string; content_type: string; + inscription_number: number; }; -type BundleSatRange = Omit & { +export type BundleSatRange = Omit & { totalSats: number; yearMined: number; }; @@ -283,6 +284,7 @@ export type BundleV2 = Omit & { satRanges: BundleSatRange[]; inscriptions: Inscription[]; satributes: RareSatsType[][]; + totalExoticSats: number; }; export type ApiBundleSatRange = { @@ -333,6 +335,7 @@ export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): Bund satRanges: [commonUnknownRange], inscriptions: [], satributes: [['UNKNOWN']], + totalExoticSats: 0, }; } @@ -357,11 +360,11 @@ export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): Bund ); // if totalExotics doesn't match the value of the bundle, it means that the bundle is not fully exotic and we need to add a common unknown sat range more - const totalExotics = satRanges.reduce((acc, curr) => acc + curr.totalSats, 0); - if (totalExotics !== apiBundle.value) { + const totalExoticSats = satRanges.reduce((acc, curr) => acc + curr.totalSats, 0); + if (totalExoticSats !== apiBundle.value) { satRanges.push({ ...commonUnknownRange, - totalSats: apiBundle.value - totalExotics, + totalSats: apiBundle.value - totalExoticSats, }); } @@ -370,5 +373,6 @@ export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): Bund satRanges, inscriptions, satributes, + totalExoticSats, }; }; diff --git a/src/locales/en.json b/src/locales/en.json index efbc22bb8..f11f2d4bf 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,7 +1,9 @@ { "COMMON": { "INSCRIPTION": "Inscription", - "SEND": "Send" + "SEND": "Send", + "COMBO": "Combo", + "SATS": "Sats" }, "LANDING_SCREEN": { "SCREEN_TITLE": "Wallet for Stacks & Bitcoin", From 836914c662701ee4d8ca0a2a6924f66c87f4af7b Mon Sep 17 00:00:00 2001 From: Tim Man Date: Thu, 23 Nov 2023 19:14:47 +0800 Subject: [PATCH 12/28] Chore merge ours to downstream develop (#62) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and code typo (#43) * unstaged package-lock.json * fix: update all custom switch colors --------- Co-authored-by: Tim Man * fix: inscriptions grid fixes (#44) * chore: bump core version to 1.9.1 * Update function to recognise and parse brc20 tokens (#46) * Update skeleton loader logic for Collectibles UI (#45) * Update skeleton loader logic for Collectibles UI * Add a separate `TilesSkeletonLoader` component, add skeleton loader on the Collection page * Add ordinal detail page skeleton loader for the extension view * Add skeleton loader for the ordinal image component * fix: collectibles fixes from review (#47) * Fix minor ui bugs in collectible screen (#48) --------- Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> * release: v0.21.0 * Small fixes for the Collectibles UI loading state (#50) * Small fixes for the Collectibles UI * Fix loader appearance in the Collectibles tabs * Fix skeleton loader on the main Collectibles tab gallery view * Fix skeleton loader on the Collection page gallery view * Add skeleton loader for the ordinal detail page * fix: container padding on ordinals collection page * chore: remove debug lines --------- Co-authored-by: Tim Man * fix: more collectible UI fixes (#52) * chore: remove testAddress and TODOs * fix: brc20 status in ordinal details * fix: back button from nft details goes to nfts tab and back button from ordinal detail says back to collection or gallery * Minor ui fixes (#51) * sort brc20 inscription array * Fix styling * Remove unused funciton --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> * feat: revamp all colors (#588) * Tim/eng 2317 consistent dashboard buttons in extension (#618) * fix: use revamped swap svg * fix: hide swap button on testnet * Ledger send btc screen crash when going back and forward (#615) * Make `Authorize data collection` property turned on by default (#614) * Make `Authorize data collection` property turned on by default * Change the html tag and text color constant * [ENG-2961] Fix eslint errors for web extension (#617) * [ENG-2961] Fix eslint errors for web extension * [ENG-2961] Fix eslint errors for web extension * Update src/app/hooks/queries/ordinals/useInscriptionDetails.ts Co-authored-by: Victor Kirov * Update src/app/hooks/queries/useAppConfig.ts Co-authored-by: Victor Kirov --------- Co-authored-by: Victor Kirov * [ENG-3059] fix: Remove ordinal callout from send rare sats (#619) * [ENG-3059] fix: Remove ordinal callout from send rare sats * Update `amount` field validation error styling * chore: turn on tsc --noEmit precommit hook (#622) * chore: add tsc-files dev dep and run on lint staged pre commit also ran npm audit fix for a critical vuln and updated direct svg import typings * chore: use string for svg typescript declarations * chore: run eslint on repo before passing the workflow checks * feat: allow unpublished UTXOs as inputs to PSBTs (#621) * feat: allow unpublished UTXOs as inputs to PSBTs * Use correct status from response --------- Co-authored-by: Tim Man * [ENG-3039] fix: Skeleton loader for BRC-20 icons in home dashboard (#620) it can be merged, tested on ledger as well * Mahmoud/eng 2284 seedphrase vault (#510) * refactor wallet flow to use seed vault * code cleanup * update auth flow and seedphrase usage * lock dependencies and user xverse-core beta * migrate onboarding to use seed vault * use account switch method from wallet reducer hook * use seed vault for stx swaps * removed seedPhrase from wallet store * rebase fixes * small fixes * clear home screen errors * revert hashing algo change * fix swap hook * Revert "clear home screen errors" This reverts commit 55da10e60ead4c0798c40d61701b904085d6e603. * apply core changes * clear encrypted seed after successfully migrating * type fixes * update core version * onboarding guard refactor * update seed vault hook * use chromeStorage driver for session storage * updated core-lib version * refactor onboarding guard to use hasSeed * update core-lib * small fixes * update auth guard and update core version * updated csp * deprecate internal message handler * update wallet exists guard * overwrite any existing seed on restore wallet * update flow to explicitly clear vault for onboarding * update image csp * reset navigation if seed is not pre-set * update sendRareSat screen to use seed vault * add rich media csp policy * added authguard to settings screen * updated lock file * minor fixes * fresh npm install using v18 * lock with develop * adde new package updates * use fixed version of core * update to core lts version --------- Co-authored-by: Victor Kirov Co-authored-by: Tim Man * [ENG-3115] fix: UI issue in the legal screen (#624) * feat: add vout to the end of the tx id for unknown rarities (#623) * feat: add vout to the end of the tx id for unknown rarities * chore: sed replace forward slash in workflow file should replace all occurrences --------- Co-authored-by: Tim Man * Fix minor UI issues (#625) * Have thousandths separators for STX balance * Add scrollbar in message signing screen * Fix spacing in ordinal detail screen * Add loader for recover ordinal screen * fix: disabling ordinals user should not see them in the (#627) * fix: only display tab buttons when more than one tab (#629) * chore: turn on eslint rule and fix up some core internal imports (#630) * chore: turn on eslint rule and fix up some core internal imports but not all, as some are not exported yet * chore: escape . in eslint rule * chore: use a different eslint rule for this * release: v0.22.0 (#626) * fix: unable to change the network to testnet on the latest (#636) * chore: investigate npm dependabot warnings on extension (#635) * Hotfix/fix (#646) * release: v0.22.0-rc.4 to main (#642) * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * feat: add sponsor swap transaction UI and add a hook with placeholder * feat: bump xverse-core dep version and use sponsor2 url * fix: bump xverse-core version and handle sponsor transaction error * feat(Dashboard): update new action button style and add swap button * feat(Swap): add swap screen placeholder * feat(swap): add swap basic UI * feat(swap): add more UI components * feat(swap): add slippage * feat(swap): make BitCoin and Stacks option in the coin select modal * feat(swap): add token selection logic * feat: add swap data connection * feat(swap): add runSwap * chore(swap): bump alex-sdk version * fix(swap): slippage setting * feat: swap confirm layout * feat: add data bindings * fix: function name and copy address * feat: add advanced settings to the confirmation page * feat: bump alex-sdk to latest and fix the issue where from is the same as to * feat: add math.floor before converting to bigInt * fix: skip action when input is invalid * chore: update package.lock * feat(swap): update to support amm v1_1 pools * chore: fix lint warnings * fix: update swap svg stroke and add missing translation * fix: add key to fix react warnings * chore: fix lint warnings * fix: add error 700 border to swap token card * fix: update swap error message and restrict input to number * chore: prettier * style: add a not-allowed cursor to disabled buttons * fix: update translations * fix: use background elevation_1 * style: update swap details spacing * style: use unicode arrow right for swap route details * feat: implement toggle tokens button in swaps * feat: add reset slippage button to swaps * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * style: prettier * chore: update package-lock with npm i * chore: fix package-lock.json for correct xverse-core dep * chore: replace workflow dep with github api calls * chore: remove erroneous ` * Fix Edit fees popup error * Fix Edit fees popup error * Add receiving address verification for ledger accounts * Fix warning display condition on the ledger verification screen * Dont close popup on checkbox click * fix: fix for JSON serialisation of location.state * chore: use the test instance URL * chore: upgrade to alex-sdk 0.1.14 * Show wrong ledger device error * Add custom ledger account name validation * fix: turn react deps warning back on and fix stale callback * fix: move sponsor url to constants and add sponsor to swap unsigned tx * fix: display the transaction explorer link on successful sponsored tx * fix: set swap transaction fee to 0 if being sponsored * The transaction history not showing a pending send transaction that was just sent from the address * release v0.14.0 * chore: update xverse-core to published release 1.4.0 * chore: update swaps xverse sponsor 2 host * fix: remove btc from swaps coin modal. change was removed during merge * fix: remove static text describing swap route * Add Before Getting Started screen for Ledger onboarding * update copy * add links and update copy * chore: add husky and pre commit prettier to staged files * chore: run prettier --write ./src * fix: show inscription service fee fiat amount * Fix ledger account name UI issue * Show loader instead of previous transaction history data * comment out swaps button * Add localization for onboarding flow Ledger Live warning screen * chore: automatically do husky install on npm install * chore: prefer .husky for hooks * chore: run prettier again * fix: fix unsigned tx serialisation in advance settings for swaps * fix: use getNewNonce to ensure swaps transactions have correct nonce * docs: comment * bump xverse-core to v1.4.2 * fix: only show swaps button if not on a ledger account * fix: post condition info should display to/from depending on the swap * Fix regression issues v0.14.0-rc.1 * fix: ensure we are sending the correct ordinal * fix: ensure we are sending the correct ordinal * 0.14.1 * fix: remove unnecessary nested BalanceAmountText * fix: use semantic html instead of all h1 * fix: add a filter list to not display coins for swaps * Fix screen crash when changing account on /send-brc20 screen * fix: button should always be disabled when processing and show loading state in swap with await, and fix typing * Update /send-brc20 screen logic * use toString to convert value to BigNumber * chore: bump xverse-core to 1.5.0 * fix: not all tickers are all uppercase e.g. xBTC * fix: decouple alex swap from/to token list and visible token list * Fix the case when address verification screen flashes when using wrong device * Add an override switch for sponsoring transaction in swap screen * Update function param name * chore: bump core version to 1.6.0 (#560) * Allow send ordinal to self and display warning instead of error (#525) * feat: allow send ordinal to self and display warning instead of error * feat: remove send btc send to self error and use warning also adjust send ordinal warning if sending brc20 ordinal to self * Release v0.15.0 (#544) * bump version to v0.15.0 * Switch to alex sdk & url for sponsoring service Inspect error code and show sponsoring service info block feat: move alex sponsored transaction hook to new file revert: changes to useSponsoredTransaction hook for future use fix: sponsor transaction switch should toggle userOverrideSponsorValue feat: add a try again button on failed swaps due to sponsor error * feat: add warning texts to explain why a swap cannot be sponsored (#553) * fix: enforce width on swap number input (#554) * Fix swap screen fee update issue (#555) * Use correct value for fee card component * Fix fee state management * Dont show fee block when sponsored * chore: bump xverse-core to 1.5.1 to include fetchStxPendingTxData fix * Fix ui glitch on the login screen (#556) * Remove css transition code * Add hover and active state * fix: use :disabled css pseudo class instead of props on buttons --------- Co-authored-by: Tim Man * Fix swaps tx history (#557) * Use ft transfer array to show token specific history * Add filter to only show specific token history * Refactor txTransfers file to reuse code * Use token ticker * Update variable name * Use correct decimal places for fungible token (#559) * Use ftDecimals function for fungible token amount * fix undefined check --------- Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> * chore: bump xverse-core to 1.6.1 (#561) * fix: Don't use ordinals as inputs when recovering ordinals (#558) * Use updated type from sats-connect (#546) * Use updated type from sats-connect * chore: bump sats-connect to 1.0.0 * Update package-lock.json --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * feat: remove binance onramp from buy screen (#567) * Release 0.16.0 (#565) * 0.16.0 * feat: change restore and backup wallet inputs (#566) * chore: fix eslint errors with typing and use of fragments * feat: move restore wallet route to larger screen size * feat: replace restore wallet seed phrase text area with input boxes * fix: ensure only one input can be visible at a time * feat: implement verify seed quiz * feat: disable copy of seed phrase view * fix: set error message properly * refactor: clean up to use one effect * fix: styling and input labels on backup/restore wallet * fix: handle edge case where new mnemonic already contains the answer * feat: seedPhraseInput will focus on next input on space and do not allow some common special characters * fix: decouple copy from restore wallet and change password screens * fix: bump xverse-core to 1.6.2 (#574) * Fix incorrect swap transaction fee ticker (#562) * Use STX as fee currency in swap screen * Fix typo * Fix variable name * Fix fiat rate state calculation * Show correct ticker and currency * Remove isSponsored check for fee amount * Add ability to remove connected Ledger account (#524) * Add ability to remove connected Ledger account * Improve the ledger account removal logic * Select the first account after ledger account removal * Create a reusable `optionsDialog` component * Fix account list logic, rename `seperator` component to `separator` * Fix option dialog indents * Add `deviceAccountIndex` value for ledger accounts that are missing it * Fix ledger account address verification * Move the `deviceAccountIndex` field migration to `loadActiveAccounts` func * Update copy --------- Co-authored-by: Tim Man * Support BTC message signing with ledger accounts (#549) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * release: v0.17.0 (#576) * release: v0.17.0 * chore: bump to 1.6.3-rc.1 (#575) * chore: bump to 1.6.3-rc.1 * bump core version --------- Co-authored-by: Yukan * update package-lock --------- Co-authored-by: Yukan * Filter out dead pending transactions (#568) * Filter out dead pending transactions * Get account current nonce from confirmed and pending transactions * Refactor filterng out dead pending transaction logic * Address comments * Update variable name * fix: account select navigation (#578) * Display pending fungible token transactions in token dashboard (#572) * Update filterTx function to show pending fungible transactions * Fix transaction title display * Show pending ordinal transactions (#563) * Show pending ordinal transactions * Slight refactor of getBtcTokenTransferTitle * Fix duplicate tx in groupBtcTxsByDate * chore: bump to xverse-core v1.6.4-rc.2 * Remove unused fallback value --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man * feat: add Xverse namespaced providers (#581) * add Xverse namespaced providers * fix comments * Enable PSBT signing for ledger BTC accounts (#570) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Enable PSBT signing for ledger BTC accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * Update PSBT signing screen copy * fix: allow display of brc-20 if application/json type (#587) * fix: allow display of brc-20 if application/json type * make bg colours for a BRC-20 coin consistent * fix: full screen and popup styling (#577) * fix: full screen and popup styling * fix screen container * fix app load styling * fix full screen popup pages --------- Co-authored-by: Tim Man * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Add STX support for Ledger accounts (#564) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Fix ledger account import when both BTC and STX options are selected * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Add error handling when user rejects stx address * Add a guard from account changing for the `/add-stx-address-ledger` route * Remove the back button on the ledger account import flow * Throw an error when `stacksCreds` were not fetched * Upgrade `@secretkeylabs/xverse-core` version to `^1.6.5-3bb284c` * Update package files * Fix add stx address error handling * Fix signing with 1st ledger account and bottom modal position * Skip the `No errors` value of the `errorMessage` for STX ledger signature * Remove the caret symbol in `sats-connect` package version * chore: bump xverse-core version 1.7.2 --------- Co-authored-by: Tim Man * fix: brc-20 balance number check (#592) * fix: don't show fees until we have UTXOs on inscription screen (#594) * fix: improve full screen popup styling (#593) * fix: improve full screen popup styling * fix: set height to 600 on options window * Release/v0.18.0 (#591) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json --------- Co-authored-by: Victor Kirov Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Fix Tx history screen reload & send form navigation issues (#584) * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * Update dependency array for useEffect * Add comment * Fix memo error * Support script outputs in psbts (#534) * Support script outputs * Update copy * Revert package.json change * Add info message for output script * Use Array.some * Remove unused style * Update core versio and address comments * Remove pretext from output script ui * Refactor render script output logic * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * chore: turn on eslint for staged files on precommit and turn off no-plusplus rule * Fix eslint issues * Update dependency array for useEffect * Add comment * Fix script count * fix: eslint fix --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * Mismatch when verifying the addresses from the ledger device (#580) * Handle min fee rate returned by the API (#583) * Handle min fee rate returned by the API * Add a check for the STX tx min fee * Fix a couple of tslint errors * fix: don't show loader on balance refetch on home screen ENG-2757 (#589) * Add refetch loader * resize loading spinner * Release/v0.18.2 (#600) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json * release v0.18.2 * fix send through app fees when inscribing * update package-lock --------- Co-authored-by: Tim Man Co-authored-by: Victor Kirov Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * feat: 1 step brc 20 transfers (#585) * chore: use xverse-core with brc20 hooks * refactor: make reusable fiat row component from sendForm * feat: update send brc20 form to use 1 step mode * feat: update theme elevations to revamp elevations * fix: ensure brc20 currencies are uppercase * fix: remove margin on reusable component tokenImage * feat: create confirm brc20 transaction screen * chore: add jsx key eslint rule * feat: style the brc20 review screen & fees component * feat: implement edit fees for brc20 transfer * fix: show brc20 ticker and image on confirm screen * fix: styling of account header and other brc20 fixes * feat: remove copy buttons from account header * feat: bottom bar will always maintain height * fix: padding and margins on confirm brc20 screen * feat: create a file for common styles and new screen for execute brc20 * fix: styling, react errors, and estimate fees on click edit fees buttons * fix: edit fees button width * fix: account list padding * feat: implement loading status animation * feat: integrate the animations for loading transaction status * fix: clean up TODOs * feat: use content loader in brc20 edit fees * chore: rename the common styled file * fix: fix reset user flow on confirmBrc20Transaction and unused styles * Revert "feat: bottom bar will always maintain height" This reverts commit 07e9fca564beb0a971c4703aa07893a8a9491e5d. * docs: comment * Update src/app/screens/confirmBrc20Transaction/index.tsx Co-authored-by: Victor Kirov * style: use relative import for consistency * style: remove unused comment * docs: add todo to existing comment * fix: reset user flow to '/' and other review fixes * fix: don't clear input if a disallowed key is pressed * fix: ensure only run executeBrc20Transaction once * refactor: simplify usage of useResetUserFlow * chore: remove unused types * chore: update core version to use new brc20 hook * refactor: use useBrc20EstimateTransfer hook * refactor: save edit fees previous state if user clicks cancel * refactor: separate logic to hook * fix: add hook typings and use phosphor icon * fix: actually pass the user input fee rate to execute transfer * fix: disable cancel and confirm buttons while estimate fee is loading * fix: add padding back in account row list on btc select address screen * fix: colors on options and popup css * fix: button positioning on full screen ledger view * refactor: rename one step brc20 send screen and put TODOs for ledger * revert: restore 2 step brc20 send form for ledger support * fix: apply useResetUserFlow update to sendBrc20 * fix: restore 2 step brc20 translations * fix: update new pages to refactored reset user flow hook --------- Co-authored-by: Victor Kirov * update license (#606) * Add scrollbar on all scrollable screens (#582) * Update scrollbar * Include scrollbar styling in theme file * Show transparent scrollbar in account list screen * Remove disable cycle dependency flag * Revert unrelated eslint fixes * Update src/theme/index.ts Co-authored-by: Tim Man * Update theme file * Add missing hidden scrollbar css --------- Co-authored-by: Tim Man * fix: loader on home page issues (#603) Co-authored-by: Tim Man * Fix scrollbar in landing page (#609) * Fix scrollbar in landing page * Revert "Fix scrollbar in landing page" This reverts commit 46c1a8f45cd4f308c84a15db2e57bc284515bbbe. * fix: add back the global CSS to hide scrollbars by default and add display: block on scrollbars CSS when desired --------- Co-authored-by: Tim Man * feat: notice for an non taproot address when sending brc 20 tokens (#602) * refactor: move fiatRow into separate component * feat: add callout and inputFeedback to send brc20 one step screen and include components in ui-library * feat: add conditional callouts to confirm brc20 screen * feat: update the recipient card on confirm brc20 transaction * fix: input borders should reflect errors only, not info feedback * refactor: include a helper function for checking if error state * refactor: make styles consistent in callout.tsx * fix: remove unused icon variants * fix: fix styling and imports on brc20 one step and callout component * refactor: use recipient card props instead of type from core * fix: update success callout color and add to theme * fix: fix estimate fee error not showing, and vertical align of callout body * refactor: use styled components instead of React.createElement * Revert "refactor: use styled components instead of React.createElement" This reverts commit 31faea642fdcc867b0cec707bf2ff8a5814aab44. * fix: disable key presses for - and . on brc20 edit fees * refactor: use styled icon instead of React.createElement * refactor: use fiatAmountText component and allow styling * fix: use input feedback in editFees and update components to allow styled components * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and code t… * Fix main dev drift (#647) * release: v0.22.0-rc.4 to main (#642) * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * feat: add sponsor swap transaction UI and add a hook with placeholder * feat: bump xverse-core dep version and use sponsor2 url * fix: bump xverse-core version and handle sponsor transaction error * feat(Dashboard): update new action button style and add swap button * feat(Swap): add swap screen placeholder * feat(swap): add swap basic UI * feat(swap): add more UI components * feat(swap): add slippage * feat(swap): make BitCoin and Stacks option in the coin select modal * feat(swap): add token selection logic * feat: add swap data connection * feat(swap): add runSwap * chore(swap): bump alex-sdk version * fix(swap): slippage setting * feat: swap confirm layout * feat: add data bindings * fix: function name and copy address * feat: add advanced settings to the confirmation page * feat: bump alex-sdk to latest and fix the issue where from is the same as to * feat: add math.floor before converting to bigInt * fix: skip action when input is invalid * chore: update package.lock * feat(swap): update to support amm v1_1 pools * chore: fix lint warnings * fix: update swap svg stroke and add missing translation * fix: add key to fix react warnings * chore: fix lint warnings * fix: add error 700 border to swap token card * fix: update swap error message and restrict input to number * chore: prettier * style: add a not-allowed cursor to disabled buttons * fix: update translations * fix: use background elevation_1 * style: update swap details spacing * style: use unicode arrow right for swap route details * feat: implement toggle tokens button in swaps * feat: add reset slippage button to swaps * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * style: prettier * chore: update package-lock with npm i * chore: fix package-lock.json for correct xverse-core dep * chore: replace workflow dep with github api calls * chore: remove erroneous ` * Fix Edit fees popup error * Fix Edit fees popup error * Add receiving address verification for ledger accounts * Fix warning display condition on the ledger verification screen * Dont close popup on checkbox click * fix: fix for JSON serialisation of location.state * chore: use the test instance URL * chore: upgrade to alex-sdk 0.1.14 * Show wrong ledger device error * Add custom ledger account name validation * fix: turn react deps warning back on and fix stale callback * fix: move sponsor url to constants and add sponsor to swap unsigned tx * fix: display the transaction explorer link on successful sponsored tx * fix: set swap transaction fee to 0 if being sponsored * The transaction history not showing a pending send transaction that was just sent from the address * release v0.14.0 * chore: update xverse-core to published release 1.4.0 * chore: update swaps xverse sponsor 2 host * fix: remove btc from swaps coin modal. change was removed during merge * fix: remove static text describing swap route * Add Before Getting Started screen for Ledger onboarding * update copy * add links and update copy * chore: add husky and pre commit prettier to staged files * chore: run prettier --write ./src * fix: show inscription service fee fiat amount * Fix ledger account name UI issue * Show loader instead of previous transaction history data * comment out swaps button * Add localization for onboarding flow Ledger Live warning screen * chore: automatically do husky install on npm install * chore: prefer .husky for hooks * chore: run prettier again * fix: fix unsigned tx serialisation in advance settings for swaps * fix: use getNewNonce to ensure swaps transactions have correct nonce * docs: comment * bump xverse-core to v1.4.2 * fix: only show swaps button if not on a ledger account * fix: post condition info should display to/from depending on the swap * Fix regression issues v0.14.0-rc.1 * fix: ensure we are sending the correct ordinal * fix: ensure we are sending the correct ordinal * 0.14.1 * fix: remove unnecessary nested BalanceAmountText * fix: use semantic html instead of all h1 * fix: add a filter list to not display coins for swaps * Fix screen crash when changing account on /send-brc20 screen * fix: button should always be disabled when processing and show loading state in swap with await, and fix typing * Update /send-brc20 screen logic * use toString to convert value to BigNumber * chore: bump xverse-core to 1.5.0 * fix: not all tickers are all uppercase e.g. xBTC * fix: decouple alex swap from/to token list and visible token list * Fix the case when address verification screen flashes when using wrong device * Add an override switch for sponsoring transaction in swap screen * Update function param name * chore: bump core version to 1.6.0 (#560) * Allow send ordinal to self and display warning instead of error (#525) * feat: allow send ordinal to self and display warning instead of error * feat: remove send btc send to self error and use warning also adjust send ordinal warning if sending brc20 ordinal to self * Release v0.15.0 (#544) * bump version to v0.15.0 * Switch to alex sdk & url for sponsoring service Inspect error code and show sponsoring service info block feat: move alex sponsored transaction hook to new file revert: changes to useSponsoredTransaction hook for future use fix: sponsor transaction switch should toggle userOverrideSponsorValue feat: add a try again button on failed swaps due to sponsor error * feat: add warning texts to explain why a swap cannot be sponsored (#553) * fix: enforce width on swap number input (#554) * Fix swap screen fee update issue (#555) * Use correct value for fee card component * Fix fee state management * Dont show fee block when sponsored * chore: bump xverse-core to 1.5.1 to include fetchStxPendingTxData fix * Fix ui glitch on the login screen (#556) * Remove css transition code * Add hover and active state * fix: use :disabled css pseudo class instead of props on buttons --------- Co-authored-by: Tim Man * Fix swaps tx history (#557) * Use ft transfer array to show token specific history * Add filter to only show specific token history * Refactor txTransfers file to reuse code * Use token ticker * Update variable name * Use correct decimal places for fungible token (#559) * Use ftDecimals function for fungible token amount * fix undefined check --------- Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> * chore: bump xverse-core to 1.6.1 (#561) * fix: Don't use ordinals as inputs when recovering ordinals (#558) * Use updated type from sats-connect (#546) * Use updated type from sats-connect * chore: bump sats-connect to 1.0.0 * Update package-lock.json --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * feat: remove binance onramp from buy screen (#567) * Release 0.16.0 (#565) * 0.16.0 * feat: change restore and backup wallet inputs (#566) * chore: fix eslint errors with typing and use of fragments * feat: move restore wallet route to larger screen size * feat: replace restore wallet seed phrase text area with input boxes * fix: ensure only one input can be visible at a time * feat: implement verify seed quiz * feat: disable copy of seed phrase view * fix: set error message properly * refactor: clean up to use one effect * fix: styling and input labels on backup/restore wallet * fix: handle edge case where new mnemonic already contains the answer * feat: seedPhraseInput will focus on next input on space and do not allow some common special characters * fix: decouple copy from restore wallet and change password screens * fix: bump xverse-core to 1.6.2 (#574) * Fix incorrect swap transaction fee ticker (#562) * Use STX as fee currency in swap screen * Fix typo * Fix variable name * Fix fiat rate state calculation * Show correct ticker and currency * Remove isSponsored check for fee amount * Add ability to remove connected Ledger account (#524) * Add ability to remove connected Ledger account * Improve the ledger account removal logic * Select the first account after ledger account removal * Create a reusable `optionsDialog` component * Fix account list logic, rename `seperator` component to `separator` * Fix option dialog indents * Add `deviceAccountIndex` value for ledger accounts that are missing it * Fix ledger account address verification * Move the `deviceAccountIndex` field migration to `loadActiveAccounts` func * Update copy --------- Co-authored-by: Tim Man * Support BTC message signing with ledger accounts (#549) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * release: v0.17.0 (#576) * release: v0.17.0 * chore: bump to 1.6.3-rc.1 (#575) * chore: bump to 1.6.3-rc.1 * bump core version --------- Co-authored-by: Yukan * update package-lock --------- Co-authored-by: Yukan * Filter out dead pending transactions (#568) * Filter out dead pending transactions * Get account current nonce from confirmed and pending transactions * Refactor filterng out dead pending transaction logic * Address comments * Update variable name * fix: account select navigation (#578) * Display pending fungible token transactions in token dashboard (#572) * Update filterTx function to show pending fungible transactions * Fix transaction title display * Show pending ordinal transactions (#563) * Show pending ordinal transactions * Slight refactor of getBtcTokenTransferTitle * Fix duplicate tx in groupBtcTxsByDate * chore: bump to xverse-core v1.6.4-rc.2 * Remove unused fallback value --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man * feat: add Xverse namespaced providers (#581) * add Xverse namespaced providers * fix comments * Enable PSBT signing for ledger BTC accounts (#570) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Enable PSBT signing for ledger BTC accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * Update PSBT signing screen copy * fix: allow display of brc-20 if application/json type (#587) * fix: allow display of brc-20 if application/json type * make bg colours for a BRC-20 coin consistent * fix: full screen and popup styling (#577) * fix: full screen and popup styling * fix screen container * fix app load styling * fix full screen popup pages --------- Co-authored-by: Tim Man * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Add STX support for Ledger accounts (#564) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Fix ledger account import when both BTC and STX options are selected * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Add error handling when user rejects stx address * Add a guard from account changing for the `/add-stx-address-ledger` route * Remove the back button on the ledger account import flow * Throw an error when `stacksCreds` were not fetched * Upgrade `@secretkeylabs/xverse-core` version to `^1.6.5-3bb284c` * Update package files * Fix add stx address error handling * Fix signing with 1st ledger account and bottom modal position * Skip the `No errors` value of the `errorMessage` for STX ledger signature * Remove the caret symbol in `sats-connect` package version * chore: bump xverse-core version 1.7.2 --------- Co-authored-by: Tim Man * fix: brc-20 balance number check (#592) * fix: don't show fees until we have UTXOs on inscription screen (#594) * fix: improve full screen popup styling (#593) * fix: improve full screen popup styling * fix: set height to 600 on options window * Release/v0.18.0 (#591) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json --------- Co-authored-by: Victor Kirov Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Fix Tx history screen reload & send form navigation issues (#584) * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * Update dependency array for useEffect * Add comment * Fix memo error * Support script outputs in psbts (#534) * Support script outputs * Update copy * Revert package.json change * Add info message for output script * Use Array.some * Remove unused style * Update core versio and address comments * Remove pretext from output script ui * Refactor render script output logic * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * chore: turn on eslint for staged files on precommit and turn off no-plusplus rule * Fix eslint issues * Update dependency array for useEffect * Add comment * Fix script count * fix: eslint fix --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * Mismatch when verifying the addresses from the ledger device (#580) * Handle min fee rate returned by the API (#583) * Handle min fee rate returned by the API * Add a check for the STX tx min fee * Fix a couple of tslint errors * fix: don't show loader on balance refetch on home screen ENG-2757 (#589) * Add refetch loader * resize loading spinner * Release/v0.18.2 (#600) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json * release v0.18.2 * fix send through app fees when inscribing * update package-lock --------- Co-authored-by: Tim Man Co-authored-by: Victor Kirov Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * feat: 1 step brc 20 transfers (#585) * chore: use xverse-core with brc20 hooks * refactor: make reusable fiat row component from sendForm * feat: update send brc20 form to use 1 step mode * feat: update theme elevations to revamp elevations * fix: ensure brc20 currencies are uppercase * fix: remove margin on reusable component tokenImage * feat: create confirm brc20 transaction screen * chore: add jsx key eslint rule * feat: style the brc20 review screen & fees component * feat: implement edit fees for brc20 transfer * fix: show brc20 ticker and image on confirm screen * fix: styling of account header and other brc20 fixes * feat: remove copy buttons from account header * feat: bottom bar will always maintain height * fix: padding and margins on confirm brc20 screen * feat: create a file for common styles and new screen for execute brc20 * fix: styling, react errors, and estimate fees on click edit fees buttons * fix: edit fees button width * fix: account list padding * feat: implement loading status animation * feat: integrate the animations for loading transaction status * fix: clean up TODOs * feat: use content loader in brc20 edit fees * chore: rename the common styled file * fix: fix reset user flow on confirmBrc20Transaction and unused styles * Revert "feat: bottom bar will always maintain height" This reverts commit 07e9fca564beb0a971c4703aa07893a8a9491e5d. * docs: comment * Update src/app/screens/confirmBrc20Transaction/index.tsx Co-authored-by: Victor Kirov * style: use relative import for consistency * style: remove unused comment * docs: add todo to existing comment * fix: reset user flow to '/' and other review fixes * fix: don't clear input if a disallowed key is pressed * fix: ensure only run executeBrc20Transaction once * refactor: simplify usage of useResetUserFlow * chore: remove unused types * chore: update core version to use new brc20 hook * refactor: use useBrc20EstimateTransfer hook * refactor: save edit fees previous state if user clicks cancel * refactor: separate logic to hook * fix: add hook typings and use phosphor icon * fix: actually pass the user input fee rate to execute transfer * fix: disable cancel and confirm buttons while estimate fee is loading * fix: add padding back in account row list on btc select address screen * fix: colors on options and popup css * fix: button positioning on full screen ledger view * refactor: rename one step brc20 send screen and put TODOs for ledger * revert: restore 2 step brc20 send form for ledger support * fix: apply useResetUserFlow update to sendBrc20 * fix: restore 2 step brc20 translations * fix: update new pages to refactored reset user flow hook --------- Co-authored-by: Victor Kirov * update license (#606) * Add scrollbar on all scrollable screens (#582) * Update scrollbar * Include scrollbar styling in theme file * Show transparent scrollbar in account list screen * Remove disable cycle dependency flag * Revert unrelated eslint fixes * Update src/theme/index.ts Co-authored-by: Tim Man * Update theme file * Add missing hidden scrollbar css --------- Co-authored-by: Tim Man * fix: loader on home page issues (#603) Co-authored-by: Tim Man * Fix scrollbar in landing page (#609) * Fix scrollbar in landing page * Revert "Fix scrollbar in landing page" This reverts commit 46c1a8f45cd4f308c84a15db2e57bc284515bbbe. * fix: add back the global CSS to hide scrollbars by default and add display: block on scrollbars CSS when desired --------- Co-authored-by: Tim Man * feat: notice for an non taproot address when sending brc 20 tokens (#602) * refactor: move fiatRow into separate component * feat: add callout and inputFeedback to send brc20 one step screen and include components in ui-library * feat: add conditional callouts to confirm brc20 screen * feat: update the recipient card on confirm brc20 transaction * fix: input borders should reflect errors only, not info feedback * refactor: include a helper function for checking if error state * refactor: make styles consistent in callout.tsx * fix: remove unused icon variants * fix: fix styling and imports on brc20 one step and callout component * refactor: use recipient card props instead of type from core * fix: update success callout color and add to theme * fix: fix estimate fee error not showing, and vertical align of callout body * refactor: use styled components instead of React.createElement * Revert "refactor: use styled components instead of React.createElement" This reverts commit 31faea642fdcc867b0cec707bf2ff8a5814aab44. * fix: disable key presses for - and . on brc20 edit fees * refactor: use styled icon instead of React.createElement * refactor: use fiatAmountText component and allow styling * fix: use input feedback in editFees and update components to allow styled components * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch an… * fix: when clicking on the inscription image in the details view (#659) * fix: settings layover (#657) * navigate back to the screen that triggers login (#651) * fix: remove bignumber from the redux store (#610) * Update btcbalance to string and fix some typing issues * stx balances to string * btc fiat rate to string and fix all typings related to it * stx fiat rate to string * update state sync settings * Remove restore btc screen --------- Co-authored-by: Tim Man * feat: Enable Ledger PSBT signing (#660) * feat: Enable Ledger PSBT signing * bump core * chore: bump sats-connect to 1.1.2 (#667) * Replace hardcoded USD with dynamic NumericFormat prefix (#670) * fix: cache keys for react queries where stale time was added (#669) * feat: STX NFTs Tab (#634) * Add hook to get nft collection data * Update stx collectible UI * Make NFT collage for collections * Fix on click function * fix import * Update NFT Collection Page & NFT Detail Page (#633) * Update NFT Detail UI * Use hook to get collection data * Add NFT Collection screen * Fix navigation * Remove hard coded address * Fix bns name navigation * refactor: use array for cache key * Turn off no-nested-ternary rule globally * Move nft util functions to a seperate file * fix: remove unnecessary use mutation in nft details and some other bug fixes * fix: add the useResetUserFlow hook to nft collection page * refactor: remove nftData from redux store use the react-query cache instead, and fixes bug where some nftData was not being stored * fix: add isLoading state back to nftdetail and route to send with id * fix: react console errors and send nft finishes at dashboard screen * feat: add sticky tabs to collectibles dashboard * refactor: separate use nft dashboard to separate file * fix: bns detail page works * chore: use core version with some updates * fix: make bns names in collection screen not clickable and display name * chore: enable stx test address from localstorage * fix: button width for gallery view (#650) * fix: open NFT gamma link (#649) * fix: open nft page on gamma * refactor: gamma url * fix: metaData * fix: show snackbar if NFT metadata is failed to fetch (#648) * fix: show snackbar if nft metadata is failed to fetch * fix: snackbar styling * feat: revamp stacks nfts send to screen (#653) * feat: revamp the send nft screen * fix: back button display should rely on back history not ledger account * fix: ledger accounts should only open in new tab when not already in full screen otherwise it is annoying * fix: add the bns name resolver to send nft form * fix: opening a send-nft from ledger should open responsive screen and debounce the stx address -> bns name resolver * fix: some nft images are still showing the moon loader spinner it should be (#654) * chore: tweak BetterBarLoader component to receive string as width and height in order to user percentages * fix: key prop in nft collection screen * fix: hardcoded placeholder size values and replace error icon with the new one * fix: NFT detail screen UI (#655) * fix: detail screen UI * fix: UI alignments * fix: buttons spacing * feat: hook items count with correct values (#658) * fix: column gap on tiles skeleton loader * chore: update core version * chore: follow i18n next doc about plurals (#661) * fix: extension crashes when closing the broadcast success screen (#662) * fix: wrong background color on transaction status screens * fix: wrong navigation routes on transaction status screen * fix: copy on inscription complete screen * fix: z index on sticky tabs list and modals, popups (#665) * refactor: collectibles fetch (#666) * refactor: adapt to core refactor of stx collectibles * fix: add back the check for metadata before nav to nft detail screen * fix: use 24 hour staleTime for nft details to match mobile * refactor: remove unused utils function * fix: add react-is-visible to virtualise nft tab and nft collection page * chore: bump core version with duplicate nft fix * chore: bump core version * chore: update core version and remove total_nft * fix: bns image size and disable click on bns item (#668) --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes * Release/v0.23.0 (#674) * release: v0.22.0-rc.4 to main (#642) * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * feat: add sponsor swap transaction UI and add a hook with placeholder * feat: bump xverse-core dep version and use sponsor2 url * fix: bump xverse-core version and handle sponsor transaction error * feat(Dashboard): update new action button style and add swap button * feat(Swap): add swap screen placeholder * feat(swap): add swap basic UI * feat(swap): add more UI components * feat(swap): add slippage * feat(swap): make BitCoin and Stacks option in the coin select modal * feat(swap): add token selection logic * feat: add swap data connection * feat(swap): add runSwap * chore(swap): bump alex-sdk version * fix(swap): slippage setting * feat: swap confirm layout * feat: add data bindings * fix: function name and copy address * feat: add advanced settings to the confirmation page * feat: bump alex-sdk to latest and fix the issue where from is the same as to * feat: add math.floor before converting to bigInt * fix: skip action when input is invalid * chore: update package.lock * feat(swap): update to support amm v1_1 pools * chore: fix lint warnings * fix: update swap svg stroke and add missing translation * fix: add key to fix react warnings * chore: fix lint warnings * fix: add error 700 border to swap token card * fix: update swap error message and restrict input to number * chore: prettier * style: add a not-allowed cursor to disabled buttons * fix: update translations * fix: use background elevation_1 * style: update swap details spacing * style: use unicode arrow right for swap route details * feat: implement toggle tokens button in swaps * feat: add reset slippage button to swaps * fix: refactor select currency logic to use reducer and unit test * chore: commit package-lock * fix: disable button when insufficient balance * fix: add token name to min received * fix: advanced settings modal on swaps * fix: use 4dp rounding on exchange rate * fix: toggle button should also toggle amounts * fix: function font style should be body_medium_m * feat: make swap confirmation buttons sticky bottom * fix: standardise button hover, active, disabled css ref: https://zeroheight.com/0683c9fa7/p/5270b4-buttons/b/32e1a2 * feat: add error state to slippage input * fix: use intended params for swap advance settings on apply handler * fix: padding on swap confirm buttons * fix: no exponents in fees block of swap confirmation * style: prettier * chore: update package-lock with npm i * chore: fix package-lock.json for correct xverse-core dep * chore: replace workflow dep with github api calls * chore: remove erroneous ` * Fix Edit fees popup error * Fix Edit fees popup error * Add receiving address verification for ledger accounts * Fix warning display condition on the ledger verification screen * Dont close popup on checkbox click * fix: fix for JSON serialisation of location.state * chore: use the test instance URL * chore: upgrade to alex-sdk 0.1.14 * Show wrong ledger device error * Add custom ledger account name validation * fix: turn react deps warning back on and fix stale callback * fix: move sponsor url to constants and add sponsor to swap unsigned tx * fix: display the transaction explorer link on successful sponsored tx * fix: set swap transaction fee to 0 if being sponsored * The transaction history not showing a pending send transaction that was just sent from the address * release v0.14.0 * chore: update xverse-core to published release 1.4.0 * chore: update swaps xverse sponsor 2 host * fix: remove btc from swaps coin modal. change was removed during merge * fix: remove static text describing swap route * Add Before Getting Started screen for Ledger onboarding * update copy * add links and update copy * chore: add husky and pre commit prettier to staged files * chore: run prettier --write ./src * fix: show inscription service fee fiat amount * Fix ledger account name UI issue * Show loader instead of previous transaction history data * comment out swaps button * Add localization for onboarding flow Ledger Live warning screen * chore: automatically do husky install on npm install * chore: prefer .husky for hooks * chore: run prettier again * fix: fix unsigned tx serialisation in advance settings for swaps * fix: use getNewNonce to ensure swaps transactions have correct nonce * docs: comment * bump xverse-core to v1.4.2 * fix: only show swaps button if not on a ledger account * fix: post condition info should display to/from depending on the swap * Fix regression issues v0.14.0-rc.1 * fix: ensure we are sending the correct ordinal * fix: ensure we are sending the correct ordinal * 0.14.1 * fix: remove unnecessary nested BalanceAmountText * fix: use semantic html instead of all h1 * fix: add a filter list to not display coins for swaps * Fix screen crash when changing account on /send-brc20 screen * fix: button should always be disabled when processing and show loading state in swap with await, and fix typing * Update /send-brc20 screen logic * use toString to convert value to BigNumber * chore: bump xverse-core to 1.5.0 * fix: not all tickers are all uppercase e.g. xBTC * fix: decouple alex swap from/to token list and visible token list * Fix the case when address verification screen flashes when using wrong device * Add an override switch for sponsoring transaction in swap screen * Update function param name * chore: bump core version to 1.6.0 (#560) * Allow send ordinal to self and display warning instead of error (#525) * feat: allow send ordinal to self and display warning instead of error * feat: remove send btc send to self error and use warning also adjust send ordinal warning if sending brc20 ordinal to self * Release v0.15.0 (#544) * bump version to v0.15.0 * Switch to alex sdk & url for sponsoring service Inspect error code and show sponsoring service info block feat: move alex sponsored transaction hook to new file revert: changes to useSponsoredTransaction hook for future use fix: sponsor transaction switch should toggle userOverrideSponsorValue feat: add a try again button on failed swaps due to sponsor error * feat: add warning texts to explain why a swap cannot be sponsored (#553) * fix: enforce width on swap number input (#554) * Fix swap screen fee update issue (#555) * Use correct value for fee card component * Fix fee state management * Dont show fee block when sponsored * chore: bump xverse-core to 1.5.1 to include fetchStxPendingTxData fix * Fix ui glitch on the login screen (#556) * Remove css transition code * Add hover and active state * fix: use :disabled css pseudo class instead of props on buttons --------- Co-authored-by: Tim Man * Fix swaps tx history (#557) * Use ft transfer array to show token specific history * Add filter to only show specific token history * Refactor txTransfers file to reuse code * Use token ticker * Update variable name * Use correct decimal places for fungible token (#559) * Use ftDecimals function for fungible token amount * fix undefined check --------- Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar Co-authored-by: Tim Man Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> * chore: bump xverse-core to 1.6.1 (#561) * fix: Don't use ordinals as inputs when recovering ordinals (#558) * Use updated type from sats-connect (#546) * Use updated type from sats-connect * chore: bump sats-connect to 1.0.0 * Update package-lock.json --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * feat: remove binance onramp from buy screen (#567) * Release 0.16.0 (#565) * 0.16.0 * feat: change restore and backup wallet inputs (#566) * chore: fix eslint errors with typing and use of fragments * feat: move restore wallet route to larger screen size * feat: replace restore wallet seed phrase text area with input boxes * fix: ensure only one input can be visible at a time * feat: implement verify seed quiz * feat: disable copy of seed phrase view * fix: set error message properly * refactor: clean up to use one effect * fix: styling and input labels on backup/restore wallet * fix: handle edge case where new mnemonic already contains the answer * feat: seedPhraseInput will focus on next input on space and do not allow some common special characters * fix: decouple copy from restore wallet and change password screens * fix: bump xverse-core to 1.6.2 (#574) * Fix incorrect swap transaction fee ticker (#562) * Use STX as fee currency in swap screen * Fix typo * Fix variable name * Fix fiat rate state calculation * Show correct ticker and currency * Remove isSponsored check for fee amount * Add ability to remove connected Ledger account (#524) * Add ability to remove connected Ledger account * Improve the ledger account removal logic * Select the first account after ledger account removal * Create a reusable `optionsDialog` component * Fix account list logic, rename `seperator` component to `separator` * Fix option dialog indents * Add `deviceAccountIndex` value for ledger accounts that are missing it * Fix ledger account address verification * Move the `deviceAccountIndex` field migration to `loadActiveAccounts` func * Update copy --------- Co-authored-by: Tim Man * Support BTC message signing with ledger accounts (#549) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * release: v0.17.0 (#576) * release: v0.17.0 * chore: bump to 1.6.3-rc.1 (#575) * chore: bump to 1.6.3-rc.1 * bump core version --------- Co-authored-by: Yukan * update package-lock --------- Co-authored-by: Yukan * Filter out dead pending transactions (#568) * Filter out dead pending transactions * Get account current nonce from confirmed and pending transactions * Refactor filterng out dead pending transaction logic * Address comments * Update variable name * fix: account select navigation (#578) * Display pending fungible token transactions in token dashboard (#572) * Update filterTx function to show pending fungible transactions * Fix transaction title display * Show pending ordinal transactions (#563) * Show pending ordinal transactions * Slight refactor of getBtcTokenTransferTitle * Fix duplicate tx in groupBtcTxsByDate * chore: bump to xverse-core v1.6.4-rc.2 * Remove unused fallback value --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man * feat: add Xverse namespaced providers (#581) * add Xverse namespaced providers * fix comments * Enable PSBT signing for ledger BTC accounts (#570) * Support BTC message signing with ledger accounts * Remove console.logs * Change ledger signing modal displaying * Add segwit tx signing functionality * Use `signSimpleBip322Message` method for bip 322 message signing * Update package-lock.json * Update PSBT signing logic for ledger accounts * Add `findLedgerAccountId` util, update usage for `signIncomingSingleSigPSBT` function * Update `isAccountSelected` func logic for external popup account select window * Pass an array of inputs to sign to `signIncomingSingleSigPSBT` func * Move `handleBip322LedgerMessageSigning` func to utils, make some small code fixes * Disable the PSBT signing for BTC ledger accounts * Enable PSBT signing for ledger BTC accounts * Remove the `@stacks/common` module * Add error warning regarding ledger Bitcoin app version * Update error handling for signature request popup * Update copy and make some small UI tweaks * Update the copy for message signing screen * Update PSBT signing screen copy * fix: allow display of brc-20 if application/json type (#587) * fix: allow display of brc-20 if application/json type * make bg colours for a BRC-20 coin consistent * fix: full screen and popup styling (#577) * fix: full screen and popup styling * fix screen container * fix app load styling * fix full screen popup pages --------- Co-authored-by: Tim Man * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Add STX support for Ledger accounts (#564) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Fix ledger account import when both BTC and STX options are selected * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Add error handling when user rejects stx address * Add a guard from account changing for the `/add-stx-address-ledger` route * Remove the back button on the ledger account import flow * Throw an error when `stacksCreds` were not fetched * Upgrade `@secretkeylabs/xverse-core` version to `^1.6.5-3bb284c` * Update package files * Fix add stx address error handling * Fix signing with 1st ledger account and bottom modal position * Skip the `No errors` value of the `errorMessage` for STX ledger signature * Remove the caret symbol in `sats-connect` package version * chore: bump xverse-core version 1.7.2 --------- Co-authored-by: Tim Man * fix: brc-20 balance number check (#592) * fix: don't show fees until we have UTXOs on inscription screen (#594) * fix: improve full screen popup styling (#593) * fix: improve full screen popup styling * fix: set height to 600 on options window * Release/v0.18.0 (#591) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json --------- Co-authored-by: Victor Kirov Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Fix Tx history screen reload & send form navigation issues (#584) * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * Update dependency array for useEffect * Add comment * Fix memo error * Support script outputs in psbts (#534) * Support script outputs * Update copy * Revert package.json change * Add info message for output script * Use Array.some * Remove unused style * Update core versio and address comments * Remove pretext from output script ui * Refactor render script output logic * Donot show spinner when refetching transaction history data * Fix STX navigation issue * Fix input fields clearance on naviagtion * chore: turn on eslint for staged files on precommit and turn off no-plusplus rule * Fix eslint issues * Update dependency array for useEffect * Add comment * Fix script count * fix: eslint fix --------- Co-authored-by: Tim Man Co-authored-by: Tim Man * Mismatch when verifying the addresses from the ledger device (#580) * Handle min fee rate returned by the API (#583) * Handle min fee rate returned by the API * Add a check for the STX tx min fee * Fix a couple of tslint errors * fix: don't show loader on balance refetch on home screen ENG-2757 (#589) * Add refetch loader * resize loading spinner * Release/v0.18.2 (#600) * release: v0.18.0 * feat: add inscription confirmation for sats connect (#571) * feat: add inscription confirmation for sats connect * implement inscribing and improve event naming * Added complete inscription screen * Add edit fees * Add HTML and SVG preview functionality * change content to content type and allow more previews * implement error designs on main screen * add error modal * fix: completion page not displaying * fix: styling issues and add inscription developer fees * add custom initial fee rate * fix screen height styling * set app height to 600 again * revert screen container size * improve screen container height * moved feerate get one level up * fix: full screen and popup styling * fix screen container * fix app load styling * Make top address selector sticky. Also fixes it for sign psbt and sign message requests * Update todos * fix full screen popup pages * fix account row styling * add json validaiton * add brc-20 and sats names views * add preview menu and fix styling * add preview markdown * switch to single inscribe event * fix preview of file type text and html * Ensure we only use non ordinal UTXOs for inscriptions * update sats-connect arg names and update the dom event name * fix type name * Show correct fiat currency * Use phosphor-icons * update beta core * fix: fee rate and styling issues * clean up icons * Clean up more icons * Update Core * Update sats connect version * Update sats connect * Use `ticker` field instead of `name` for ft and brc-20 token sending (#595) * update package-lock.json * release v0.18.2 * fix send through app fees when inscribing * update package-lock --------- Co-authored-by: Tim Man Co-authored-by: Victor Kirov Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * feat: 1 step brc 20 transfers (#585) * chore: use xverse-core with brc20 hooks * refactor: make reusable fiat row component from sendForm * feat: update send brc20 form to use 1 step mode * feat: update theme elevations to revamp elevations * fix: ensure brc20 currencies are uppercase * fix: remove margin on reusable component tokenImage * feat: create confirm brc20 transaction screen * chore: add jsx key eslint rule * feat: style the brc20 review screen & fees component * feat: implement edit fees for brc20 transfer * fix: show brc20 ticker and image on confirm screen * fix: styling of account header and other brc20 fixes * feat: remove copy buttons from account header * feat: bottom bar will always maintain height * fix: padding and margins on confirm brc20 screen * feat: create a file for common styles and new screen for execute brc20 * fix: styling, react errors, and estimate fees on click edit fees buttons * fix: edit fees button width * fix: account list padding * feat: implement loading status animation * feat: integrate the animations for loading transaction status * fix: clean up TODOs * feat: use content loader in brc20 edit fees * chore: rename the common styled file * fix: fix reset user flow on confirmBrc20Transaction and unused styles * Revert "feat: bottom bar will always maintain height" This reverts commit 07e9fca564beb0a971c4703aa07893a8a9491e5d. * docs: comment * Update src/app/screens/confirmBrc20Transaction/index.tsx Co-authored-by: Victor Kirov * style: use relative import for consistency * style: remove unused comment * docs: add todo to existing comment * fix: reset user flow to '/' and other review fixes * fix: don't clear input if a disallowed key is pressed * fix: ensure only run executeBrc20Transaction once * refactor: simplify usage of useResetUserFlow * chore: remove unused types * chore: update core version to use new brc20 hook * refactor: use useBrc20EstimateTransfer hook * refactor: save edit fees previous state if user clicks cancel * refactor: separate logic to hook * fix: add hook typings and use phosphor icon * fix: actually pass the user input fee rate to execute transfer * fix: disable cancel and confirm buttons while estimate fee is loading * fix: add padding back in account row list on btc select address screen * fix: colors on options and popup css * fix: button positioning on full screen ledger view * refactor: rename one step brc20 send screen and put TODOs for ledger * revert: restore 2 step brc20 send form for ledger support * fix: apply useResetUserFlow update to sendBrc20 * fix: restore 2 step brc20 translations * fix: update new pages to refactored reset user flow hook --------- Co-authored-by: Victor Kirov * update license (#606) * Add scrollbar on all scrollable screens (#582) * Update scrollbar * Include scrollbar styling in theme file * Show transparent scrollbar in account list screen * Remove disable cycle dependency flag * Revert unrelated eslint fixes * Update src/theme/index.ts Co-authored-by: Tim Man * Update theme file * Add missing hidden scrollbar css --------- Co-authored-by: Tim Man * fix: loader on home page issues (#603) Co-authored-by: Tim Man * Fix scrollbar in landing page (#609) * Fix scrollbar in landing page * Revert "Fix scrollbar in landing page" This reverts commit 46c1a8f45cd4f308c84a15db2e57bc284515bbbe. * fix: add back the global CSS to hide scrollbars by default and add display: block on scrollbars CSS when desired --------- Co-authored-by: Tim Man * feat: notice for an non taproot address when sending brc 20 tokens (#602) * refactor: move fiatRow into separate component * feat: add callout and inputFeedback to send brc20 one step screen and include components in ui-library * feat: add conditional callouts to confirm brc20 screen * feat: update the recipient card on confirm brc20 transaction * fix: input borders should reflect errors only, not info feedback * refactor: include a helper function for checking if error state * refactor: make styles consistent in callout.tsx * fix: remove unused icon variants * fix: fix styling and imports on brc20 one step and callout component * refactor: use recipient card props instead of type from core * fix: update success callout color and add to theme * fix: fix estimate fee error not showing, and vertical align of callout body * refactor: use styled components instead of React.createElement * Revert "refactor: use styled components instead of React.createElement" This reverts commit 31faea642fdcc867b0cec707bf2ff8a5814aab44. * fix: disable key presses for - and . on brc20 edit fees * refactor: use styled icon instead of React.createElement * refactor: use fiatAmountText component and allow styling * fix: use input feedback in editFees and update components to allow styled components * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * Release/v0.20.0 (#611) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Show BRC20 token transaction history (#523) * Show BRC20 token transaction history * Handle pending state * Use updated brc20 transaction history response * Update package.lock.json file * fix loading state * Update brc20 history tx title * Update core version to latest --------- Co-authored-by: Denys Hriaznov <36603049+dhriaznov@users.noreply.github.com> * fix rare sats settings copy (#612) * Release/0.21.0 (#613) * chore: merge from upstream develop (#26) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * chore: allow ci build version to pass env vars to build (#27) * feat/eng 2904 implement frontend on web extension (#5) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file --------- Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * release v0.20.0 (#29) * release: v0.19.0 (#607) * release: v0.19.0 * update package-lock * bump xverse core version to fix fee issue --------- Co-authored-by: Yukan * Build analytics tracking for web-extension (#590) * Build analytics tracking for web-extension * Add `/privacy-preferences` screen * Build analytics tracking for web-extension * Update mixpanel tracking logic * Remove unused wallet action name * Add authorize data collection toggler and popup * Update tracking logic * Add translation keys * Update mixpanel tracking logic * Remove unused imports * Make some code changes after PR review, upgrade `xverse-core` package version * Upgrade `xverse-core` package version * Resolve git conflicts * Handling fees with thresholds (#601) * Handling fees with thresholds * Add margin under the high fees warning * Change the high fees warning position for Ordinals & Brc-20 txs * Show the warning if the initial fee from transaction is greater than the threshold * Add high fee warning for one-step brc20 transfer * update copy --------- Co-authored-by: Yukan * Refactor ledger-related logic (#586) * Add STX support for Ledger accounts * Update the copy and ledger account import logic * Update the ledger account import logic for STX support * Add `/add-stx-address-ledger` route for adding stx account * Remove the old case handling when there is no `ordinalsAddress` * Add STX address verification with ledger device * Remove the `/send-stx-ledger` path and update `/send-stx` to handle ledger * Handle regular STX transactions * Remove unused `/review-ledger-stx-tx` path, add STX NFT handling * Remove `/review-ledger-ft-tx` and `/send-ft-ledger` routes, update `/send-ft` to support ledger * Enable STX auth requests for ledger accounts that have an STX address * Add link to the auth popup to add the STX Ledger account * Update screen UI for STX NFT sending * Update copy for STX incoming tx signing * Update STX message signing logic * Update STX-related logic for ledger accounts * Update error handling for STX message signing with ledger * Get rid of `findLedgerAccountId` ledger util, move more copy to locales * Fix cropped button container for tx signing popup * Update address index definition for adding stx address * Update address index definition for address verification and stx tx confirmation * Update address index definition for stx jwt auth * Refactor ledger-related logic * Refactor ledger account import * Fix ledger account import when both BTC and STX options are selected * Refactor ledger address verification screen * Refactor ledger tx confirmation screen * Refactor Add stx address screen * Fix `unsignedTx` type * Add `StacksRecipient` type and make some small code fixes * Add `icon` prop for the `ActionButton` component * Change the ledger steps in a callback * Add types for ledger tx state objects * Fix account index for stx account import, update ledger tx types and utils * Change the import path for `StacksRecipient` * Change the steps numeration for ledger account import * Get rid of unused step changing logic for ledger account import * Add more error handling * Update xverse-core version for testing purposes * Remove caret symbol in xverse-core package * Fix CI build * Make a couple of code fixes according to PR review comments * Add more transaltions * Add the `DEFAULT_TRANSITION_OPTIONS` constant * Make separate components for Steps and StepControls for the Ledger account import flow * Fix style imports * Upgrade the `xverse-core` package version * Upgrade `xverse-core` package version * Disable PSBT tx signing for ledger accounts * update xverse-core * package-lock --------- Co-authored-by: Yukan * release v0.20.0 * chore: bump to xverse-core 1.8.2 for bip322 signing fix * fix: collectibles dashboard should ignore invalid params errors (#33) * fix: put in a quick fix for more location.state serialization bugs (#34) * chore: add support for rare sats in tx confirmation screen (#35) * chore: add support for rare sats in tx confirmation screen * chore: remove logs and fix typo * chore: change unknown icon --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Tim Man Co-authored-by: fede erbes * chore: tidy up zips of each build run and the release uploads (#31) * feat: collectibles ui frontend (#30) * [ENG-2836] feat: Ordinals and BRC-20 collectibles UI * Improve ordinals & brc-20 collectibles fetching logic and UI * Collectible ordinal detail page (#32) * Tim/eng 2933 implement dashboard display of rare sats bundles (#1) * chore: create a hook for rare sats with placeholder data * chore: add some inscription placeholder with image * feat/eng 2933 implement dashboard rare sats tab (#4) * chore: create a collectiblesTabs component with react-tabs * refactor: move nft dashboard logic into hook * feat: move rare sats into separate tab * fix: add tab state styling and move to common.styled * feat: style collectibles header * fix: restyle all grid item colors and add total items * fix: supply total nfts and total rare sats number and type the collectiblesTabs props * style: comments * feat/eng 2934 implement sats bundle UI screen (#6) * Abdulhaseeb/eng 2930 implement settings screen updates (#7) * feat: enable rare sats from settings * fix: disabled UI * fix: typos * Abdulhaseeb/eng 2931 implement info dialogs (#8) * feat: enable rare sats from settings * feat: notice alert and rarities screen * feat: new feature dialog * fix: styles * feat: add UI for rare sats bundle in collectible item details (#2) * fix: ordinal thumbnails were broken (#10) * Add no collectibles and error screens (#11) * feat: integrate rare sats form core (#9) * feat: add rare sats item detail screen (#3) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen --------- Co-authored-by: Tim Man * feat: implement rare sats send screen (#12) * chore: use getUtxoOrdinalBundle to know if a inscription belongs to a bundle (#14) * Abdulhaseeb/eng 2938 implement rare sats confirm screen (#15) * feat: confirm rare sat tx * feat: added warning callout * feat: implement UI for rare sats thumbnails (#16) * feat: add UI for rare sats bundle in collectible item details * feat: implement rare sats details screen * feat: add rare sats thumbnathumbnails * chore: add missing mock data for testing inscriptions belonging to a bundle * Tim/eng 2959 set up test mocks (#17) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen (#18) * fix: react console errors * fix: send rare sat heading and sub text * fix: eslint errors * chore: add mock test cases in hook * fix: back button sometimes has no history * fix: revert merge change * fix: should be no commoners in mock tests * feat: added thumbnail in confirm screen * fix: ui --------- Co-authored-by: Tim Man * fix: rarities screen UI (#19) * chore: fix some todos and issues in rare sats feature (#20) * chore: Unify assets and rarity label in rarityTile and rareSatIcon components * chore: create bundle asset and use it in RareSatsTabGridItem and confirm send screen * chore: add bundle asset component in send screen * chore: make glow optional and remove it from inscribed rare sats asset * chore: add assets to bundle gallery view * chore: remove unsupported media callout. add margin bottom and fix cannot send rare sat individually for gallery view * fix: styling on gallery view for dashboard and rare sats bundle grids (#22) * fix: styling on gallery view for dashboard and rare sats bundle grids * fix: add column layout for rare sats bundle gallery view * fix: rare sats bundle back should always fo to gallery * fix: header spacing rare sats bundle and load more button * feat: add isLoading state for rare sats tab * fix: remove is owned by active account check the user flow resets whenever account changes, so this check is no longer necessary * feat: save collectibles tab index in query params * fix: restore ledger open in new tab behaviour * fix: show info panel regardless of empty state (#23) * Add ordinal attributes in detail screen * chore: fix UI issues (#24) * chore: fix issues with dont see your rare sat banner * chore: fix ui issues in rare sats details screen * Update src/app/screens/nftDashboard/notice.tsx * refactor: use library components and minor styling fixes * fix: rare sat bundle send button width * fix: add separator in gallery view rare sats bundle and styling fixes * fix: minor style fix --------- Co-authored-by: Tim Man * fix: branch merge errors * chore: remove mock data (#28) * chore: remove mock data * chore: add extenral links to scan tool and rare sats post * chore: move external link urls to constants file * Add scrollbar to ordinal detail screen * Adjust text alignment * Update Navigation Bar * Add Share button in extension ordinal detail screen * Include useInscription hook --------- Co-authored-by: Tim Man Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov * Fix `getNextPageParam` param in the `useAddressInscriptionCollections` hook * feat: inscriptions collection page UI components (#36) * chore: use xverse-core with api functions * feat: add ordinals collection screen and route * chore: add prettier organize imports plugin * chore: remove unused eslint disable line * fix: fix tab query params * feat: add ordinals collection route and screen * fix: revert scrollbar change * Tim/eng 2813 inscriptions collection page data fetching pagination (#37) * Make some small code tweaks * Complete Remaining Todos for Ordinal Detail Screen (#38) * Update ordinal detail Ui accodrding to MVP * Get ordinal details from api * Have placeholder incase market data does not exist * Fix navigation and address comments * feat: collection grid items (#39) * Add content skeleton loader for Collectibles tab * Fix border radius for Collectibles skeleton loader * Fix the loader condition in Collectibles tab * Update BRC20 token collection thumbnail in main collectible page * Tim/eng 2833 inscriptions full screen responsive main page collection (#41) * feat: style the send screen including responsive layout * style: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> --------- Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Display collection market data (#40) * Get collection amrket data * Fix alignment on collection page * chore: revert the large package-lock.json diff * Update receive screen and bottom modal (#42) * Update recieve screen * Add updated QR code in recieve screen * Update receive modal * Fix getNextPageParam for const useAddressInscriptionCollections = () => { * Remove unused package * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix: use theme radius Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * Address comments * chore: remove empty unreferenced component * Remove unused background color * fix: layout and spacing on updated bottom modal, receive nft --------- Co-authored-by: Tim Man Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> * fix color for custom switch and c… --------- Co-authored-by: Yukan Co-authored-by: Den <36603049+dhriaznov@users.noreply.github.com> Co-authored-by: Abdul Haseeb Co-authored-by: fede erbes Co-authored-by: Victor Kirov Co-authored-by: Imamah-Zafar <88320460+Imamah-Zafar@users.noreply.github.com> Co-authored-by: Duska.T <55587184+DuskaT021@users.noreply.github.com> Co-authored-by: Mahmoud Aboelenein Co-authored-by: Kyle Fang Co-authored-by: Denys Hriaznov Co-authored-by: Imamah-Zafar Co-authored-by: Jordan K <65149726+jordankzf@users.noreply.github.com> --- .eslintrc.json | 24 +- package-lock.json | 373 ++++++---- package.json | 7 +- src/app/App.tsx | 8 +- src/app/components/barLoader/index.tsx | 5 +- .../components/bundleAsset/bundleAsset.tsx | 4 +- .../collectibleCollage.tsx} | 16 +- .../collectibleCollectionGridItem/index.tsx} | 61 +- .../collectibleDetailTile/index.tsx | 9 +- .../confirmBtcTransactionComponent/index.tsx | 7 +- .../inputOutputComponent.tsx | 2 +- .../confirmStxTransactionComponent/index.tsx | 5 +- .../optionsDialog/optionsDialog.tsx | 2 +- .../components/recipientAddressView/index.tsx | 4 +- .../components/recipientComponent/index.tsx | 4 +- src/app/components/sendForm/index.tsx | 63 +- src/app/components/tabBar/index.tsx | 2 +- src/app/components/tilesSkeletonLoader.tsx | 2 +- src/app/components/tokenTile/index.tsx | 6 +- src/app/components/topRow/index.tsx | 2 +- .../components/transactionSetting/editFee.tsx | 23 +- .../components/transactionSetting/index.tsx | 6 +- .../ContractCallRequest.tsx | 25 +- src/app/components/transferFeeView/index.tsx | 9 +- .../queries/ordinals/useAddressRareSats.ts | 2 +- .../ordinals/useCollectionMarketData.ts | 2 +- src/app/hooks/queries/useBnsName.ts | 16 +- src/app/hooks/queries/useBtcWalletData.ts | 4 +- src/app/hooks/queries/useCoinRates.ts | 2 +- src/app/hooks/queries/useNftDetail.ts | 28 + .../hooks/queries/useStacksCollectibles.ts | 43 +- src/app/hooks/stores/useNftReducer.ts | 23 - src/app/hooks/stores/useOrdinalReducer.ts | 2 +- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 2 +- src/app/hooks/useResetUserFlow.ts | 19 +- src/app/hooks/useTextOrdinalContent.ts | 2 +- src/app/layouts/sendLayout.tsx | 101 +++ src/app/routes/index.tsx | 18 +- src/app/screens/btcSendScreen/index.tsx | 4 +- src/app/screens/coinDashboard/coinHeader.tsx | 6 +- .../confirmBrc20Transaction/editFees.tsx | 2 +- .../screens/confirmBrc20Transaction/index.tsx | 2 +- .../confirmBrc20Transaction/recipientCard.tsx | 2 +- .../confirmInscriptionRequest/index.tsx | 6 +- .../screens/confirmNftTransaction/index.tsx | 20 +- .../confirmOrdinalTransaction/index.tsx | 11 +- .../screens/confirmStxTransaction/index.tsx | 48 +- .../createInscription/CompleteScreen.tsx | 46 +- src/app/screens/home/index.tsx | 30 +- src/app/screens/nftCollection/index.tsx | 270 +++++++ .../screens/nftCollection/useNftCollection.ts | 44 ++ .../screens/nftDashboard/collectiblesTabs.tsx | 20 +- src/app/screens/nftDashboard/index.tsx | 278 +------- .../nftDashboard/inscriptionsTabGridItem.tsx | 9 +- src/app/screens/nftDashboard/nft.tsx | 96 +-- src/app/screens/nftDashboard/nftImage.tsx | 60 +- .../screens/nftDashboard/nftTabGridItem.tsx | 81 +++ .../screens/nftDashboard/receiveNft/index.tsx | 12 +- .../nftDashboard/tilesSkeletonLoader.tsx | 41 -- .../screens/nftDashboard/useNftDashboard.tsx | 270 +++++++ src/app/screens/nftDetail/index.tsx | 669 +++++++++++------- src/app/screens/nftDetail/nftAttribute.tsx | 16 +- src/app/screens/nftDetail/useNftDetail.ts | 78 ++ src/app/screens/ordinalDetail/index.tsx | 1 - .../screens/ordinalDetail/useOrdinalDetail.ts | 4 +- src/app/screens/ordinalsCollection/index.tsx | 33 +- src/app/screens/rareSatsBundle/index.tsx | 4 +- .../screens/rareSatsDetail/rareSatsDetail.tsx | 9 +- src/app/screens/restoreFunds/index.tsx | 6 - .../screens/restoreFunds/restoreBtc/index.tsx | 208 ------ .../restoreFunds/restoreOrdinals/index.tsx | 5 +- src/app/screens/sendBrc20/index.tsx | 23 +- src/app/screens/sendBtc/index.tsx | 30 +- src/app/screens/sendNft/index.tsx | 321 +++++---- src/app/screens/sendOrdinal/index.tsx | 173 ++--- src/app/screens/settings/index.tsx | 5 +- src/app/screens/signPsbtRequest/index.tsx | 125 ++-- src/app/screens/swap/swapTokenBlock/index.tsx | 15 +- .../screens/swap/useCurrencyConversion.tsx | 14 +- src/app/screens/transactionStatus/index.tsx | 25 +- src/app/stores/index.ts | 11 +- .../stores/nftData/actions/actionCreator.ts | 11 +- src/app/stores/nftData/actions/types.ts | 13 +- src/app/stores/nftData/reducer.ts | 7 - .../stores/wallet/actions/actionCreators.ts | 34 +- src/app/stores/wallet/actions/types.ts | 26 +- src/app/stores/wallet/reducer.ts | 23 +- src/app/ui-library/snackBar.tsx | 75 ++ src/app/utils/nfts.ts | 36 + src/assets/img/nftDashboard/bns.svg | 9 + .../img/nftDashboard/ic_nft_diamond.svg | 3 - src/assets/img/nftDashboard/nft_user.svg | 4 - src/locales/en.json | 14 +- src/react-app-env.d.ts | 1 + 94 files changed, 2492 insertions(+), 1830 deletions(-) rename src/app/components/{bundleAsset/rareSatsCollage.tsx => collectibleCollage/collectibleCollage.tsx} (66%) rename src/app/{screens/ordinalsCollection/ordinalsCollectionGridItem.tsx => components/collectibleCollectionGridItem/index.tsx} (50%) create mode 100644 src/app/hooks/queries/useNftDetail.ts delete mode 100644 src/app/hooks/stores/useNftReducer.ts create mode 100644 src/app/layouts/sendLayout.tsx create mode 100644 src/app/screens/nftCollection/index.tsx create mode 100644 src/app/screens/nftCollection/useNftCollection.ts create mode 100644 src/app/screens/nftDashboard/nftTabGridItem.tsx delete mode 100644 src/app/screens/nftDashboard/tilesSkeletonLoader.tsx create mode 100644 src/app/screens/nftDashboard/useNftDashboard.tsx create mode 100644 src/app/screens/nftDetail/useNftDetail.ts delete mode 100644 src/app/screens/restoreFunds/restoreBtc/index.tsx create mode 100644 src/app/ui-library/snackBar.tsx create mode 100644 src/app/utils/nfts.ts create mode 100644 src/assets/img/nftDashboard/bns.svg delete mode 100644 src/assets/img/nftDashboard/ic_nft_diamond.svg delete mode 100644 src/assets/img/nftDashboard/nft_user.svg diff --git a/.eslintrc.json b/.eslintrc.json index e8b938d9e..5f3531fda 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,26 +20,20 @@ "sourceType": "module", "project": "./tsconfig.json" }, - "plugins": [ - "react", - "prettier", - "eslint-plugin-no-inline-styles", - "@tanstack/query" - ], + "plugins": ["react", "prettier", "eslint-plugin-no-inline-styles", "@tanstack/query"], "rules": { "consistent-return": "off", "import/prefer-default-export": 1, "no-restricted-imports": [ "warn", { - "patterns": [ - "@secretkeylabs/xverse-core/**/*" - ] + "patterns": ["@secretkeylabs/xverse-core/**/*"] } ], "no-promise-executor-return": "warn", "max-len": "off", "no-inline-styles/no-inline-styles": 2, + "no-nested-ternary": "off", "no-param-reassign": "off", "react-hooks/exhaustive-deps": "warn", "react/jsx-key": "warn", @@ -61,16 +55,8 @@ "settings": { "import/resolver": { "node": { - "extensions": [ - ".js", - ".jsx", - ".ts", - ".tsx" - ], - "moduleDirectory": [ - "node_modules", - "src/" - ] + "extensions": [".js", ".jsx", ".ts", ".tsx"], + "moduleDirectory": ["node_modules", "src/"] } } } diff --git a/package-lock.json b/package-lock.json index 6d2709260..736fcde5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "xverse-web-extension", - "version": "0.22.1", + "version": "0.23.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xverse-web-extension", - "version": "0.22.1", + "version": "0.23.0", "dependencies": { "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "2.3.0", + "@secretkeylabs/xverse-core": "3.0.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", @@ -47,6 +47,7 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", "react-i18next": "^11.18.6", + "react-is-visible": "^1.2.0", "react-modal": "^3.15.1", "react-number-format": "^5.0.0", "react-qr-code": "^2.0.8", @@ -61,7 +62,7 @@ "redux": "^4.0.5", "redux-persist": "^6.0.0", "redux-state-sync": "^3.1.4", - "sats-connect": "1.1.1", + "sats-connect": "1.1.2", "stream-browserify": "^3.0.0", "string-to-color": "^2.2.2", "styled-components": "^5.3.5", @@ -3407,9 +3408,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "2.3.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/2.3.0/024dea2b4f44fb6cc84c7125b8adf381f8f2791d", - "integrity": "sha512-zE/C/e1ri551rVLJTNnJRDfLcXujOtdfTnW6nanIrEAjmNQxXH1DAploudDkRMDnG9JQBHrFnuW9JpeAGR4Y+g==", + "version": "3.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.0.0/90bd130bc7b3f9c0739e65d34772d6a550b5818d", + "integrity": "sha512-dtPkHY+VSNf/iwta3cSO2ZsKxdURTM4E+FPCwrotXc85MfxO0MIjyRa4VlOCtHsj8fNS2yH+KHg3uClLK9+WiQ==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -3625,14 +3626,14 @@ } }, "node_modules/@stacks/auth": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", - "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", - "dependencies": { - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", - "@stacks/profile": "^6.7.0", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.9.0.tgz", + "integrity": "sha512-tBOB+H/96TUNK9pKmr1YQoiIItUFp2ms5RCNYPSjy3/lbIYYJYtw/O2fOS78fVQvCCpuObhhO65AVsrE/IzQeg==", + "dependencies": { + "@stacks/common": "^6.8.1", + "@stacks/encryption": "^6.9.0", + "@stacks/network": "^6.8.1", + "@stacks/profile": "^6.9.0", "cross-fetch": "^3.1.5", "jsontokens": "^4.0.1" } @@ -3663,15 +3664,24 @@ "@scure/base": "~1.1.0" } }, + "node_modules/@stacks/auth/node_modules/@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, "node_modules/@stacks/auth/node_modules/@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", + "integrity": "sha512-hbpZ47eYgw9ZH5ly+GSgvw2Ffsu9L6d++2XIhvYSzL7yxYl4m1+FV5QYdJthJ2AS3vi8cI5otE254HTfCrhKzg==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", @@ -3679,10 +3689,19 @@ "varuint-bitcoin": "^1.1.2" } }, + "node_modules/@stacks/auth/node_modules/@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "dependencies": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } + }, "node_modules/@stacks/common": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.5.tgz", - "integrity": "sha512-6v2AVHTTryvl1Govu5rmBXLywAyen2fU3doMCx/7Lk/tFLc4OjMEx4uf1wzpPx1zw/fwJnvoz74OrT/RSALDYw==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", "dependencies": { "@types/bn.js": "^5.1.0", "@types/node": "^18.0.4" @@ -3898,11 +3917,12 @@ } }, "node_modules/@stacks/network": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.5.tgz", - "integrity": "sha512-lw7+g6UhOpvWasMeRYMb2OGRKm9ptYkGt27Usg3Eo0z/pu20jZxvHXLBMdDQqxNQOOmwiG4FadICnwTlmnHaqw==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "peer": true, "dependencies": { - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "cross-fetch": "^3.1.5" } }, @@ -3915,13 +3935,13 @@ } }, "node_modules/@stacks/profile": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", - "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.9.0.tgz", + "integrity": "sha512-sIR60DsAHi8C6zGqKqSe1r2hXTMHgwrJkX3fAaP3de40KeplZ2bkE+0B83yismEeU2baNc+AukyVvWJv0PfP0A==", "dependencies": { - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", - "@stacks/transactions": "^6.7.0", + "@stacks/common": "^6.8.1", + "@stacks/network": "^6.8.1", + "@stacks/transactions": "^6.9.0", "jsontokens": "^4.0.1", "schema-inspector": "^2.0.2", "zone-file": "^2.0.0-beta.3" @@ -3938,15 +3958,33 @@ } ] }, + "node_modules/@stacks/profile/node_modules/@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, + "node_modules/@stacks/profile/node_modules/@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "dependencies": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } + }, "node_modules/@stacks/profile/node_modules/@stacks/transactions": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", - "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", + "integrity": "sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", + "@stacks/common": "^6.8.1", + "@stacks/network": "^6.8.1", "c32check": "^2.0.0", "lodash.clonedeep": "^4.5.0" } @@ -3957,14 +3995,14 @@ "integrity": "sha512-Mw5dBPx3DySPupwaq0iBdm1WdEVXIfhjUVaTjI2iSyzWz4Fgs3U7JCaAezLbgNu7Q69c/ZN4JUDWuo9FVjy7oA==" }, "node_modules/@stacks/storage": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", - "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", - "dependencies": { - "@stacks/auth": "^6.7.0", - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.9.0.tgz", + "integrity": "sha512-aZ3tOnwRSk5cHQh9ButhfHDvAylNVxPRQzeSB8PydHfyib4XL7fSAJwizzEWNgJV4dovqW2Nsy8gm/4rM/oFKQ==", + "dependencies": { + "@stacks/auth": "^6.9.0", + "@stacks/common": "^6.8.1", + "@stacks/encryption": "^6.9.0", + "@stacks/network": "^6.8.1", "base64-js": "^1.5.1", "jsontokens": "^4.0.1" } @@ -3995,15 +4033,24 @@ "@scure/base": "~1.1.0" } }, + "node_modules/@stacks/storage/node_modules/@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, "node_modules/@stacks/storage/node_modules/@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", + "integrity": "sha512-hbpZ47eYgw9ZH5ly+GSgvw2Ffsu9L6d++2XIhvYSzL7yxYl4m1+FV5QYdJthJ2AS3vi8cI5otE254HTfCrhKzg==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", @@ -4011,6 +4058,15 @@ "varuint-bitcoin": "^1.1.2" } }, + "node_modules/@stacks/storage/node_modules/@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "dependencies": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } + }, "node_modules/@stacks/transactions": { "version": "4.3.8", "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", @@ -4418,9 +4474,9 @@ } }, "node_modules/@testing-library/dom": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", - "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -6654,13 +6710,13 @@ "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" }, "node_modules/bitcoinjs-lib": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.3.tgz", - "integrity": "sha512-TYXs/Qf+GNk2nnsB9HrXWqzFuEgCg0Gx+v3UW3B8VuceFHXVvhT+7hRnTSvwkX0i8rz2rtujeU6gFaDcFqYFDw==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.5.tgz", + "integrity": "sha512-yuf6xs9QX/E8LWE2aMJPNd0IxGofwfuVOiYdNUESkc+2bHHVKjhJd8qewqapeoolh9fihzHGoDCB5Vkr57RZCQ==", "dependencies": { "@noble/hashes": "^1.2.0", "bech32": "^2.0.0", - "bip174": "^2.1.0", + "bip174": "^2.1.1", "bs58check": "^3.0.1", "typeforce": "^1.11.3", "varuint-bitcoin": "^1.1.2" @@ -15691,6 +15747,19 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "peer": true }, + "node_modules/react-is-visible": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-is-visible/-/react-is-visible-1.2.0.tgz", + "integrity": "sha512-052RH7aHdKrABOBH12wvS2zTAzJ8MnaswPvX2AQGq5wxvD8BnQ5vcnf0cA0cj2g4bjH0+qXz1AIkEL9ZlnN23A==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "hoist-non-react-statics": "3.3.2" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -16340,9 +16409,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sats-connect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.1.tgz", - "integrity": "sha512-cckwlFc0gnYNZsNUsH9xACcpIeD+XdbSvtYhkGZSRqNeqzbqgdVI50mD4mzxs1ILbUGLjdTCINohVP6WbbvhcA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.2.tgz", + "integrity": "sha512-nJmCV69WgMNGH9H2cTTH/HsO9wEYS7g0AvnCNNgY5fezEJmA6jNpRMP4Xidv/c0xWL1uGOUHPLJEEOSG4NoneQ==", "dependencies": { "jsontokens": "^4.0.1", "process": "^0.11.10", @@ -16370,9 +16439,9 @@ } }, "node_modules/schema-inspector": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.3.tgz", - "integrity": "sha512-Q9mpYxrP3w6CpHRfnh3QLOE1urkGTLvnl7xgVH7fsu0HYJUZenUASUr4j/pf7bAxShh+4R3Ta8ZgVKak1b2wyA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.1.0.tgz", + "integrity": "sha512-3bmQVhbA01/EW8cZin4vIpqlpNU2SIy4BhKCfCgogJ3T/L76dLx3QAE+++4o+dNT33sa+SN9vOJL7iHiHFjiNg==", "dependencies": { "async": "~2.6.3" } @@ -21432,9 +21501,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "2.3.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/2.3.0/024dea2b4f44fb6cc84c7125b8adf381f8f2791d", - "integrity": "sha512-zE/C/e1ri551rVLJTNnJRDfLcXujOtdfTnW6nanIrEAjmNQxXH1DAploudDkRMDnG9JQBHrFnuW9JpeAGR4Y+g==", + "version": "3.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.0.0/90bd130bc7b3f9c0739e65d34772d6a550b5818d", + "integrity": "sha512-dtPkHY+VSNf/iwta3cSO2ZsKxdURTM4E+FPCwrotXc85MfxO0MIjyRa4VlOCtHsj8fNS2yH+KHg3uClLK9+WiQ==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -21626,14 +21695,14 @@ } }, "@stacks/auth": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.7.0.tgz", - "integrity": "sha512-By0KuZlC0UNiD+q74TIPre0todQjsTPLWDOPskR0Rf9WKZMpw0YSaW02mdggJd+/oJjvDDidUxlPlsiKYe8d+w==", - "requires": { - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", - "@stacks/profile": "^6.7.0", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/auth/-/auth-6.9.0.tgz", + "integrity": "sha512-tBOB+H/96TUNK9pKmr1YQoiIItUFp2ms5RCNYPSjy3/lbIYYJYtw/O2fOS78fVQvCCpuObhhO65AVsrE/IzQeg==", + "requires": { + "@stacks/common": "^6.8.1", + "@stacks/encryption": "^6.9.0", + "@stacks/network": "^6.8.1", + "@stacks/profile": "^6.9.0", "cross-fetch": "^3.1.5", "jsontokens": "^4.0.1" }, @@ -21652,28 +21721,46 @@ "@scure/base": "~1.1.0" } }, + "@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "requires": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, "@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", + "integrity": "sha512-hbpZ47eYgw9ZH5ly+GSgvw2Ffsu9L6d++2XIhvYSzL7yxYl4m1+FV5QYdJthJ2AS3vi8cI5otE254HTfCrhKzg==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", "ripemd160-min": "^0.0.6", "varuint-bitcoin": "^1.1.2" } + }, + "@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "requires": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } } } }, "@stacks/common": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.5.tgz", - "integrity": "sha512-6v2AVHTTryvl1Govu5rmBXLywAyen2fU3doMCx/7Lk/tFLc4OjMEx4uf1wzpPx1zw/fwJnvoz74OrT/RSALDYw==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", "requires": { "@types/bn.js": "^5.1.0", "@types/node": "^18.0.4" @@ -21882,11 +21969,12 @@ } }, "@stacks/network": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.5.tgz", - "integrity": "sha512-lw7+g6UhOpvWasMeRYMb2OGRKm9ptYkGt27Usg3Eo0z/pu20jZxvHXLBMdDQqxNQOOmwiG4FadICnwTlmnHaqw==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "peer": true, "requires": { - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "cross-fetch": "^3.1.5" } }, @@ -21899,13 +21987,13 @@ } }, "@stacks/profile": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.7.0.tgz", - "integrity": "sha512-jwCpSFMmxL/1K5zWdhQ9/CPWEylW0hnMjGKmQNIUtLJO6+qnmp2Jr+Pc6vm6V5jE+L2wtrumv89TKJisrxg/Kg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/profile/-/profile-6.9.0.tgz", + "integrity": "sha512-sIR60DsAHi8C6zGqKqSe1r2hXTMHgwrJkX3fAaP3de40KeplZ2bkE+0B83yismEeU2baNc+AukyVvWJv0PfP0A==", "requires": { - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", - "@stacks/transactions": "^6.7.0", + "@stacks/common": "^6.8.1", + "@stacks/network": "^6.8.1", + "@stacks/transactions": "^6.9.0", "jsontokens": "^4.0.1", "schema-inspector": "^2.0.2", "zone-file": "^2.0.0-beta.3" @@ -21916,15 +22004,33 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==" }, + "@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "requires": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, + "@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "requires": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } + }, "@stacks/transactions": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.7.0.tgz", - "integrity": "sha512-M/SxSkKk78cTa7hLxq36YcN+NnnSanvKgINfXnQGTL31dzvH3UfQbRzPZHEkjPRRN82E9XC0scu6Kpwq+qVbtA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", + "integrity": "sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.5", - "@stacks/network": "^6.5.5", + "@stacks/common": "^6.8.1", + "@stacks/network": "^6.8.1", "c32check": "^2.0.0", "lodash.clonedeep": "^4.5.0" } @@ -21937,14 +22043,14 @@ "integrity": "sha512-Mw5dBPx3DySPupwaq0iBdm1WdEVXIfhjUVaTjI2iSyzWz4Fgs3U7JCaAezLbgNu7Q69c/ZN4JUDWuo9FVjy7oA==" }, "@stacks/storage": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.7.0.tgz", - "integrity": "sha512-Ega/AudDGWII10WjVM1/6gF4XHvGM022O1Gxau4pRbHXxzq5gKafkqQqRI8/O+rYllBclCZfKOkSNNGaEpgzsQ==", - "requires": { - "@stacks/auth": "^6.7.0", - "@stacks/common": "^6.5.5", - "@stacks/encryption": "^6.7.0", - "@stacks/network": "^6.5.5", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/storage/-/storage-6.9.0.tgz", + "integrity": "sha512-aZ3tOnwRSk5cHQh9ButhfHDvAylNVxPRQzeSB8PydHfyib4XL7fSAJwizzEWNgJV4dovqW2Nsy8gm/4rM/oFKQ==", + "requires": { + "@stacks/auth": "^6.9.0", + "@stacks/common": "^6.8.1", + "@stacks/encryption": "^6.9.0", + "@stacks/network": "^6.8.1", "base64-js": "^1.5.1", "jsontokens": "^4.0.1" }, @@ -21963,21 +22069,39 @@ "@scure/base": "~1.1.0" } }, + "@stacks/common": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "requires": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, "@stacks/encryption": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.7.0.tgz", - "integrity": "sha512-31eh+Wd14/+4rsD3HGtbpfWl7T30aZHTJsCdK5+XWvl4umJQytNkTMH3nPHoouxfLW0lR9rHPm8gTntblKMQhg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", + "integrity": "sha512-hbpZ47eYgw9ZH5ly+GSgvw2Ffsu9L6d++2XIhvYSzL7yxYl4m1+FV5QYdJthJ2AS3vi8cI5otE254HTfCrhKzg==", "requires": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.5", + "@stacks/common": "^6.8.1", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", "ripemd160-min": "^0.0.6", "varuint-bitcoin": "^1.1.2" } + }, + "@stacks/network": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "requires": { + "@stacks/common": "^6.8.1", + "cross-fetch": "^3.1.5" + } } } }, @@ -22312,9 +22436,9 @@ } }, "@testing-library/dom": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.1.tgz", - "integrity": "sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", "peer": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -24109,13 +24233,13 @@ "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" }, "bitcoinjs-lib": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.3.tgz", - "integrity": "sha512-TYXs/Qf+GNk2nnsB9HrXWqzFuEgCg0Gx+v3UW3B8VuceFHXVvhT+7hRnTSvwkX0i8rz2rtujeU6gFaDcFqYFDw==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.5.tgz", + "integrity": "sha512-yuf6xs9QX/E8LWE2aMJPNd0IxGofwfuVOiYdNUESkc+2bHHVKjhJd8qewqapeoolh9fihzHGoDCB5Vkr57RZCQ==", "requires": { "@noble/hashes": "^1.2.0", "bech32": "^2.0.0", - "bip174": "^2.1.0", + "bip174": "^2.1.1", "bs58check": "^3.0.1", "typeforce": "^1.11.3", "varuint-bitcoin": "^1.1.2" @@ -30888,6 +31012,15 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "peer": true }, + "react-is-visible": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-is-visible/-/react-is-visible-1.2.0.tgz", + "integrity": "sha512-052RH7aHdKrABOBH12wvS2zTAzJ8MnaswPvX2AQGq5wxvD8BnQ5vcnf0cA0cj2g4bjH0+qXz1AIkEL9ZlnN23A==", + "requires": { + "@babel/runtime": "^7.12.5", + "hoist-non-react-statics": "3.3.2" + } + }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -31348,9 +31481,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sats-connect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.1.tgz", - "integrity": "sha512-cckwlFc0gnYNZsNUsH9xACcpIeD+XdbSvtYhkGZSRqNeqzbqgdVI50mD4mzxs1ILbUGLjdTCINohVP6WbbvhcA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sats-connect/-/sats-connect-1.1.2.tgz", + "integrity": "sha512-nJmCV69WgMNGH9H2cTTH/HsO9wEYS7g0AvnCNNgY5fezEJmA6jNpRMP4Xidv/c0xWL1uGOUHPLJEEOSG4NoneQ==", "requires": { "jsontokens": "^4.0.1", "process": "^0.11.10", @@ -31375,9 +31508,9 @@ } }, "schema-inspector": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.0.3.tgz", - "integrity": "sha512-Q9mpYxrP3w6CpHRfnh3QLOE1urkGTLvnl7xgVH7fsu0HYJUZenUASUr4j/pf7bAxShh+4R3Ta8ZgVKak1b2wyA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-2.1.0.tgz", + "integrity": "sha512-3bmQVhbA01/EW8cZin4vIpqlpNU2SIy4BhKCfCgogJ3T/L76dLx3QAE+++4o+dNT33sa+SN9vOJL7iHiHFjiNg==", "requires": { "async": "~2.6.3" } diff --git a/package.json b/package.json index 1afd69db9..8dcc16c02 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xverse-web-extension", "description": "A Bitcoin wallet for Web3", - "version": "0.22.1", + "version": "0.23.0", "private": true, "engines": { "node": "^18.18.2" @@ -10,7 +10,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "2.3.0", + "@secretkeylabs/xverse-core": "3.0.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", @@ -46,6 +46,7 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", "react-i18next": "^11.18.6", + "react-is-visible": "^1.2.0", "react-modal": "^3.15.1", "react-number-format": "^5.0.0", "react-qr-code": "^2.0.8", @@ -60,7 +61,7 @@ "redux": "^4.0.5", "redux-persist": "^6.0.0", "redux-state-sync": "^3.1.4", - "sats-connect": "1.1.1", + "sats-connect": "1.1.2", "stream-browserify": "^3.0.0", "string-to-color": "^2.2.2", "styled-components": "^5.3.5", diff --git a/src/app/App.tsx b/src/app/App.tsx index 215a33c1b..73c0f2138 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -2,16 +2,16 @@ import LoadingScreen from '@components/loadingScreen'; import rootStore from '@stores/index'; import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { MIX_PANEL_TOKEN } from '@utils/constants'; import { queryClient } from '@utils/query'; +import mixpanel from 'mixpanel-browser'; +import { useEffect } from 'react'; import { Toaster } from 'react-hot-toast'; import { Provider } from 'react-redux'; import { RouterProvider } from 'react-router-dom'; import { PersistGate } from 'redux-persist/integration/react'; import { ThemeProvider } from 'styled-components'; import '../locales'; -import { useEffect } from 'react'; -import mixpanel from 'mixpanel-browser'; -import { MIX_PANEL_TOKEN } from '@utils/constants'; import Theme from '../theme'; import GlobalStyle from '../theme/global'; import SessionGuard from './components/guards/session'; @@ -40,7 +40,7 @@ function App(): JSX.Element { - + diff --git a/src/app/components/barLoader/index.tsx b/src/app/components/barLoader/index.tsx index 5c53d37da..428a9cc76 100644 --- a/src/app/components/barLoader/index.tsx +++ b/src/app/components/barLoader/index.tsx @@ -77,8 +77,8 @@ export function BetterBarLoader({ height, className, }: { - width: number; - height: number; + width: number | string; + height: number | string; className?: string; }) { return ( @@ -88,7 +88,6 @@ export function BetterBarLoader({ interval={0.1} width={width} height={height} - viewBox={`0 0 ${width} ${height}`} backgroundColor={Theme.colors.elevation3} foregroundColor={Theme.colors.grey} className={className} diff --git a/src/app/components/bundleAsset/bundleAsset.tsx b/src/app/components/bundleAsset/bundleAsset.tsx index 4ab31b673..284534cba 100644 --- a/src/app/components/bundleAsset/bundleAsset.tsx +++ b/src/app/components/bundleAsset/bundleAsset.tsx @@ -2,7 +2,7 @@ import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; import { Bundle } from '@utils/rareSats'; import styled from 'styled-components'; -import RareSatsCollage from './rareSatsCollage'; +import CollectibleCollage from '../collectibleCollage/collectibleCollage'; const ImageContainer = styled.div` display: flex; @@ -29,7 +29,7 @@ function BundleAsset({ bundle }: Props) { return ( {isMoreThanOneItem ? ( - + ) : ( diff --git a/src/app/components/bundleAsset/rareSatsCollage.tsx b/src/app/components/collectibleCollage/collectibleCollage.tsx similarity index 66% rename from src/app/components/bundleAsset/rareSatsCollage.tsx rename to src/app/components/collectibleCollage/collectibleCollage.tsx index b5d0a7466..e15ee56c5 100644 --- a/src/app/components/bundleAsset/rareSatsCollage.tsx +++ b/src/app/components/collectibleCollage/collectibleCollage.tsx @@ -1,4 +1,6 @@ import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; +import Nft from '@screens/nftDashboard/nft'; +import { NonFungibleToken } from '@secretkeylabs/xverse-core'; import { BundleItem } from '@utils/rareSats'; import styled from 'styled-components'; @@ -31,15 +33,16 @@ const RemainingAmountOfAssets = styled.div((props) => ({ borderRadius: props.theme.radius(1), background: props.theme.colors.elevation1, p: { - ...props.theme.body_medium_m, - fontSize: 'calc(2vw + 2vh)', + ...props.theme.typography.body_medium_m, + fontSize: 'calc((2vw + 2vh)* 0.8)', color: props.theme.colors.white_0, }, })); -function RareSatsCollage({ items }: { items: Array }) { +function CollectibleCollage({ items }: { items: Array }) { const moreThanFourItems = items.length > 4; + const isBundleItem = (item: any): boolean => (item as BundleItem).rarity_ranking !== undefined; return ( {items.slice(0, 4).map((item, index) => ( @@ -49,8 +52,11 @@ function RareSatsCollage({ items }: { items: Array }) {

+{items.length - 4}

+ ) : // Conditionally render RareSatAsset if item is a BundleItem otherwise render Nft + isBundleItem(item) ? ( + ) : ( - + )} ))} @@ -58,4 +64,4 @@ function RareSatsCollage({ items }: { items: Array }) { ); } -export default RareSatsCollage; +export default CollectibleCollage; diff --git a/src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx b/src/app/components/collectibleCollectionGridItem/index.tsx similarity index 50% rename from src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx rename to src/app/components/collectibleCollectionGridItem/index.tsx index 933c6d92a..d11c4be81 100644 --- a/src/app/screens/ordinalsCollection/ordinalsCollectionGridItem.tsx +++ b/src/app/components/collectibleCollectionGridItem/index.tsx @@ -1,14 +1,7 @@ -import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; -import OrdinalImage from '@screens/ordinals/ordinalImage'; -import type { Inscription } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; -import { - getInscriptionsCollectionGridItemId, - getInscriptionsCollectionGridItemSubText, - getInscriptionsCollectionGridItemSubTextColor, -} from '@utils/inscriptions'; -import { useNavigate } from 'react-router-dom'; +import { ReactNode } from 'react'; import styled from 'styled-components'; +import { Color } from 'theme'; const InfoContainer = styled.div` display: flex; @@ -22,6 +15,7 @@ const StyledItemId = styled(StyledP)` text-wrap: nowrap; overflow: hidden; width: 100%; + text-overflow: ellipsis; `; const StyledItemSub = styled(StyledP)` @@ -49,35 +43,46 @@ const GridItemContainer = styled.button` flex-direction: column; background: transparent; gap: ${(props) => props.theme.space.s}; + cursor: ${(props) => (props.onClick ? 'pointer' : 'initial')}; + width: 100%; `; -export function OrdinalsCollectionGridItem({ item }: { item: Inscription }) { - const navigate = useNavigate(); - const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); - - const handleOnClick = () => { - setSelectedOrdinalDetails(item); - navigate(`/nft-dashboard/ordinal-detail/${item.id}`); - }; - - const itemId = getInscriptionsCollectionGridItemId(item); - const itemSubText = getInscriptionsCollectionGridItemSubText(item); - const itemSubTextColor = getInscriptionsCollectionGridItemSubTextColor(item); +interface Props { + item: any; + itemId: string; + itemSubText?: string; + itemSubTextColor?: Color; + children: ReactNode; + onClick?: (collectible: any) => void; +} +export function CollectibleCollectionGridItem({ + item, + itemId, + itemSubText, + itemSubTextColor, + children, + onClick, +}: Props) { + const handleOnClick = onClick + ? () => { + onClick(item); + } + : undefined; return ( - - - + {children} {itemId} - - {itemSubText} - + {itemSubText && ( + + {itemSubText} + + )} ); } -export default OrdinalsCollectionGridItem; +export default CollectibleCollectionGridItem; diff --git a/src/app/components/collectibleDetailTile/index.tsx b/src/app/components/collectibleDetailTile/index.tsx index 7ef735d22..88058a8dd 100644 --- a/src/app/components/collectibleDetailTile/index.tsx +++ b/src/app/components/collectibleDetailTile/index.tsx @@ -7,17 +7,17 @@ interface DetailSectionProps { isGallery: boolean; } const DescriptionHeadingText = styled.p((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white['400'], + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_400, marginBottom: props.theme.spacing(2), whiteSpace: 'nowrap', textAlign: props.isGallery ? 'right' : 'left', })); const DescriptionValueText = styled.p((props) => ({ - ...props.theme.body_medium_m, + ...props.theme.typography.body_medium_m, wordWrap: 'break-word', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, textAlign: !props.isGallery ? 'left' : 'right', maxWidth: 375, })); @@ -30,6 +30,7 @@ const Container = styled.div((props) => ({ display: 'flex', flexDirection: props.isColumnAlignment ? 'column' : 'row', width: '100%', + flex: 1, justifyContent: 'space-between', })); diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 551364017..a39114420 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -10,7 +10,6 @@ import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; import { - BtcUtxoDataResponse, ErrorCodes, getBtcFiatEquivalent, ResponseError, @@ -130,7 +129,7 @@ interface Props { assetDetail?: string; assetDetailValue?: string; isRestoreFundFlow?: boolean; - nonOrdinalUtxos?: BtcUtxoDataResponse[]; + nonOrdinalUtxos?: UTXO[]; isBtcSendBrowserTx?: boolean; currencyType?: CurrencyTypes; isPartOfBundle?: boolean; @@ -318,7 +317,7 @@ function ConfirmBtcTransactionComponent({ const newFee = new BigNumber(modifiedFee); setCurrentFee(newFee); const seed = await getSeed(); - setCurrentFeeRate(new BigNumber(feeRate ?? '')); + setCurrentFeeRate(new BigNumber(feeRate!)); if (ordinalTxUtxo) ordinalMutate({ txFee: modifiedFee, seedPhrase: seed }); else if (isRestoreFundFlow) { mutateSignNonOrdinalBtcTransaction({ txFee: modifiedFee, seedPhrase: seed }); @@ -439,7 +438,7 @@ function ConfirmBtcTransactionComponent({ )} diff --git a/src/app/components/confirmBtcTransactionComponent/inputOutputComponent.tsx b/src/app/components/confirmBtcTransactionComponent/inputOutputComponent.tsx index d120ccba0..1703f7d00 100644 --- a/src/app/components/confirmBtcTransactionComponent/inputOutputComponent.tsx +++ b/src/app/components/confirmBtcTransactionComponent/inputOutputComponent.tsx @@ -97,7 +97,7 @@ const Button = styled.button((props) => ({ interface Props { address: string[]; - parsedPsbt: ParsedPSBT; + parsedPsbt: ParsedPSBT | undefined; isExpanded: boolean; onArrowClick: () => void; } diff --git a/src/app/components/confirmStxTransactionComponent/index.tsx b/src/app/components/confirmStxTransactionComponent/index.tsx index 67b4498bc..d5937ee86 100644 --- a/src/app/components/confirmStxTransactionComponent/index.tsx +++ b/src/app/components/confirmStxTransactionComponent/index.tsx @@ -12,16 +12,17 @@ import useNetworkSelector from '@hooks/useNetwork'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; import Transport from '@ledgerhq/hw-transport-webusb'; +import type { StacksTransaction } from '@secretkeylabs/xverse-core'; import { getNonce, + microstacksToStx, setFee, setNonce, signLedgerStxTransaction, signMultiStxTransactions, signTransaction, + stxToMicrostacks, } from '@secretkeylabs/xverse-core'; -import { microstacksToStx, stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; -import { StacksTransaction } from '@secretkeylabs/xverse-core/types'; import { isHardwareAccount } from '@utils/helper'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; diff --git a/src/app/components/optionsDialog/optionsDialog.tsx b/src/app/components/optionsDialog/optionsDialog.tsx index 084d8cbf9..fd151bfdf 100644 --- a/src/app/components/optionsDialog/optionsDialog.tsx +++ b/src/app/components/optionsDialog/optionsDialog.tsx @@ -23,7 +23,7 @@ const OuterContainer = styled.div({ left: 0, right: 0, backgroundColor: 'transparent', - zIndex: 1, + zIndex: 2, }); interface Props { diff --git a/src/app/components/recipientAddressView/index.tsx b/src/app/components/recipientAddressView/index.tsx index cdc3d5d75..54e71e372 100644 --- a/src/app/components/recipientAddressView/index.tsx +++ b/src/app/components/recipientAddressView/index.tsx @@ -1,6 +1,5 @@ import ArrowSquareOut from '@assets/img/arrow_square_out.svg'; import { useBnsName } from '@hooks/queries/useBnsName'; -import useNetworkSelector from '@hooks/useNetwork'; import { getExplorerUrl } from '@utils/helper'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -56,9 +55,8 @@ interface Props { recipient: string; } function RecipientAddressView({ recipient }: Props) { - const selectedNetwork = useNetworkSelector(); const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' }); - const bnsName = useBnsName(recipient, selectedNetwork); + const bnsName = useBnsName(recipient); const handleOnPress = () => { window.open(getExplorerUrl(recipient)); }; diff --git a/src/app/components/recipientComponent/index.tsx b/src/app/components/recipientComponent/index.tsx index 222bf0d8b..62b88cb2c 100644 --- a/src/app/components/recipientComponent/index.tsx +++ b/src/app/components/recipientComponent/index.tsx @@ -146,8 +146,8 @@ function RecipientComponent({ amountInCurrency = getFiatEquivalent( Number(value), currencyType, - stxBtcRate, - btcFiatRate, + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), fungibleToken, ); } diff --git a/src/app/components/sendForm/index.tsx b/src/app/components/sendForm/index.tsx index 38e4e060d..c10231387 100644 --- a/src/app/components/sendForm/index.tsx +++ b/src/app/components/sendForm/index.tsx @@ -1,13 +1,15 @@ import ActionButton from '@components/button'; import InfoContainer from '@components/infoContainer'; import TokenImage from '@components/tokenImage'; -import { useBnsName, useBNSResolver } from '@hooks/queries/useBnsName'; +import { useBnsName, useBnsResolver } from '@hooks/queries/useBnsName'; import useDebounce from '@hooks/useDebounce'; -import useNetworkSelector from '@hooks/useNetwork'; import useWalletSelector from '@hooks/useWalletSelector'; -import { getBtcEquivalent, getStxTokenEquivalent } from '@secretkeylabs/xverse-core'; -import { getFiatEquivalent } from '@secretkeylabs/xverse-core/transactions'; -import { FungibleToken } from '@secretkeylabs/xverse-core/types'; +import { + FungibleToken, + getBtcEquivalent, + getFiatEquivalent, + getStxTokenEquivalent, +} from '@secretkeylabs/xverse-core'; import InputFeedback from '@ui-library/inputFeedback'; import { CurrencyTypes } from '@utils/constants'; import { getCurrencyFlag } from '@utils/currency'; @@ -64,45 +66,45 @@ const MemoContainer = styled.div((props) => ({ marginBottom: props.theme.spacing(6), })); -const ErrorText = styled.h1((props) => ({ - ...props.theme.body_xs, - color: props.theme.colors.feedback.error, +const ErrorText = styled.p((props) => ({ + ...props.theme.typography.body_s, + color: props.theme.colors.danger_medium, })); const InputFieldContainer = styled.div(() => ({ flex: 1, })); -const TitleText = styled.h1((props) => ({ - ...props.theme.body_medium_m, +const TitleText = styled.p((props) => ({ + ...props.theme.typography.body_medium_m, flex: 1, display: 'flex', })); -const Text = styled.h1((props) => ({ - ...props.theme.body_medium_m, +const Text = styled.p((props) => ({ + ...props.theme.typography.body_medium_m, })); -const SubText = styled.h1((props) => ({ - ...props.theme.body_xs, +const SubText = styled.p((props) => ({ + ...props.theme.typography.body_s, display: 'flex', flex: 1, color: props.theme.colors.white_400, })); -const AssociatedText = styled.h1((props) => ({ - ...props.theme.body_xs, +const AssociatedText = styled.p((props) => ({ + ...props.theme.typography.body_s, wordWrap: 'break-word', })); -const BalanceText = styled.h1((props) => ({ - ...props.theme.body_medium_m, +const BalanceText = styled.p((props) => ({ + ...props.theme.typography.body_medium_m, color: props.theme.colors.white_400, marginRight: props.theme.spacing(2), })); const InputField = styled.input((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, backgroundColor: props.theme.colors.elevation_n1, color: props.theme.colors.white_0, width: '100%', @@ -224,10 +226,9 @@ function SendForm({ const { stxBtcRate, btcFiatRate, fiatCurrency, stxAddress, selectedAccount } = useWalletSelector(); - const network = useNetworkSelector(); const debouncedSearchTerm = useDebounce(recipientAddress, 300); - const associatedBnsName = useBnsName(recipientAddress, network); - const associatedAddress = useBNSResolver(debouncedSearchTerm, stxAddress, currencyType); + const associatedBnsName = useBnsName(recipientAddress); + const associatedAddress = useBnsResolver(debouncedSearchTerm, stxAddress, currencyType); const { isAccountSwitched } = useClearFormOnAccountSwitch(); useEffect(() => { @@ -257,8 +258,8 @@ function SendForm({ const amountInCurrency = getFiatEquivalent( Number(amountToSend), currencyType, - stxBtcRate, - btcFiatRate, + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), fungibleToken, ); setFiatAmount(amountInCurrency); @@ -293,8 +294,8 @@ function SendForm({ const amountInCurrency = getFiatEquivalent( Number(newValue), currencyType, - stxBtcRate, - btcFiatRate, + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), fungibleToken, ); setFiatAmount(amountInCurrency); @@ -307,11 +308,17 @@ function SendForm({ if (!tokenAmount) return '0'; switch (currencyType) { case 'STX': - return getStxTokenEquivalent(new BigNumber(tokenAmount), stxBtcRate, btcFiatRate) + return getStxTokenEquivalent( + new BigNumber(tokenAmount), + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), + ) .toFixed(6) .toString(); case 'BTC': - return getBtcEquivalent(new BigNumber(tokenAmount), btcFiatRate).toFixed(8).toString(); + return getBtcEquivalent(new BigNumber(tokenAmount), BigNumber(btcFiatRate)) + .toFixed(8) + .toString(); case 'FT': if (fungibleToken?.tokenFiatRate) { return new BigNumber(tokenAmount) diff --git a/src/app/components/tabBar/index.tsx b/src/app/components/tabBar/index.tsx index 3bd6786fc..92601e9fd 100644 --- a/src/app/components/tabBar/index.tsx +++ b/src/app/components/tabBar/index.tsx @@ -31,7 +31,7 @@ const Button = styled.button({ zIndex: 2, }); -type Tab = 'dashboard' | 'nft' | 'stacking' | 'settings'; +export type Tab = 'dashboard' | 'nft' | 'stacking' | 'settings'; interface Props { tab: Tab; diff --git a/src/app/components/tilesSkeletonLoader.tsx b/src/app/components/tilesSkeletonLoader.tsx index 1252ced0d..3f7325179 100644 --- a/src/app/components/tilesSkeletonLoader.tsx +++ b/src/app/components/tilesSkeletonLoader.tsx @@ -7,7 +7,7 @@ const TilesLoaderContainer = styled.div<{ width: '100%', display: 'flex', justifyContent: 'flex-start', - columnGap: props.isGalleryOpen ? props.theme.spacing(16) : props.theme.spacing(12), + columnGap: props.isGalleryOpen ? props.theme.spacing(16) : props.theme.spacing(8), })); const TileLoaderContainer = styled.div({ diff --git a/src/app/components/tokenTile/index.tsx b/src/app/components/tokenTile/index.tsx index 0ba643f25..60756ad5c 100644 --- a/src/app/components/tokenTile/index.tsx +++ b/src/app/components/tokenTile/index.tsx @@ -1,6 +1,6 @@ import { BetterBarLoader } from '@components/barLoader'; -import { microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core/currency'; -import { FungibleToken } from '@secretkeylabs/xverse-core/types'; +import type { FungibleToken } from '@secretkeylabs/xverse-core'; +import { microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; import { StoreState } from '@stores/index'; import { CurrencyTypes } from '@utils/constants'; @@ -347,7 +347,7 @@ function TokenTile({ onPress({ coin: currency as CurrencyTypes, ft: fungibleToken && fungibleToken.principal, - brc20Ft: !fungibleToken?.principal && fungibleToken?.name, + brc20Ft: !fungibleToken?.principal ? fungibleToken?.name : undefined, }); }; diff --git a/src/app/components/topRow/index.tsx b/src/app/components/topRow/index.tsx index ed4a6b966..38e44039c 100644 --- a/src/app/components/topRow/index.tsx +++ b/src/app/components/topRow/index.tsx @@ -40,7 +40,7 @@ const AnimatedBackButton = styled(BackButton)` interface Props { title: string; - onClick: () => void; + onClick: (e: React.MouseEvent) => void; showBackButton?: boolean; className?: string; } diff --git a/src/app/components/transactionSetting/editFee.tsx b/src/app/components/transactionSetting/editFee.tsx index bf51ea681..8d2b51286 100644 --- a/src/app/components/transactionSetting/editFee.tsx +++ b/src/app/components/transactionSetting/editFee.tsx @@ -1,12 +1,13 @@ import useDebounce from '@hooks/useDebounce'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; import useWalletSelector from '@hooks/useWalletSelector'; -import { BtcUtxoDataResponse, ErrorCodes, UTXO } from '@secretkeylabs/xverse-core'; import { + ErrorCodes, getBtcFiatEquivalent, getStxFiatEquivalent, stxToMicrostacks, -} from '@secretkeylabs/xverse-core/currency'; + UTXO, +} from '@secretkeylabs/xverse-core'; import { getBtcFees, getBtcFeesForNonOrdinalBtcSend, @@ -146,7 +147,7 @@ interface Props { btcRecipients?: Recipient[]; ordinalTxUtxo?: UTXO; isRestoreFlow?: boolean; - nonOrdinalUtxos?: BtcUtxoDataResponse[]; + nonOrdinalUtxos?: UTXO[]; feeMode: string; error: string; setIsLoading: () => void; @@ -185,7 +186,7 @@ function EditFee({ } = useWalletSelector(); const [totalFee, setTotalFee] = useState(fee); const [feeRateInput, setFeeRateInput] = useState(feeRate?.toString() ?? ''); - const inputRef = useRef(null); + const inputRef = useRef(null); const debouncedFeeRateInput = useDebounce(feeRateInput, 500); const isBtcOrOrdinals = type === 'BTC' || type === 'Ordinals'; const isStx = type === 'STX'; @@ -292,7 +293,7 @@ function EditFee({ feeMode, feeRateInput, ); - setFeeRateInput(selectedFeeRate?.toString()); + setFeeRateInput(selectedFeeRate!.toString()); setTotalFee(modifiedFee.toString()); } else if (btcRecipients && selectedAccount) { const { fee: modifiedFee, selectedFeeRate } = await getBtcFees( @@ -302,7 +303,7 @@ function EditFee({ feeMode, feeRateInput, ); - setFeeRateInput(selectedFeeRate?.toString()); + setFeeRateInput(selectedFeeRate!.toString()); setTotalFee(modifiedFee.toString()); } } catch (err: any) { @@ -328,7 +329,7 @@ function EditFee({ feeMode, feeRateInput, ); - setFeeRateInput(selectedFeeRate?.toString()); + setFeeRateInput(selectedFeeRate!.toString()); setTotalFee(modifiedFee.toString()); } catch (err: any) { if (Number(err) === ErrorCodes.InSufficientBalance) { @@ -356,8 +357,12 @@ function EditFee({ function getFiatEquivalent() { return isStx - ? getStxFiatEquivalent(stxToMicrostacks(new BigNumber(totalFee)), stxBtcRate, btcFiatRate) - : getBtcFiatEquivalent(new BigNumber(totalFee), btcFiatRate); + ? getStxFiatEquivalent( + stxToMicrostacks(new BigNumber(totalFee)), + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), + ) + : getBtcFiatEquivalent(new BigNumber(totalFee), BigNumber(btcFiatRate)); } const getFiatAmountString = (fiatAmount: BigNumber) => { diff --git a/src/app/components/transactionSetting/index.tsx b/src/app/components/transactionSetting/index.tsx index 42bf77098..20bd18b3d 100644 --- a/src/app/components/transactionSetting/index.tsx +++ b/src/app/components/transactionSetting/index.tsx @@ -3,7 +3,7 @@ import ArrowIcon from '@assets/img/settings/arrow.svg'; import BottomModal from '@components/bottomModal'; import ActionButton from '@components/button'; import useWalletSelector from '@hooks/useWalletSelector'; -import { BtcUtxoDataResponse, UTXO } from '@secretkeylabs/xverse-core'; +import { UTXO } from '@secretkeylabs/xverse-core'; import { stxToMicrostacks } from '@secretkeylabs/xverse-core/currency'; import { isCustomFeesAllowed, Recipient } from '@secretkeylabs/xverse-core/transactions/btc'; import BigNumber from 'bignumber.js'; @@ -64,7 +64,7 @@ interface Props { btcRecipients?: Recipient[]; ordinalTxUtxo?: UTXO; isRestoreFlow?: boolean; - nonOrdinalUtxos?: BtcUtxoDataResponse[]; + nonOrdinalUtxos?: UTXO[]; showFeeSettings: boolean; setShowFeeSettings: (value: boolean) => void; } @@ -123,7 +123,7 @@ function TransactionSettingAlert({ const applyClickForBtc = async () => { const currentFee = new BigNumber(feeInput); - if (btcBalance && currentFee.gt(btcBalance)) { + if (currentFee.gt(btcBalance)) { // show fee exceeds total balance error setError(t('TRANSACTION_SETTING.GREATER_FEE_ERROR')); return; diff --git a/src/app/components/transactionsRequests/ContractCallRequest.tsx b/src/app/components/transactionsRequests/ContractCallRequest.tsx index 8c3a021dc..f20a09173 100644 --- a/src/app/components/transactionsRequests/ContractCallRequest.tsx +++ b/src/app/components/transactionsRequests/ContractCallRequest.tsx @@ -134,8 +134,9 @@ export default function ContractCallRequest(props: ContractCallRequestProps) { const functionArgsView = () => { const args = getFunctionArgs(); - return args.map((arg, index) => ( + return args.map((arg) => ( 20 ? truncateFunctionArgsView(arg.value) : arg.value} description={arg.type} @@ -224,20 +225,18 @@ export default function ContractCallRequest(props: ContractCallRequestProps) { switch (postCondition.conditionType) { case PostConditionType.STX: return ; - case PostConditionType.Fungible: + case PostConditionType.Fungible: { + const coinInfo = coinsMetaData?.find( + (coin: Coin) => + coin.contract === + `${addressToString(postCondition.assetInfo.address)}.${ + postCondition.assetInfo.contractName.content + }`, + ); return ( - - coin.contract === - `${addressToString(postCondition.assetInfo.address)}.${ - postCondition.assetInfo.contractName.content - }`, - )} - /> + ); + } case PostConditionType.NonFungible: return ; default: diff --git a/src/app/components/transferFeeView/index.tsx b/src/app/components/transferFeeView/index.tsx index bc061948d..7080417fd 100644 --- a/src/app/components/transferFeeView/index.tsx +++ b/src/app/components/transferFeeView/index.tsx @@ -56,7 +56,12 @@ function TransferFeeView({ feePerVByte, fee, currency, title }: Props) { const { btcFiatRate, stxBtcRate, fiatCurrency } = useSelector( (state: StoreState) => state.walletState, ); - const fiatRate = getFiatEquivalent(Number(fee), currency, stxBtcRate, btcFiatRate); + const fiatRate = getFiatEquivalent( + Number(fee), + currency, + BigNumber(stxBtcRate), + BigNumber(btcFiatRate), + ); const getFiatAmountString = (fiatAmount: BigNumber) => { if (!fiatAmount) { return ''; @@ -103,7 +108,7 @@ function TransferFeeView({ feePerVByte, fee, currency, title }: Props) { {getFiatAmountString( currency === 'sats' - ? getBtcFiatEquivalent(new BigNumber(fee), btcFiatRate) + ? getBtcFiatEquivalent(new BigNumber(fee), BigNumber(btcFiatRate)) : new BigNumber(fiatRate!), )} diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 547cd9cf6..0329325dc 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -53,7 +53,7 @@ export const useGetUtxoOrdinalBundle = (output?: string, shouldMakeTheCall?: boo const { data, isLoading } = useQuery({ enabled: !!(output && shouldMakeTheCall), - queryKey: ['rare-sats', output], + queryKey: ['rare-sats', output, network.type], queryFn: getUtxoOrdinalBundleByOutput, retry: handleRetries, staleTime: 1 * 60 * 1000, // 1 min diff --git a/src/app/hooks/queries/ordinals/useCollectionMarketData.ts b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts index 990a667fc..ab5a9e8b1 100644 --- a/src/app/hooks/queries/ordinals/useCollectionMarketData.ts +++ b/src/app/hooks/queries/ordinals/useCollectionMarketData.ts @@ -18,7 +18,7 @@ const useInscriptionCollectionMarketData = (collectionId?: string | null) => { return useQuery({ enabled: !!collectionId, retry: handleRetries, - queryKey: ['collection-market-data', collectionId], + queryKey: ['collection-market-data', collectionId, network.type], queryFn: collectionMarketData, staleTime: 1 * 60 * 1000, // 1 min }); diff --git a/src/app/hooks/queries/useBnsName.ts b/src/app/hooks/queries/useBnsName.ts index 028d1c06c..6f02fe79a 100644 --- a/src/app/hooks/queries/useBnsName.ts +++ b/src/app/hooks/queries/useBnsName.ts @@ -1,10 +1,10 @@ +import { fetchAddressOfBnsName, getBnsName, validateStxAddress } from '@secretkeylabs/xverse-core'; import { useEffect, useState } from 'react'; -import { StacksNetwork, validateStxAddress } from '@secretkeylabs/xverse-core'; -import { fetchAddressOfBnsName, getBnsName } from '@secretkeylabs/xverse-core/api'; -import useWalletSelector from '../useWalletSelector'; import useNetworkSelector from '../useNetwork'; +import useWalletSelector from '../useWalletSelector'; -export const useBnsName = (walletAddress: string, network: StacksNetwork) => { +export const useBnsName = (walletAddress: string) => { + const network = useNetworkSelector(); const [bnsName, setBnsName] = useState(''); useEffect(() => { @@ -12,15 +12,15 @@ export const useBnsName = (walletAddress: string, network: StacksNetwork) => { const name = await getBnsName(walletAddress, network); setBnsName(name ?? ''); })(); - }, [walletAddress]); + }, [walletAddress, network]); return bnsName; }; -export const useBNSResolver = ( +export const useBnsResolver = ( recipientAddress: string, walletAddress: string, - currencyType: string, + currencyType?: string, ) => { const { network } = useWalletSelector(); const selectedNetwork = useNetworkSelector(); @@ -43,7 +43,7 @@ export const useBNSResolver = ( setAssociatedAddress(''); } })(); - }, [recipientAddress]); + }, [recipientAddress, network, currencyType, selectedNetwork, walletAddress]); return associatedAddress; }; diff --git a/src/app/hooks/queries/useBtcWalletData.ts b/src/app/hooks/queries/useBtcWalletData.ts index f2615ac55..ef83e1762 100644 --- a/src/app/hooks/queries/useBtcWalletData.ts +++ b/src/app/hooks/queries/useBtcWalletData.ts @@ -2,7 +2,6 @@ import useBtcClient from '@hooks/useBtcClient'; import type { BtcAddressData } from '@secretkeylabs/xverse-core'; import { SetBtcWalletDataAction } from '@stores/wallet/actions/actionCreators'; import { useQuery } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; import { useDispatch } from 'react-redux'; import useWalletSelector from '../useWalletSelector'; @@ -13,8 +12,7 @@ export const useBtcWalletData = () => { const fetchBtcWalletData = async () => { const btcData: BtcAddressData = await btcClient.getBalance(btcAddress); - const btcBalance = new BigNumber(btcData.finalBalance); - dispatch(SetBtcWalletDataAction(btcBalance)); + dispatch(SetBtcWalletDataAction(btcData.finalBalance)); return btcData; }; diff --git a/src/app/hooks/queries/useCoinRates.ts b/src/app/hooks/queries/useCoinRates.ts index 92e2e446b..cb87c308b 100644 --- a/src/app/hooks/queries/useCoinRates.ts +++ b/src/app/hooks/queries/useCoinRates.ts @@ -22,7 +22,7 @@ export const useCoinRates = () => { }; return useQuery({ - queryKey: ['coin_rates'], + queryKey: ['coin_rates', fiatCurrency, network.type], queryFn: fetchCoinRates, staleTime: 5 * 60 * 1000, // 5 min }); diff --git a/src/app/hooks/queries/useNftDetail.ts b/src/app/hooks/queries/useNftDetail.ts new file mode 100644 index 000000000..85a37841a --- /dev/null +++ b/src/app/hooks/queries/useNftDetail.ts @@ -0,0 +1,28 @@ +import { getNftDetail, NftDetailResponse, NonFungibleToken } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; +import { getIdentifier, isBnsCollection } from '@utils/nfts'; +import { handleRetries } from '@utils/query'; + +const useNftDetail = (id: string | NonFungibleToken['identifier']) => { + const { tokenId, contractAddress, contractName } = + typeof id === 'string' ? getIdentifier(id) : id; + + const fetchNft = (): Promise => + getNftDetail(tokenId, contractAddress, contractName); + + return useQuery({ + enabled: !!( + id && + tokenId && + contractAddress && + contractName && + !isBnsCollection(`${contractAddress}.${contractName}`) + ), + retry: handleRetries, + queryKey: ['nft-detail', contractAddress, contractName, tokenId], + queryFn: fetchNft, + staleTime: 24 * 60 * 60 * 1000, // 24 hours + }); +}; + +export default useNftDetail; diff --git a/src/app/hooks/queries/useStacksCollectibles.ts b/src/app/hooks/queries/useStacksCollectibles.ts index d93cdffbc..3ad6c3c0a 100644 --- a/src/app/hooks/queries/useStacksCollectibles.ts +++ b/src/app/hooks/queries/useStacksCollectibles.ts @@ -1,42 +1,23 @@ import useNetworkSelector from '@hooks/useNetwork'; import useWalletSelector from '@hooks/useWalletSelector'; -import { getNfts, NftsListData } from '@secretkeylabs/xverse-core'; -import { useInfiniteQuery } from '@tanstack/react-query'; -import { handleRetries, InvalidParamsError } from '@utils/query'; +import { getNftCollections, StacksCollectionList } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; +import { handleRetries } from '@utils/query'; const useStacksCollectibles = () => { const { stxAddress } = useWalletSelector(); const selectedNetwork = useNetworkSelector(); - function fetchNfts({ pageParam = 0 }): Promise { - if (!stxAddress) { - return Promise.reject(new InvalidParamsError('stxAddress is required')); - } - return getNfts(stxAddress, selectedNetwork, pageParam); - } + const fetchNftCollections = (): Promise => + getNftCollections(stxAddress, selectedNetwork); - const { isLoading, data, fetchNextPage, isFetchingNextPage, hasNextPage, refetch, error } = - useInfiniteQuery([`nft-meta-data-${stxAddress}`], fetchNfts, { - retry: handleRetries, - keepPreviousData: false, - getNextPageParam: (lastpage, pages) => { - const currentLength = pages.map((page) => page.nftsList).flat().length; - if (currentLength < lastpage.total) { - return currentLength; - } - return false; - }, - }); - - return { - isLoading, - error, - data, - fetchNextPage, - isFetchingNextPage, - hasNextPage, - refetch, - }; + return useQuery({ + enabled: !!stxAddress, + retry: handleRetries, + queryKey: ['nft-collection-data', stxAddress], + queryFn: fetchNftCollections, + staleTime: 5 * 60 * 1000, // 5mins + }); }; export default useStacksCollectibles; diff --git a/src/app/hooks/stores/useNftReducer.ts b/src/app/hooks/stores/useNftReducer.ts deleted file mode 100644 index a6caf3510..000000000 --- a/src/app/hooks/stores/useNftReducer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { NftData } from '@secretkeylabs/xverse-core/types/api/gamma/currency'; -import { setNftDataAction } from '@stores/nftData/actions/actionCreator'; -import { useDispatch } from 'react-redux'; -import useNftDataSelector from './useNftDataSelector'; - -const useNftDataReducer = () => { - const { nftData } = useNftDataSelector(); - const dispatch = useDispatch(); - - const storeNftData = (data: NftData) => { - const nftExists = nftData.find((nftItem) => nftItem?.token_id === data?.token_id); - if (data && !nftExists) { - const modifiedNftList = [...nftData]; - modifiedNftList.push(data); - dispatch(setNftDataAction(modifiedNftList)); - } - }; - return { - storeNftData, - }; -}; - -export default useNftDataReducer; diff --git a/src/app/hooks/stores/useOrdinalReducer.ts b/src/app/hooks/stores/useOrdinalReducer.ts index 966d2c64d..86f7f2645 100644 --- a/src/app/hooks/stores/useOrdinalReducer.ts +++ b/src/app/hooks/stores/useOrdinalReducer.ts @@ -1,4 +1,4 @@ -import { Inscription } from '@secretkeylabs/xverse-core/types/api/ordinals'; +import type { Inscription } from '@secretkeylabs/xverse-core'; import { setSelectedOrdinalAction } from '@stores/nftData/actions/actionCreator'; import { useDispatch } from 'react-redux'; diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index 9483c86d1..36fe692b7 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -4,7 +4,7 @@ import { isAxiosError } from 'axios'; import { useEffect, useState } from 'react'; import useWalletSelector from './useWalletSelector'; -const useDetectOrdinalInSignPsbt = (parsedPsbt: '' | ParsedPSBT) => { +const useDetectOrdinalInSignPsbt = (parsedPsbt: undefined | ParsedPSBT) => { const [loading, setLoading] = useState(false); const [userReceivesOrdinal, setUserReceivesOrdinal] = useState(false); const [bundleItemsData, setBundleItemsData] = useState([]); diff --git a/src/app/hooks/useResetUserFlow.ts b/src/app/hooks/useResetUserFlow.ts index 932f416f3..7443eb201 100644 --- a/src/app/hooks/useResetUserFlow.ts +++ b/src/app/hooks/useResetUserFlow.ts @@ -14,18 +14,19 @@ const userFlowConfig: Record = { '/send-brc20': { resetTo: '/' }, '/confirm-brc20-tx': { resetTo: '/' }, '/confirm-inscription-request': { resetTo: '/' }, - '/ordinal-detail': { resetTo: '/nft-dashboard' }, - '/send-ordinal': { resetTo: '/nft-dashboard' }, - '/confirm-ordinal-tx': { resetTo: '/nft-dashboard' }, - '/nft-detail': { resetTo: '/nft-dashboard' }, - '/send-nft': { resetTo: '/nft-dashboard' }, - '/confirm-nft-tx': { resetTo: '/nft-dashboard' }, - '/verify-ledger': { resetTo: '/verify-ledger?mismatch=true' }, - '/add-stx-address-ledger': { resetTo: '/add-stx-address-ledger?mismatch=true' }, + '/ordinals-collection': { resetTo: '/nft-dashboard?tab=inscriptions' }, + '/ordinal-detail': { resetTo: '/nft-dashboard?tab=inscriptions' }, + '/send-ordinal': { resetTo: '/nft-dashboard?tab=inscriptions' }, + '/confirm-ordinal-tx': { resetTo: '/nft-dashboard?tab=inscriptions' }, + '/nft-collection': { resetTo: '/nft-dashboard?tab=nfts' }, + '/nft-detail': { resetTo: '/nft-dashboard?tab=nfts' }, + '/send-nft': { resetTo: '/nft-dashboard?tab=nfts' }, + '/confirm-nft-tx': { resetTo: '/nft-dashboard?tab=nfts' }, '/rare-sats-detail': { resetTo: '/nft-dashboard?tab=rareSats' }, '/rare-sats-bundle': { resetTo: '/nft-dashboard?tab=rareSats' }, '/send-rare-sat': { resetTo: '/nft-dashboard?tab=rareSats' }, - '/ordinals-collection': { resetTo: '/nft-dashboard?tab=inscriptions' }, + '/verify-ledger': { resetTo: '/verify-ledger?mismatch=true' }, + '/add-stx-address-ledger': { resetTo: '/add-stx-address-ledger?mismatch=true' }, }; type UserFlowConfigKey = keyof typeof userFlowConfig; diff --git a/src/app/hooks/useTextOrdinalContent.ts b/src/app/hooks/useTextOrdinalContent.ts index 130dfdcc2..00a6040ac 100644 --- a/src/app/hooks/useTextOrdinalContent.ts +++ b/src/app/hooks/useTextOrdinalContent.ts @@ -9,7 +9,7 @@ const queue = new PQueue({ concurrency: 1 }); const useTextOrdinalContent = (ordinal: Inscription | CondensedInscription) => { const { network } = useWalletSelector(); const { data: textContent } = useQuery({ - queryKey: [`ordinal-text-${ordinal?.id}`], + queryKey: ['ordinal-text', ordinal?.id, network.type], queryFn: async () => queue.add(() => getTextOrdinalContent(network.type, ordinal?.id)), staleTime: 5 * 60 * 1000, // 5 min }); diff --git a/src/app/layouts/sendLayout.tsx b/src/app/layouts/sendLayout.tsx new file mode 100644 index 000000000..8a077ce8b --- /dev/null +++ b/src/app/layouts/sendLayout.tsx @@ -0,0 +1,101 @@ +import AccountHeaderComponent from '@components/accountHeader'; +import BottomBar, { Tab } from '@components/tabBar'; +import TopRow from '@components/topRow'; +import { ArrowLeft } from '@phosphor-icons/react'; +import { StyledP } from '@ui-library/common.styled'; +import { PropsWithChildren } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; +import { breakpoints, devices } from 'theme'; + +const ScrollContainer = styled.div((props) => ({ + display: 'flex', + flex: 1, + flexDirection: 'column', + ...props.theme.scrollbar, +})); + +const Container = styled.div` + display: flex; + flex-direction: column; + margin: auto; + margin-top: ${(props) => props.theme.space.xxs}; + padding: 0 ${(props) => props.theme.space.s}; + width: 100%; + height: 100%; + max-width: ${breakpoints.xs}px; + max-height: 600px; + + @media only screen and ${devices.min.s} { + flex: initial; + max-width: 588px; + border: 1px solid ${(props) => props.theme.colors.elevation3}; + border-radius: ${(props) => props.theme.space.s}; + padding: ${(props) => props.theme.space.l} ${(props) => props.theme.space.m}; + padding-bottom: ${(props) => props.theme.space.xxl}; + margin-top: ${(props) => props.theme.space.xxxxl}; + } +`; + +const FooterContainer = styled.div` + display: flex; + justify-content: center; + margin-bottom: ${(props) => props.theme.space.xxl}; +`; + +const BottomBarContainer = styled.div({ + marginTop: 'auto', +}); + +const Button = styled.button` + display: flex; + background-color: transparent; + margin-bottom: ${(props) => props.theme.space.l}; +`; + +function SendLayout({ + children, + selectedBottomTab, + onClickBack, + hideBackButton = false, +}: PropsWithChildren<{ + selectedBottomTab: Tab; + onClickBack?: (e: React.MouseEvent) => void; + hideBackButton?: boolean; +}>) { + const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); + const isScreenLargerThanXs = document.documentElement.clientWidth > Number(breakpoints.xs); + const year = new Date().getFullYear(); + + return ( + <> + {isScreenLargerThanXs ? ( + + ) : ( + + )} + + + {isScreenLargerThanXs && !hideBackButton && onClickBack && ( + + )} + {children} + + {isScreenLargerThanXs && ( + + + {t('COPYRIGHT', { year })} + + + )} + + + {!isScreenLargerThanXs && } + + + ); +} + +export default SendLayout; diff --git a/src/app/routes/index.tsx b/src/app/routes/index.tsx index 9d426fb2a..60dc5417b 100644 --- a/src/app/routes/index.tsx +++ b/src/app/routes/index.tsx @@ -33,6 +33,7 @@ import VerifyLedger from '@screens/ledger/verifyLedgerAccountAddress'; import LegalLinks from '@screens/legalLinks'; import Login from '@screens/login'; import ManageTokens from '@screens/manageTokens'; +import NftCollection from '@screens/nftCollection'; import NftDashboard from '@screens/nftDashboard'; import SupportedRarities from '@screens/nftDashboard/supportedRarities'; import NftDetailScreen from '@screens/nftDetail'; @@ -43,7 +44,6 @@ import RareSatsBundle from '@screens/rareSatsBundle'; import RareSatsDetailScreen from '@screens/rareSatsDetail/rareSatsDetail'; import Receive from '@screens/receive'; import RestoreFunds from '@screens/restoreFunds'; -import RestoreBtc from '@screens/restoreFunds/restoreBtc'; import RestoreOrdinals from '@screens/restoreFunds/restoreOrdinals'; import RestoreWallet from '@screens/restoreWallet'; import SendBrc20Screen from '@screens/sendBrc20'; @@ -301,10 +301,6 @@ const router = createHashRouter([ path: 'restore-funds', element: , }, - { - path: 'recover-btc', - element: , - }, { path: 'recover-ordinals', element: , @@ -374,10 +370,6 @@ const router = createHashRouter([ ), }, - { - path: 'send-nft/:id', - element: , - }, { path: 'confirm-inscription-request', element: ( @@ -457,6 +449,14 @@ const router = createHashRouter([ path: 'nft-dashboard/nft-detail/:id/send-nft', element: , }, + { + path: 'nft-dashboard/nft-collection/:id', + element: ( + + + + ), + }, { path: 'nft-dashboard/ordinal-detail/:id/send-ordinal', element: ( diff --git a/src/app/screens/btcSendScreen/index.tsx b/src/app/screens/btcSendScreen/index.tsx index 04e84627a..422734a34 100644 --- a/src/app/screens/btcSendScreen/index.tsx +++ b/src/app/screens/btcSendScreen/index.tsx @@ -109,9 +109,9 @@ function BtcSendScreen() { recipient, fee: signedTx.fee, feePerVByte: signedTx.feePerVByte, - fiatFee: getBtcFiatEquivalent(signedTx.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(signedTx.fee, BigNumber(btcFiatRate)), total: signedTx.total, - fiatTotal: getBtcFiatEquivalent(signedTx.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(signedTx.total, BigNumber(btcFiatRate)), btcSendBrowserTx: true, requestToken, tabId, diff --git a/src/app/screens/coinDashboard/coinHeader.tsx b/src/app/screens/coinDashboard/coinHeader.tsx index ce741ad1c..5825b3721 100644 --- a/src/app/screens/coinDashboard/coinHeader.tsx +++ b/src/app/screens/coinDashboard/coinHeader.tsx @@ -10,7 +10,7 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { FungibleToken, microstacksToStx, satsToBtc } from '@secretkeylabs/xverse-core'; import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; import { CurrencyTypes } from '@utils/constants'; -import { isLedgerAccount } from '@utils/helper'; +import { isInOptions, isLedgerAccount } from '@utils/helper'; import { getFtBalance, getFtTicker } from '@utils/tokens'; import BigNumber from 'bignumber.js'; import { useState } from 'react'; @@ -231,7 +231,7 @@ export default function CoinHeader(props: CoinBalanceProps) { } const renderStackingBalances = () => { - if (stxLockedBalance && !new BigNumber(stxLockedBalance).eq(0, 10) && coin === 'STX') { + if (!new BigNumber(stxLockedBalance).eq(0) && coin === 'STX') { return ( <> @@ -262,7 +262,7 @@ export default function CoinHeader(props: CoinBalanceProps) { }; const goToSendScreen = async () => { - if (isLedgerAccount(selectedAccount)) { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { switch (coin) { case 'BTC': await chrome.tabs.create({ diff --git a/src/app/screens/confirmBrc20Transaction/editFees.tsx b/src/app/screens/confirmBrc20Transaction/editFees.tsx index cad42c787..36c2a3e1a 100644 --- a/src/app/screens/confirmBrc20Transaction/editFees.tsx +++ b/src/app/screens/confirmBrc20Transaction/editFees.tsx @@ -228,7 +228,7 @@ export function EditFees({ onClose(); }; - const fiatFee = getBtcFiatEquivalent(new BigNumber(fee), btcFiatRate); + const fiatFee = getBtcFiatEquivalent(new BigNumber(fee), BigNumber(btcFiatRate)); return ( } diff --git a/src/app/screens/confirmInscriptionRequest/index.tsx b/src/app/screens/confirmInscriptionRequest/index.tsx index 7a697fe37..ac7c278d7 100644 --- a/src/app/screens/confirmInscriptionRequest/index.tsx +++ b/src/app/screens/confirmInscriptionRequest/index.tsx @@ -317,7 +317,7 @@ function ConfirmInscriptionRequest() { nonce?: string; }) => { const seedPhrase = await getSeed(); - setCurrentFeeRate(new BigNumber(feeRate)); + setCurrentFeeRate(new BigNumber(feeRate!)); mutateTxFee({ recipients: recipient, txFee: modifiedFee, seedPhrase }); }; @@ -391,7 +391,7 @@ function ConfirmInscriptionRequest() { + + ); - const galleryView = - isLoading || !nft ? ( - - - - ) : ( - + const galleryView = isLoading ? ( + + - + - {nft?.token_metadata.name} - - - - - - - - - - {showShareNftOptions && ( - - )} - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + ) : ( + + + + + + {t('MOVE_TO_ASSET_DETAIL')} + + + + + {nft && } + {nftAttributes} + - {t('DESCRIPTION')} - - {nft?.rarity_score && ( - - )} - - {nft?.nft_token_attributes.length !== 0 && ( - <> - {t('ATTRIBUTES')} - - {nft?.nft_token_attributes.map((attribute) => ( - - ))} - - - )} - - - - - ); + + + + ); return ( <> @@ -452,7 +575,7 @@ function NftDetailScreen() { ) : ( )} - {isGalleryOpen ? galleryView : extensionView} + {isGalleryOpen ? galleryView : extensionView} {!isGalleryOpen && ( diff --git a/src/app/screens/nftDetail/nftAttribute.tsx b/src/app/screens/nftDetail/nftAttribute.tsx index 7f00fd22c..3d1b7eef0 100644 --- a/src/app/screens/nftDetail/nftAttribute.tsx +++ b/src/app/screens/nftDetail/nftAttribute.tsx @@ -1,25 +1,23 @@ import styled from 'styled-components'; -const Container = styled.h1((props) => ({ +const Container = styled.div((props) => ({ display: 'flex', - borderRadius: 20, + borderRadius: 12, border: `1px solid ${props.theme.colors.elevation3}`, - flexDirection: 'row', - marginEnd: 10, - padding: props.theme.spacing(5), - alignItems: 'center', + flexDirection: 'column', + padding: '8px 16px', + alignItems: 'flex-start', })); const TypeText = styled.h1((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, color: props.theme.colors.white_400, })); const ValueText = styled.h1((props) => ({ - ...props.theme.body_medium_m, + ...props.theme.typography.body_medium_m, color: props.theme.colors.white_0, wordBreak: 'break-all', - marginLeft: props.theme.spacing(3), })); interface Props { diff --git a/src/app/screens/nftDetail/useNftDetail.ts b/src/app/screens/nftDetail/useNftDetail.ts new file mode 100644 index 000000000..61443e77d --- /dev/null +++ b/src/app/screens/nftDetail/useNftDetail.ts @@ -0,0 +1,78 @@ +import useNftDetail from '@hooks/queries/useNftDetail'; +import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; +import useResetUserFlow from '@hooks/useResetUserFlow'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { GAMMA_URL } from '@utils/constants'; +import { getExplorerUrl, isInOptions, isLedgerAccount } from '@utils/helper'; +import { useMemo } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; + +export default function useNftDetailScreen() { + const navigate = useNavigate(); + const { stxAddress, selectedAccount } = useWalletSelector(); + const { id } = useParams(); + + const nftDetailQuery = useNftDetail(id!); + const nftCollectionsQuery = useStacksCollectibles(); + const collectionId = nftDetailQuery.data?.data.collection_contract_id; + const collection = nftCollectionsQuery.data?.results.find( + (c) => c.collection_id === collectionId, + ); + + const metadata = nftDetailQuery.data?.data?.token_metadata; + const gammaUrl = `${GAMMA_URL}collections/${metadata?.contract_id}/${nftDetailQuery.data?.data?.token_id}`; + + useResetUserFlow('/nft-detail'); + + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); + const galleryTitle = metadata?.name; + + const onSharePress = () => { + navigator.clipboard.writeText(gammaUrl); + }; + + const handleBackButtonClick = () => { + navigate(`/nft-dashboard/nft-collection/${collectionId}`); + }; + + const onGammaPress = () => { + window.open(gammaUrl); + }; + + const onExplorerPress = () => { + const address = metadata?.contract_id?.split('.')!; + window.open(getExplorerUrl(address[0])); + }; + + const openInGalleryView = async () => { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/nft-dashboard/nft-detail/${id}`), + }); + }; + + const handleOnSendClick = async () => { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { + await chrome.tabs.create({ + url: chrome.runtime.getURL(`options.html#/nft-dashboard/nft-detail/${id}/send-nft`), + }); + return; + } + navigate(`/nft-dashboard/nft-detail/${id}/send-nft`); + }; + + return { + nft: nftDetailQuery.data, + nftData: nftDetailQuery.data?.data, + collection, + stxAddress, + isLoading: nftDetailQuery.isLoading, + isGalleryOpen, + onSharePress, + handleBackButtonClick, + onGammaPress, + onExplorerPress, + openInGalleryView, + handleOnSendClick, + galleryTitle, + }; +} diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index 418feae32..53a5279f8 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/white_ordinals_icon.svg'; import AccountHeaderComponent from '@components/accountHeader'; diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts index abd694b05..7704e5b78 100644 --- a/src/app/screens/ordinalDetail/useOrdinalDetail.ts +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -8,7 +8,7 @@ import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import useTextOrdinalContent from '@hooks/useTextOrdinalContent'; import useWalletSelector from '@hooks/useWalletSelector'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; -import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; +import { getBtcTxStatusUrl, isInOptions, isLedgerAccount } from '@utils/helper'; import { getInscriptionsCollectionGridItemSubText, getInscriptionsCollectionGridItemSubTextColor, @@ -83,7 +83,7 @@ export default function useOrdinalDetail() { return; } if (ordinalData) setSelectedOrdinalDetails(ordinalData); - if (isLedgerAccount(selectedAccount)) { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { await chrome.tabs.create({ url: chrome.runtime.getURL(`options.html#/nft-dashboard/ordinal-detail/${id}/send-ordinal`), }); diff --git a/src/app/screens/ordinalsCollection/index.tsx b/src/app/screens/ordinalsCollection/index.tsx index 70017292e..51b28fe7e 100644 --- a/src/app/screens/ordinalsCollection/index.tsx +++ b/src/app/screens/ordinalsCollection/index.tsx @@ -1,6 +1,7 @@ import AccountHeaderComponent from '@components/accountHeader'; import { BetterBarLoader } from '@components/barLoader'; import ActionButton from '@components/button'; +import CollectibleCollectionGridItem from '@components/collectibleCollectionGridItem'; import CollectibleDetailTile from '@components/collectibleDetailTile'; import Separator from '@components/separator'; import BottomTabBar from '@components/tabBar'; @@ -10,15 +11,22 @@ import WebGalleryButton from '@components/webGalleryButton'; import WrenchErrorMessage from '@components/wrenchErrorMessage'; import useAddressInscriptions from '@hooks/queries/ordinals/useAddressInscriptions'; import useInscriptionCollectionMarketData from '@hooks/queries/ordinals/useCollectionMarketData'; +import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import { ArrowLeft } from '@phosphor-icons/react'; import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { Inscription } from '@secretkeylabs/xverse-core'; import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { + getInscriptionsCollectionGridItemId, + getInscriptionsCollectionGridItemSubText, + getInscriptionsCollectionGridItemSubTextColor, +} from '@utils/inscriptions'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useParams } from 'react-router-dom'; import styled from 'styled-components'; -import { OrdinalsCollectionGridItem } from './ordinalsCollectionGridItem'; interface DetailSectionProps { isGalleryOpen?: boolean; @@ -27,11 +35,9 @@ interface DetailSectionProps { /* layout */ // TODO tim: create a reusable layout const Container = styled.div` - overflow-y: auto; display: flex; flex-direction: column; flex: 1; - overflow-y: auto; ${(props) => props.theme.scrollbar} `; @@ -129,8 +135,9 @@ const StyledBarLoader = styled(BetterBarLoader)((props) => ({ })); function OrdinalsCollection() { - const { t } = useTranslation('translation', { keyPrefix: 'ORDINALS_COLLECTION_SCREEN' }); + const { t } = useTranslation('translation', { keyPrefix: 'COLLECTIBLE_COLLECTION_SCREEN' }); const navigate = useNavigate(); + const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); const { id: collectionId } = useParams(); const { data, error, isLoading, hasNextPage, isFetchingNextPage, fetchNextPage } = useAddressInscriptions(collectionId); @@ -151,7 +158,7 @@ function OrdinalsCollection() { }); }; - const isEmpty = !isLoading && !error && data?.pages?.[0]?.data?.total === 0; + const isEmpty = !isLoading && !error && data?.pages?.[0]?.total === 0; const collectionHeading = data?.pages?.[0].collection_name; const estPortfolioValue = @@ -162,6 +169,11 @@ function OrdinalsCollection() { ? `${collectionMarketData?.floor_price?.toFixed(8)} BTC` : '--'; + const handleOnClick = (item: Inscription) => { + setSelectedOrdinalDetails(item); + navigate(`/nft-dashboard/ordinal-detail/${item.id}`); + }; + return ( <> {isGalleryOpen ? ( @@ -222,7 +234,16 @@ function OrdinalsCollection() { ?.map((page) => page?.data) .flat() .map((inscription) => ( - + + + )) )} diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx index ed00dc4ef..985bf887b 100644 --- a/src/app/screens/rareSatsBundle/index.tsx +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -14,7 +14,7 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; import { GridContainer } from '@screens/nftDashboard/collectiblesTabs'; import { StyledHeading, StyledP } from '@ui-library/common.styled'; -import { getBtcTxStatusUrl, isLedgerAccount } from '@utils/helper'; +import { getBtcTxStatusUrl, isInOptions, isLedgerAccount } from '@utils/helper'; import { BundleItem } from '@utils/rareSats'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -171,7 +171,7 @@ function RareSatsBundle() { return setShowSendOrdinalsAlert(true); } - if (isLedgerAccount(selectedAccount)) { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { await chrome.tabs.create({ url: chrome.runtime.getURL('options.html#/nft-dashboard/send-rare-sat'), }); diff --git a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx index 57e7bef4c..b5bb2b9a0 100644 --- a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx +++ b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx @@ -14,7 +14,12 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowRight, ArrowUp, Circle } from '@phosphor-icons/react'; import Callout from '@ui-library/callout'; import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; -import { getBtcTxStatusUrl, getTruncatedAddress, isLedgerAccount } from '@utils/helper'; +import { + getBtcTxStatusUrl, + getTruncatedAddress, + isInOptions, + isLedgerAccount, +} from '@utils/helper'; import { BundleItem, getBundleItemId, @@ -292,7 +297,7 @@ function RareSatsDetailScreen() { return showAlert(); } - if (isLedgerAccount(selectedAccount)) { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { await chrome.tabs.create({ url: chrome.runtime.getURL('options.html#/nft-dashboard/send-rare-sat'), }); diff --git a/src/app/screens/restoreFunds/index.tsx b/src/app/screens/restoreFunds/index.tsx index e6ab2c740..d08635be9 100644 --- a/src/app/screens/restoreFunds/index.tsx +++ b/src/app/screens/restoreFunds/index.tsx @@ -1,4 +1,3 @@ -import BitcoinIcon from '@assets/img/dashboard/bitcoin_icon.svg'; import OrdinalsIcon from '@assets/img/nftDashboard/ordinals_icon.svg'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; @@ -31,10 +30,6 @@ function RestoreFunds() { navigate(-1); }; - const handleOnRestoreBtcClick = () => { - navigate('/recover-btc'); - }; - const handleOnRestoreOridnalClick = () => { navigate('/recover-ordinals'); }; @@ -44,7 +39,6 @@ function RestoreFunds() { {t('DESCRIPTION')} - {/* */} ({ - ...props.theme.body_l, - marginBottom: props.theme.spacing(16), - color: props.theme.colors.white_200, -})); - -const BtcCard = styled.div((props) => ({ - display: 'flex', - flexDirection: 'row', - background: props.theme.colors.elevation1, - borderRadius: props.theme.radius(1), - padding: '16px 12px', -})); - -const Icon = styled.img((props) => ({ - marginRight: props.theme.spacing(6), - width: 32, - height: 32, - borderRadius: 30, -})); - -const TitleText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white_0, -})); - -const ValueText = styled.h1((props) => ({ - ...props.theme.body_xs, - color: props.theme.colors.white_400, -})); - -const BtcContainer = styled.div({ - display: 'flex', - flexDirection: 'column', -}); - -const Container = styled.div((props) => ({ - display: 'flex', - flex: 1, - flexDirection: 'column', - marginLeft: props.theme.spacing(8), - marginTop: props.theme.spacing(16), - marginRight: props.theme.spacing(8), -})); - -const ButtonContainer = styled.div((props) => ({ - marginLeft: props.theme.spacing(8), - marginBottom: props.theme.spacing(16), - marginRight: props.theme.spacing(8), -})); - -function RestoreBtc() { - const { t } = useTranslation('translation', { keyPrefix: 'RESTORE_BTC_SCREEN' }); - const { ordinalsAddress, btcAddress, network, selectedAccount, btcFiatRate } = - useWalletSelector(); - const { getSeed } = useSeedVault(); - const navigate = useNavigate(); - const { unspentUtxos } = useNonOrdinalUtxos(); - let amount = new BigNumber(0); - if (unspentUtxos) { - amount = sumUnspentOutputs(unspentUtxos); - } - const isNoAmount = amount.isEqualTo(0) || !unspentUtxos[0]?.status.confirmed; - - const { data: ordinalsFee } = useQuery({ - queryKey: [`getFee-${ordinalsAddress}`], - queryFn: () => - getBtcFeesForNonOrdinalBtcSend(btcAddress, unspentUtxos, ordinalsAddress, network.type), - }); - - const { - error: errorSigningNonOrdial, - data: signedNonOrdinalBtcSend, - mutate: mutateSignNonOrdinalBtcTransaction, - } = useMutation< - SignedBtcTx, - Error, - { - recipientAddress: string; - nonOrdinalUtxos: Array; - accountIndex: number; - seedPhrase: string; - network: NetworkType; - fee?: BigNumber; - } - >({ - mutationFn: async ({ - recipientAddress, - nonOrdinalUtxos, - accountIndex, - seedPhrase: currentSeedPhrase, - network: currentNetwork, - fee, - }) => - signNonOrdinalBtcSendTransaction( - recipientAddress, - nonOrdinalUtxos, - accountIndex, - currentSeedPhrase, - currentNetwork, - fee, - ), - }); - - const onClickTransfer = async () => { - const seedPhrase = await getSeed(); - mutateSignNonOrdinalBtcTransaction({ - recipientAddress: btcAddress, - nonOrdinalUtxos: unspentUtxos, - accountIndex: selectedAccount?.id ?? 0, - seedPhrase, - network: network.type, - fee: ordinalsFee?.fee, - }); - }; - - useEffect(() => { - if (errorSigningNonOrdial) { - navigate('/tx-status', { - state: { - txid: '', - currency: 'BTC', - error: errorSigningNonOrdial.toString(), - }, - }); - } - }, [errorSigningNonOrdial]); - - useEffect(() => { - if (signedNonOrdinalBtcSend) { - navigate('/confirm-btc-tx', { - state: { - signedTxHex: signedNonOrdinalBtcSend.signedTx, - recipientAddress: btcAddress, - amount, - recipient: [ - { - address: btcAddress, - amountSats: new BigNumber(amount), - }, - ], - fiatAmount: getBtcFiatEquivalent(amount, btcFiatRate), - fee: ordinalsFee?.fee, - feePerVByte: ordinalsFee?.selectedFeeRate, - fiatFee: getBtcFiatEquivalent(ordinalsFee?.fee!, btcFiatRate), - isRestoreFundFlow: true, - unspentUtxos, - }, - }); - } - }, [signedNonOrdinalBtcSend]); - - const handleOnCancelClick = () => { - navigate(-1); - }; - - return ( - <> - - - {isNoAmount ? ( - {t('NO_FUNDS')} - ) : ( - <> - {t('DESCRIPTION')} - - - - {`${satsToBtc(amount)} BTC`} - {t('BTC')} - - - - )} - - - - - - - ); -} - -export default RestoreBtc; diff --git a/src/app/screens/restoreFunds/restoreOrdinals/index.tsx b/src/app/screens/restoreFunds/restoreOrdinals/index.tsx index a0c551e9c..695d4db2f 100644 --- a/src/app/screens/restoreFunds/restoreOrdinals/index.tsx +++ b/src/app/screens/restoreFunds/restoreOrdinals/index.tsx @@ -12,6 +12,7 @@ import { } from '@secretkeylabs/xverse-core/transactions/btc'; import { BtcOrdinal, ErrorCodes, Inscription } from '@secretkeylabs/xverse-core/types'; import { useMutation } from '@tanstack/react-query'; +import BigNumber from 'bignumber.js'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -123,9 +124,9 @@ function RestoreOrdinals() { recipientAddress: ordinalsAddress, fee: signedTx.fee, feePerVByte: signedTx.feePerVByte, - fiatFee: getBtcFiatEquivalent(signedTx.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(signedTx.fee, BigNumber(btcFiatRate)), total: signedTx.total, - fiatTotal: getBtcFiatEquivalent(signedTx.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(signedTx.total, BigNumber(btcFiatRate)), ordinalUtxo: selectedOrdinal.utxo, }, }); diff --git a/src/app/screens/sendBrc20/index.tsx b/src/app/screens/sendBrc20/index.tsx index f46642876..e6b42bd09 100644 --- a/src/app/screens/sendBrc20/index.tsx +++ b/src/app/screens/sendBrc20/index.tsx @@ -114,7 +114,7 @@ function SendBrc20Screen() { } else { console.log('Unexpected error', error); } - return Promise.reject(error); + throw error; } }; @@ -148,16 +148,11 @@ function SendBrc20Screen() { selectedAccount?.id ?? 0, seedPhrase, network.type, - ).catch((err) => { - if (Number(err) === ErrorCodes.InSufficientBalance) { - setAmountError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); - } else if (Number(err) === ErrorCodes.InSufficientBalanceWithTxFee) { - setAmountError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); - } else setAmountError(err.toString()); - }); + ); navigate('/confirm-inscription-request', { state: { - brcContent: order.inscriptionRequest.files[0].dataURL, + // !NOTE: Typing below is broken. Not going to fix as this page is deprecated. + brcContent: (order.inscriptionRequest as any).files[0].dataURL, signedTxHex: data?.signedTx, recipientAddress: order.inscriptionRequest.charge.address, amount: order.inscriptionRequest.charge.amount.toString(), @@ -165,12 +160,18 @@ function SendBrc20Screen() { fiatAmount: order.inscriptionRequest.charge.fiat_value, fee: data?.fee, feePerVByte: data?.feePerVByte, - fiatFee: getBtcFiatEquivalent(data?.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(data?.fee, BigNumber(btcFiatRate)), total: data?.total, - fiatTotal: getBtcFiatEquivalent(data?.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(data?.total, BigNumber(btcFiatRate)), }, }); } catch (err) { + if (Number(err) === ErrorCodes.InSufficientBalance) { + setAmountError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); + } else if (Number(err) === ErrorCodes.InSufficientBalanceWithTxFee) { + setAmountError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); + } else setAmountError(`${err}`); + setIsCreatingOrder(false); } }; diff --git a/src/app/screens/sendBtc/index.tsx b/src/app/screens/sendBtc/index.tsx index ab5c8eb93..31e6467ee 100644 --- a/src/app/screens/sendBtc/index.tsx +++ b/src/app/screens/sendBtc/index.tsx @@ -1,21 +1,21 @@ -import BigNumber from 'bignumber.js'; -import { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useMutation } from '@tanstack/react-query'; -import { useLocation, useNavigate } from 'react-router-dom'; import SendForm from '@components/sendForm'; -import TopRow from '@components/topRow'; import BottomBar from '@components/tabBar'; -import { signBtcTransaction } from '@secretkeylabs/xverse-core/transactions'; +import TopRow from '@components/topRow'; +import { useResetUserFlow } from '@hooks/useResetUserFlow'; +import useSeedVault from '@hooks/useSeedVault'; +import useWalletSelector from '@hooks/useWalletSelector'; +import { ErrorCodes, ResponseError } from '@secretkeylabs/xverse-core'; import { btcToSats, getBtcFiatEquivalent, satsToBtc } from '@secretkeylabs/xverse-core/currency'; +import { signBtcTransaction } from '@secretkeylabs/xverse-core/transactions'; +import { Recipient, SignedBtcTx } from '@secretkeylabs/xverse-core/transactions/btc'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; +import { useMutation } from '@tanstack/react-query'; import { BITCOIN_DUST_AMOUNT_SATS } from '@utils/constants'; -import { Recipient, SignedBtcTx } from '@secretkeylabs/xverse-core/transactions/btc'; -import { ErrorCodes, ResponseError } from '@secretkeylabs/xverse-core'; -import useWalletSelector from '@hooks/useWalletSelector'; -import useSeedVault from '@hooks/useSeedVault'; -import { useResetUserFlow } from '@hooks/useResetUserFlow'; import { isInOptions } from '@utils/helper'; +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useNavigate } from 'react-router-dom'; function SendBtcScreen() { const location = useLocation(); @@ -71,12 +71,12 @@ function SendBtcScreen() { recipientAddress, amount, recipient, - fiatAmount: getBtcFiatEquivalent(parsedAmountSats, btcFiatRate), + fiatAmount: getBtcFiatEquivalent(parsedAmountSats, BigNumber(btcFiatRate)), fee: data.fee, feePerVByte: data.feePerVByte, - fiatFee: getBtcFiatEquivalent(data.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(data.fee, BigNumber(btcFiatRate)), total: data.total, - fiatTotal: getBtcFiatEquivalent(data.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(data.total, BigNumber(btcFiatRate)), }, }); } diff --git a/src/app/screens/sendNft/index.tsx b/src/app/screens/sendNft/index.tsx index 7704b6672..84ff4a26e 100644 --- a/src/app/screens/sendNft/index.tsx +++ b/src/app/screens/sendNft/index.tsx @@ -1,146 +1,131 @@ -import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import AccountHeaderComponent from '@components/accountHeader'; -import SendForm from '@components/sendForm'; -import BottomBar from '@components/tabBar'; -import TopRow from '@components/topRow'; +import ActionButton from '@components/button'; +import { useBnsName, useBnsResolver } from '@hooks/queries/useBnsName'; +import useNftDetail from '@hooks/queries/useNftDetail'; import useStxPendingTxData from '@hooks/queries/useStxPendingTxData'; -import useNftDataSelector from '@hooks/stores/useNftDataSelector'; +import useDebounce from '@hooks/useDebounce'; import useNetworkSelector from '@hooks/useNetwork'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; -import NftImage from '@screens/nftDashboard/nftImage'; -import { validateStxAddress } from '@secretkeylabs/xverse-core'; -import { generateUnsignedTransaction } from '@secretkeylabs/xverse-core/transactions'; import { cvToHex, + generateUnsignedTransaction, StacksTransaction, uintCV, UnsignedStacksTransation, -} from '@secretkeylabs/xverse-core/types'; -import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; + validateStxAddress, +} from '@secretkeylabs/xverse-core'; import { useMutation } from '@tanstack/react-query'; -import { checkNftExists, isLedgerAccount } from '@utils/helper'; +import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { InputFeedback, InputFeedbackProps, isDangerFeedback } from '@ui-library/inputFeedback'; +import { checkNftExists } from '@utils/helper'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import styled from 'styled-components'; +import SendLayout from '../../layouts/sendLayout'; -const ScrollContainer = styled.div` +const Container = styled.div` display: flex; - flex: 1; flex-direction: column; - overflow-y: auto; - &::-webkit-scrollbar { - display: none; - } - width: 360px; - margin: auto; + justify-content: space-between; + flex-grow: 1; `; -const Container = styled.div({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - flex: 1, -}); - -const NftContainer = styled.div((props) => ({ - maxHeight: 148, - width: 148, - display: 'flex', - aspectRatio: 1, - justifyContent: 'center', - alignItems: 'center', - borderRadius: 8, - marginTop: props.theme.spacing(16), - marginBottom: props.theme.spacing(12), -})); +const StyledSendTo = styled(StyledHeading)` + margin-bottom: ${(props) => props.theme.space.l}; +`; -const NftTitleText = styled.h1((props) => ({ - ...props.theme.headline_s, - color: props.theme.colors.white_0, - textAlign: 'center', +const NextButtonContainer = styled.div((props) => ({ + position: 'sticky', + bottom: 0, + paddingBottom: props.theme.spacing(12), + paddingTop: props.theme.spacing(12), + backgroundColor: props.theme.colors.elevation0, })); -const BottomBarContainer = styled.div({ - marginTop: 'auto', -}); +const InputGroup = styled.div` + margin-top: ${(props) => props.theme.spacing(8)}px; +`; -const ButtonContainer = styled.div((props) => ({ +const Label = styled.label((props) => ({ + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_200, display: 'flex', - flexDirection: 'row', - marginLeft: '15%', - marginTop: props.theme.spacing(40), + flex: 1, })); -const Button = styled.button((props) => ({ +const AmountInputContainer = styled.div<{ error: boolean }>((props) => ({ display: 'flex', flexDirection: 'row', - justifyContent: 'flex-end', alignItems: 'center', + marginTop: props.theme.spacing(4), + marginBottom: props.theme.spacing(4), + border: props.error + ? `1px solid ${props.theme.colors.danger_dark_200}` + : `1px solid ${props.theme.colors.white_800}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - opacity: 0.8, - marginTop: props.theme.spacing(5), + paddingLeft: props.theme.spacing(5), + paddingRight: props.theme.spacing(5), + height: 44, })); -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, +const InputFieldContainer = styled.div(() => ({ + flex: 1, +})); + +const InputField = styled.input((props) => ({ + ...props.theme.typography.body_m, + backgroundColor: 'transparent', color: props.theme.colors.white_0, - textAlign: 'center', + width: '100%', + border: 'transparent', })); -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', +const ErrorContainer = styled.div((props) => ({ + marginTop: props.theme.spacing(3), + marginBottom: props.theme.spacing(12), })); +const RowContainer = styled.div({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', +}); + function SendNft() { const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); const navigate = useNavigate(); - const { id } = useParams(); const location = useLocation(); - let address: string | undefined; + const [recipientError, setRecipientError] = useState(null); + const [recipientAddress, setRecipientAddress] = useState(location.state?.recipientAddress ?? ''); - if (location.state) { - address = location.state.recipientAddress; - } - const { nftData } = useNftDataSelector(); - const nftIdDetails = id!.split('::'); - const [nft, setNft] = useState(undefined); + useResetUserFlow('/send-nft'); + + const { id } = useParams(); + const { data: nftDetail } = useNftDetail(id!); + const nft = nftDetail?.data; - useEffect(() => { - const data = nftData.find( - (nftItem) => Number(nftItem?.token_id) === Number(nftIdDetails[2].slice(1)), - ); - if (data) { - setNft(data); - } - }, []); const selectedNetwork = useNetworkSelector(); const { data: stxPendingTxData } = useStxPendingTxData(); - const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; - const { stxAddress, stxPublicKey, network, feeMultipliers, selectedAccount } = - useWalletSelector(); - const [error, setError] = useState(''); - const [recipientAddress, setRecipientAddress] = useState(''); + const { stxAddress, stxPublicKey, network, feeMultipliers } = useWalletSelector(); + const debouncedSearchTerm = useDebounce(recipientAddress, 300); + const associatedBnsName = useBnsName(debouncedSearchTerm); + const associatedAddress = useBnsResolver(debouncedSearchTerm, stxAddress); + const { isLoading, data, mutate } = useMutation< StacksTransaction, Error, - { tokenId: string; associatedAddress: string } + { tokenId: string; address: string } >({ - mutationFn: async ({ tokenId, associatedAddress }) => { + mutationFn: async ({ tokenId, address }) => { const principal = nft?.fully_qualified_token_id?.split('::')!; const name = principal[1].split(':')[0]; const contractInfo: string[] = principal[0].split('.'); const unsginedTx: UnsignedStacksTransation = { amount: tokenId, senderAddress: stxAddress, - recipientAddress: associatedAddress, + recipientAddress: address, contractAddress: contractInfo[0], contractName: contractInfo[1], assetName: name, @@ -156,7 +141,7 @@ function SendNft() { unsignedTx.auth.spendingCondition.fee * BigInt(feeMultipliers.stxSendTxMultiplier), ); } - setRecipientAddress(associatedAddress); + setRecipientAddress(address); return unsignedTx; }, }); @@ -172,81 +157,115 @@ function SendNft() { } }, [data]); - useResetUserFlow('/send-nft'); - const handleBackButtonClick = () => { navigate(-1); }; - function validateFields(associatedAddress: string): boolean { - if (!associatedAddress) { - setError(t('ERRORS.ADDRESS_REQUIRED')); - return false; - } - - if (!validateStxAddress({ stxAddress: associatedAddress, network: network.type })) { - setError(t('ERRORS.ADDRESS_INVALID')); - return false; - } - - if (associatedAddress === stxAddress) { - setError(t('ERRORS.SEND_TO_SELF')); - return false; - } - - return true; - } - - const onPressSendNFT = async (associatedAddress: string) => { + const onPressNext = async () => { if (stxPendingTxData) { if (checkNftExists(stxPendingTxData?.pendingTransactions, nft!)) { - setError(t('ERRORS.NFT_SEND_DETAIL')); + setRecipientError({ variant: 'danger', message: t('ERRORS.NFT_SEND_DETAIL') }); return; } } - if (validateFields(associatedAddress.trim()) && nft) { - setError(''); + if (!isDangerFeedback(recipientError) && nft) { const tokenId = cvToHex(uintCV(nft?.token_id.toString()!)); - mutate({ tokenId, associatedAddress }); + mutate({ tokenId, address: associatedAddress || recipientAddress }); } }; + + const handleAddressChange = (e: React.ChangeEvent) => { + setRecipientAddress(e.target.value.trim()); + }; + + useEffect(() => { + const validateRecipientAddress = (address: string): boolean => { + if (!address) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_REQUIRED') }); + return false; + } + if (!validateStxAddress({ stxAddress: address, network: network.type })) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_INVALID') }); + return false; + } + if (address === stxAddress) { + setRecipientError({ variant: 'info', message: t('YOU_ARE_TRANSFERRING_TO_YOURSELF') }); + return true; + } + setRecipientError(null); + return true; + }; + if (associatedAddress) { + validateRecipientAddress(associatedAddress); + } else if (recipientAddress) { + validateRecipientAddress(recipientAddress); + } + }, [associatedAddress, recipientAddress, network.type, stxAddress, t]); + + const isNextEnabled = !isDangerFeedback(recipientError) && !!recipientAddress; + + // hide back button if there is no history + const hideBackButton = location.key === 'default'; + return ( - <> - {isGalleryOpen && ( - <> - - {!isLedgerAccount(selectedAccount) && ( - - - - )} - - )} - - {!isGalleryOpen && } - - - - - - {nft?.token_metadata?.name} - - - {!isGalleryOpen && } - - + + +
+ + {t('SEND_TO')} + + + + + + + + + + + {associatedAddress && ( + <> + + {t('ASSOCIATED_ADDRESS')} + + + {associatedAddress} + + + )} + {associatedBnsName && ( + <> + + {t('ASSOCIATED_BNS_DOMAIN')} + + + {associatedBnsName} + + + )} + + {recipientError && } + + +
+ + + +
+
); } diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index 12a59bea9..75a49e6b8 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -1,65 +1,37 @@ -import AccountHeaderComponent from '@components/accountHeader'; import ActionButton from '@components/button'; -import BottomBar from '@components/tabBar'; -import TopRow from '@components/topRow'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; -import { ArrowLeft } from '@phosphor-icons/react'; -import { isOrdinalOwnedByAccount } from '@secretkeylabs/xverse-core'; -import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; +import { + ErrorCodes, + getBtcFiatEquivalent, + isOrdinalOwnedByAccount, + ResponseError, + UTXO, + validateBtcAddress, +} from '@secretkeylabs/xverse-core'; import { SignedBtcTx, signOrdinalSendTransaction, } from '@secretkeylabs/xverse-core/transactions/btc'; -import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; -import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { useMutation } from '@tanstack/react-query'; import Callout from '@ui-library/callout'; -import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { StyledHeading } from '@ui-library/common.styled'; import { InputFeedback, InputFeedbackProps, isDangerFeedback } from '@ui-library/inputFeedback'; -import { isLedgerAccount } from '@utils/helper'; -import { useEffect, useMemo, useState } from 'react'; +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import { devices } from 'theme'; - -const ScrollContainer = styled.div((props) => ({ - display: 'flex', - flex: 1, - flexDirection: 'column', - ...props.theme.scrollbar, -})); +import SendLayout from '../../layouts/sendLayout'; const Container = styled.div` display: flex; - flex: 1; flex-direction: column; - margin: auto; - margin-top: ${(props) => props.theme.space.xxs}; - padding: 0 ${(props) => props.theme.space.s}; justify-content: space-between; - max-width: 360px; - - @media only screen and ${devices.min.s} { - flex: initial; - max-width: 588px; - border: 1px solid ${(props) => props.theme.colors.elevation3}; - border-radius: ${(props) => props.theme.space.s}; - padding: ${(props) => props.theme.space.l} ${(props) => props.theme.space.m}; - padding-bottom: ${(props) => props.theme.space.xxl}; - margin-top: ${(props) => props.theme.space.xxxxl}; - min-height: 600px; - } -`; - -const FooterContainer = styled.div` - display: flex; - justify-content: center; - margin-bottom: ${(props) => props.theme.space.xxl}; + flex-grow: 1; `; const StyledSendTo = styled(StyledHeading)` @@ -79,7 +51,7 @@ const InputGroup = styled.div` `; const Label = styled.label((props) => ({ - ...props.theme.body_medium_m, + ...props.theme.typography.body_medium_m, color: props.theme.colors.white_200, display: 'flex', flex: 1, @@ -106,9 +78,9 @@ const InputFieldContainer = styled.div(() => ({ })); const InputField = styled.input((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, backgroundColor: 'transparent', - color: props.theme.colors.white['0'], + color: props.theme.colors.white_0, width: '100%', border: 'transparent', })); @@ -128,16 +100,6 @@ const StyledCallout = styled(Callout)` margin-bottom: ${(props) => props.theme.spacing(14)}px; `; -const BottomBarContainer = styled.div({ - marginTop: 'auto', -}); - -const Button = styled.button` - display: flex; - background-color: transparent; - margin-bottom: ${(props) => props.theme.space.l}; -`; - function SendOrdinal() { const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); const navigate = useNavigate(); @@ -153,8 +115,6 @@ function SendOrdinal() { useResetUserFlow('/send-ordinal'); - const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); - const { isLoading, data, @@ -203,9 +163,9 @@ function SendOrdinal() { recipientAddress, fee: data.fee, feePerVByte: data.feePerVByte, - fiatFee: getBtcFiatEquivalent(data.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(data.fee, BigNumber(btcFiatRate)), total: data.total, - fiatTotal: getBtcFiatEquivalent(data.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(data.total, BigNumber(btcFiatRate)), ordinalUtxo, }, }); @@ -257,63 +217,50 @@ function SendOrdinal() { }; const isNextEnabled = !isDangerFeedback(recipientError) && !!recipientAddress; - const year = new Date().getFullYear(); + + // hide back button if there is no history + const hideBackButton = location.key === 'default'; return ( - <> - {isGalleryOpen && ( - - )} - {!isGalleryOpen && } - - -
- {isGalleryOpen && !isLedgerAccount(selectedAccount) && ( - - )} - - {t('SEND_TO')} - - - - - - - - - - - - {recipientError && } - - - -
- - - -
- {isGalleryOpen && ( - - - {t('COPYRIGHT', { year })} - - - )} -
- {!isGalleryOpen && } - + + +
+ + {t('SEND_TO')} + + + + + + + + + + + + {recipientError && } + + + +
+ + + +
+
); } diff --git a/src/app/screens/settings/index.tsx b/src/app/screens/settings/index.tsx index 791895106..12677354f 100644 --- a/src/app/screens/settings/index.tsx +++ b/src/app/screens/settings/index.tsx @@ -3,7 +3,6 @@ import ArrowIcon from '@assets/img/settings/arrow.svg'; import XverseLogo from '@assets/img/settings/logo.svg'; import PasswordInput from '@components/passwordInput'; import BottomBar from '@components/tabBar'; -import useNonOrdinalUtxos from '@hooks/useNonOrdinalUtxo'; import useSeedVault from '@hooks/useSeedVault'; import useWalletReducer from '@hooks/useWalletReducer'; import useWalletSelector from '@hooks/useWalletSelector'; @@ -12,7 +11,7 @@ import { ChangeActivateRareSatsAction, } from '@stores/wallet/actions/actionCreators'; import { PRIVACY_POLICY_LINK, SUPPORT_LINK, TERMS_LINK } from '@utils/constants'; -import { isLedgerAccount } from '@utils/helper'; +import { isInOptions, isLedgerAccount } from '@utils/helper'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch } from 'react-redux'; @@ -137,7 +136,7 @@ function Setting() { }; const onRestoreFundClick = async () => { - if (isLedgerAccount(selectedAccount)) { + if (isLedgerAccount(selectedAccount) && !isInOptions()) { await chrome.tabs.create({ url: chrome.runtime.getURL('options.html#/restore-funds'), }); diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index 6dd3cf894..f85e8297f 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -15,17 +15,13 @@ import useDetectOrdinalInSignPsbt from '@hooks/useDetectOrdinalInSignPsbt'; import useSignPsbtTx from '@hooks/useSignPsbtTx'; import useWalletSelector from '@hooks/useWalletSelector'; import Transport from '@ledgerhq/hw-transport-webusb'; -import { - getBtcFiatEquivalent, - satsToBtc, - signIncomingSingleSigPSBT, -} from '@secretkeylabs/xverse-core'; +import { getBtcFiatEquivalent, satsToBtc, signLedgerPSBT } from '@secretkeylabs/xverse-core'; import { Transport as TransportType } from '@secretkeylabs/xverse-core/ledger/types'; import { parsePsbt, psbtBase64ToHex } from '@secretkeylabs/xverse-core/transactions/psbt'; import { isLedgerAccount } from '@utils/helper'; import BigNumber from 'bignumber.js'; import { decodeToken } from 'jsontokens'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -95,8 +91,15 @@ const SuccessActionsContainer = styled.div((props) => ({ })); function SignPsbtRequest() { - const { btcAddress, ordinalsAddress, selectedAccount, network, btcFiatRate } = - useWalletSelector(); + const { + btcAddress, + btcPublicKey, + ordinalsAddress, + ordinalsPublicKey, + selectedAccount, + network, + btcFiatRate, + } = useWalletSelector(); const navigate = useNavigate(); const { t } = useTranslation('translation', { keyPrefix: 'CONFIRM_TRANSACTION' }); const { t: signatureRequestTranslate } = useTranslation('translation', { @@ -120,15 +123,14 @@ function SignPsbtRequest() { const request = decodeToken(requestToken) as any as SignTransactionOptions; const btcClient = useBtcClient(); - const handlePsbtParsing = useCallback(() => { + const parsedPsbt = useMemo(() => { try { return parsePsbt(selectedAccount!, payload.inputsToSign, payload.psbtBase64, network.type); } catch (err) { - return ''; + return undefined; } - }, [selectedAccount, payload.psbtBase64]); + }, [selectedAccount, payload.inputsToSign, payload.psbtBase64, network.type]); - const parsedPsbt = useMemo(() => handlePsbtParsing(), [handlePsbtParsing]); const { loading, bundleItemsData, userReceivesOrdinal } = useDetectOrdinalInSignPsbt(parsedPsbt); const signingAddresses = useMemo( () => getSigningAddresses(payload.inputsToSign), @@ -187,7 +189,7 @@ function SignPsbtRequest() { const onSignPsbtConfirmed = async () => { try { if (isLedgerAccount(selectedAccount)) { - // setIsModalVisible(true); + setIsModalVisible(true); return; } @@ -232,19 +234,20 @@ function SignPsbtRequest() { const handleLedgerPsbtSigning = async (transport: TransportType) => { const addressIndex = selectedAccount?.deviceAccountIndex; - const { inputsToSign, psbtBase64, broadcast } = payload; + const { psbtBase64, broadcast } = payload; if (addressIndex === undefined) { throw new Error('Account not found'); } - const signingResponse = await signIncomingSingleSigPSBT({ + const signingResponse = await signLedgerPSBT({ transport, network: network.type, addressIndex, - inputsToSign, - psbtBase64, - finalize: broadcast, + psbtInputBase64: psbtBase64, + finalize: broadcast ?? false, + nativeSegwitPubKey: btcPublicKey, + taprootPubKey: ordinalsPublicKey, }); let txId: string = ''; @@ -346,53 +349,46 @@ function SignPsbtRequest() { ) : ( <> - {isLedgerAccount(selectedAccount) ? ( - - - - ) : ( - - {t('REVIEW_TRANSACTION')} - {!payload.broadcast && ( - - )} - {bundleItemsData && - bundleItemsData.map((bundleItem, index) => ( - - ))} - - - - - {payload.broadcast ? ( - + {t('REVIEW_TRANSACTION')} + {!payload.broadcast && } + {bundleItemsData && + bundleItemsData.map((bundleItem, index) => ( + - ) : null} - {hasOutputScript && } - - )} + ))} + + + + + {payload.broadcast ? ( + + ) : null} + {hasOutputScript && } +
@@ -402,7 +398,6 @@ function SignPsbtRequest() { text={t('CONFIRM')} onPress={onSignPsbtConfirmed} processing={isSigning} - disabled={isLedgerAccount(selectedAccount)} /> diff --git a/src/app/screens/swap/swapTokenBlock/index.tsx b/src/app/screens/swap/swapTokenBlock/index.tsx index 26fe27324..f36ea34fa 100644 --- a/src/app/screens/swap/swapTokenBlock/index.tsx +++ b/src/app/screens/swap/swapTokenBlock/index.tsx @@ -1,7 +1,10 @@ import ChevronIcon from '@assets/img/swap/chevron.svg'; import TokenImage from '@components/tokenImage'; +import useWalletSelector from '@hooks/useWalletSelector'; import { SwapToken } from '@screens/swap/types'; +import { currencySymbolMap } from '@secretkeylabs/xverse-core/types/currency'; import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; const Container = styled.div((props) => ({ @@ -115,6 +118,7 @@ function SwapTokenBlock({ error, }: SwapTokenBlockProps) { const { t } = useTranslation('translation', { keyPrefix: 'SWAP_SCREEN' }); + const { fiatCurrency } = useWalletSelector(); return ( @@ -141,9 +145,14 @@ function SwapTokenBlock({ /> - - {selectedCoin?.fiatAmount ? `≈ $ ${selectedCoin.fiatAmount} USD` : '--'} - + {value}} + /> diff --git a/src/app/screens/swap/useCurrencyConversion.tsx b/src/app/screens/swap/useCurrencyConversion.tsx index b912ea892..65ef55061 100644 --- a/src/app/screens/swap/useCurrencyConversion.tsx +++ b/src/app/screens/swap/useCurrencyConversion.tsx @@ -6,6 +6,7 @@ import { AlexSDK, Currency } from 'alex-sdk'; import BigNumber from 'bignumber.js'; import { SwapToken } from './types'; +// eslint-disable-next-line import/prefer-default-export export function useCurrencyConversion() { const alexSDK = new AlexSDK(); const { @@ -46,7 +47,14 @@ export function useCurrencyConversion() { amount, fiatAmount: amount != null - ? Number(getFiatEquivalent(amount, 'STX', stxBtcRate as any, btcFiatRate as any)) + ? Number( + getFiatEquivalent( + amount, + 'STX', + BigNumber(stxBtcRate) as any, + BigNumber(btcFiatRate) as any, + ), + ) : undefined, }; } @@ -63,7 +71,9 @@ export function useCurrencyConversion() { balance: Number(ftDecimals(token.balance, token.decimals ?? 0)), fiatAmount: amount != null - ? Number(getFiatEquivalent(amount, 'FT', stxBtcRate as any, btcFiatRate as any, token)) + ? Number( + getFiatEquivalent(amount, 'FT', BigNumber(stxBtcRate), BigNumber(btcFiatRate), token), + ) : undefined, }; } diff --git a/src/app/screens/transactionStatus/index.tsx b/src/app/screens/transactionStatus/index.tsx index 000f9480c..1e397eba8 100644 --- a/src/app/screens/transactionStatus/index.tsx +++ b/src/app/screens/transactionStatus/index.tsx @@ -10,13 +10,12 @@ import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -const TxStatusContainer = styled.div({ - background: 'rgba(25, 25, 48, 0.74)', +const TxStatusContainer = styled.div((props) => ({ + background: props.theme.colors.elevation0, display: 'flex', flexDirection: 'column', height: '100%', - backdropFilter: 'blur(16px)', -}); +})); const Container = styled.div({ display: 'flex', @@ -84,14 +83,14 @@ const Image = styled.img({ }); const HeadingText = styled.h1((props) => ({ - ...props.theme.headline_s, + ...props.theme.typography.headline_s, color: props.theme.colors.white_0, textAlign: 'center', marginTop: props.theme.spacing(8), })); const BodyText = styled.h1((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, color: props.theme.colors.white_400, marginTop: props.theme.spacing(8), textAlign: 'center', @@ -110,19 +109,19 @@ const TxIDText = styled.h1((props) => ({ })); const BeforeButtonText = styled.h1((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, color: props.theme.colors.white_400, })); const IDText = styled.h1((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, color: props.theme.colors.white_0, marginTop: props.theme.spacing(2), wordBreak: 'break-all', })); const ButtonText = styled.h1((props) => ({ - ...props.theme.body_m, + ...props.theme.typography.body_m, marginRight: props.theme.spacing(2), color: props.theme.colors.white_0, })); @@ -152,6 +151,7 @@ function TransactionStatus() { browserTx, isOrdinal, isNft, + isRareSat, errorTitle, isBrc20TokenFlow, isSponsorServiceError, @@ -186,9 +186,10 @@ function TransactionStatus() { const onCloseClick = () => { if (browserTx) window.close(); - else if (isOrdinal) navigate(-4); - else if (isNft) navigate(-3); - else navigate(-3); + else if (isRareSat) navigate('/nft-dashboard?tab=rareSats'); + else if (isOrdinal) navigate('/nft-dashboard?tab=inscriptions'); + else if (isNft) navigate('/nft-dashboard?tab=nfts'); + else navigate('/'); }; const handleClickTrySwapAgain = () => { diff --git a/src/app/stores/index.ts b/src/app/stores/index.ts index 94f0fbe20..d8fdd1d65 100644 --- a/src/app/stores/index.ts +++ b/src/app/stores/index.ts @@ -3,7 +3,6 @@ import { applyMiddleware, combineReducers, createStore } from 'redux'; import { PersistConfig, persistReducer, persistStore } from 'redux-persist'; import { createStateSyncMiddleware, initMessageListener } from 'redux-state-sync'; import NftDataStateReducer from './nftData/reducer'; -import * as actions from './wallet/actions/types'; import { WalletState } from './wallet/actions/types'; import walletReducer from './wallet/reducer'; @@ -33,14 +32,8 @@ export type StoreState = ReturnType; const storeMiddleware = [ createStateSyncMiddleware({ - // We only want to sync seedphrase data for onboarding - whitelist: [ - actions.StoreEncryptedSeedKey, - actions.SelectAccountKey, - actions.SetWalletUnlockedKey, - actions.AddAccountKey, - actions.UpdateLedgerAccountsKey, - ], + // We don't want to sync the redux-persist actions + blacklist: ['persist/PERSIST', 'persist/REHYDRATE'], }), ]; const store = createStore(persistedReducer, applyMiddleware(...storeMiddleware)); diff --git a/src/app/stores/nftData/actions/actionCreator.ts b/src/app/stores/nftData/actions/actionCreator.ts index 6c98635e9..e87b88878 100644 --- a/src/app/stores/nftData/actions/actionCreator.ts +++ b/src/app/stores/nftData/actions/actionCreator.ts @@ -1,15 +1,6 @@ -/* eslint-disable import/prefer-default-export */ -import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; -import { Inscription } from '@secretkeylabs/xverse-core/types/api/ordinals'; +import { Inscription } from '@secretkeylabs/xverse-core'; import * as actions from './types'; -export function setNftDataAction(nftData: NftData[]): actions.SetNftData { - return { - type: actions.SetNftDataKey, - nftData, - }; -} - export function setSelectedOrdinalAction( selectedOrdinal: Inscription | null, ): actions.SetSelectedOrdinal { diff --git a/src/app/stores/nftData/actions/types.ts b/src/app/stores/nftData/actions/types.ts index 7c76f3b7f..69056dd72 100644 --- a/src/app/stores/nftData/actions/types.ts +++ b/src/app/stores/nftData/actions/types.ts @@ -1,26 +1,16 @@ -import { Inscription } from '@secretkeylabs/xverse-core/types/api/ordinals'; -import { NftData } from '@secretkeylabs/xverse-core/types/api/stacks/assets'; +import type { Inscription } from '@secretkeylabs/xverse-core'; import { Bundle } from '@utils/rareSats'; export interface NftDataState { - nftData: NftData[]; selectedOrdinal: Inscription | null; selectedSatBundle: Bundle | null; selectedSatBundleItemIndex: number | null; } -export const SetNftDataKey = 'SetNftData'; - export const SetSelectedOrdinalKey = 'SetSelectedOrdinal'; - export const SetSelectedSatBundleKey = 'SetSelectedSatBundle'; export const SetSelectedSatBundleItemIndexKey = 'SetSelectedSatBundleItemIndex'; -export interface SetNftData { - type: typeof SetNftDataKey; - nftData: NftData[]; -} - export interface SetSelectedOrdinal { type: typeof SetSelectedOrdinalKey; selectedOrdinal: Inscription | null; @@ -36,7 +26,6 @@ export interface SetSelectedSatBundleItemIndex { } export type NftDataAction = - | SetNftData | SetSelectedOrdinal | SetSelectedSatBundle | SetSelectedSatBundleItemIndex; diff --git a/src/app/stores/nftData/reducer.ts b/src/app/stores/nftData/reducer.ts index 8d4c4701c..4d37c0bb7 100644 --- a/src/app/stores/nftData/reducer.ts +++ b/src/app/stores/nftData/reducer.ts @@ -1,14 +1,12 @@ import { NftDataAction, NftDataState, - SetNftDataKey, SetSelectedOrdinalKey, SetSelectedSatBundleItemIndexKey, SetSelectedSatBundleKey, } from './actions/types'; const initialNftDataState: NftDataState = { - nftData: [], selectedOrdinal: null, selectedSatBundle: null, selectedSatBundleItemIndex: null, @@ -20,11 +18,6 @@ const NftDataStateReducer = ( action: NftDataAction, ): NftDataState => { switch (action.type) { - case SetNftDataKey: - return { - ...state, - nftData: action.nftData, - }; case SetSelectedOrdinalKey: return { ...state, diff --git a/src/app/stores/wallet/actions/actionCreators.ts b/src/app/stores/wallet/actions/actionCreators.ts index cbf9a060e..3648dd6c0 100644 --- a/src/app/stores/wallet/actions/actionCreators.ts +++ b/src/app/stores/wallet/actions/actionCreators.ts @@ -13,6 +13,16 @@ import type { import BigNumber from 'bignumber.js'; import * as actions from './types'; +type NumberLike = string | number | bigint | BigNumber; + +function numberLikeToStringOrThrow(value: NumberLike, name: string): string { + if (typeof value !== 'bigint' && BigNumber(value).isNaN()) { + throw new Error(`Invalid value for ${name}: ${value}`); + } + + return `${value}`; +} + export function setWalletAction(wallet: BaseWallet): actions.SetWallet { return { type: actions.SetWalletKey, @@ -103,37 +113,37 @@ export function setFeeMultiplierAction(feeMultipliers: AppInfo): actions.SetFeeM } export function setCoinRatesAction( - stxBtcRate: BigNumber, - btcFiatRate: BigNumber, + stxBtcRate: NumberLike, + btcFiatRate: NumberLike, ): actions.SetCoinRates { return { type: actions.SetCoinRatesKey, - stxBtcRate, - btcFiatRate, + stxBtcRate: numberLikeToStringOrThrow(stxBtcRate, 'stx fiat rate'), + btcFiatRate: numberLikeToStringOrThrow(btcFiatRate, 'btc fiat rate'), }; } export function setStxWalletDataAction( - stxBalance: BigNumber, - stxAvailableBalance: BigNumber, - stxLockedBalance: BigNumber, + stxBalance: NumberLike, + stxAvailableBalance: NumberLike, + stxLockedBalance: NumberLike, stxTransactions: TransactionData[], stxNonce: number, ): actions.SetStxWalletData { return { type: actions.SetStxWalletDataKey, - stxBalance, - stxAvailableBalance, - stxLockedBalance, + stxBalance: numberLikeToStringOrThrow(stxBalance, 'stx balance'), + stxAvailableBalance: numberLikeToStringOrThrow(stxAvailableBalance, 'stx available'), + stxLockedBalance: numberLikeToStringOrThrow(stxLockedBalance, 'stx locked'), stxTransactions, stxNonce, }; } -export function SetBtcWalletDataAction(balance: BigNumber): actions.SetBtcWalletData { +export function SetBtcWalletDataAction(balance: NumberLike): actions.SetBtcWalletData { return { type: actions.SetBtcWalletDataKey, - balance, + balance: numberLikeToStringOrThrow(balance, 'bitcoin balance'), }; } diff --git a/src/app/stores/wallet/actions/types.ts b/src/app/stores/wallet/actions/types.ts index 26c2db85b..df898784b 100644 --- a/src/app/stores/wallet/actions/types.ts +++ b/src/app/stores/wallet/actions/types.ts @@ -9,7 +9,6 @@ import type { SupportedCurrency, TransactionData, } from '@secretkeylabs/xverse-core'; -import BigNumber from 'bignumber.js'; export const SetWalletKey = 'SetWallet'; export const ResetWalletKey = 'ResetWallet'; @@ -67,13 +66,13 @@ export interface WalletState { network: SettingsNetwork; encryptedSeed: string; fiatCurrency: SupportedCurrency; - btcFiatRate: BigNumber; - stxBtcRate: BigNumber; - stxBalance: BigNumber; - stxAvailableBalance: BigNumber; - stxLockedBalance: BigNumber; + btcFiatRate: string; + stxBtcRate: string; + stxBalance: string; + stxAvailableBalance: string; + stxLockedBalance: string; stxNonce: number; - btcBalance: BigNumber; + btcBalance: string; coinsList: FungibleToken[] | null; coins: Coin[]; brcCoinsList: FungibleToken[] | null; @@ -142,22 +141,22 @@ export interface SelectAccount { } export interface SetCoinRates { type: typeof SetCoinRatesKey; - stxBtcRate: BigNumber; - btcFiatRate: BigNumber; + stxBtcRate: string; + btcFiatRate: string; } export interface SetStxWalletData { type: typeof SetStxWalletDataKey; - stxBalance: BigNumber; - stxAvailableBalance: BigNumber; - stxLockedBalance: BigNumber; + stxBalance: string; + stxAvailableBalance: string; + stxLockedBalance: string; stxTransactions: TransactionData[]; stxNonce: number; } export interface SetBtcWalletData { type: typeof SetBtcWalletDataKey; - balance: BigNumber; + balance: string; } export interface SetCoinData { @@ -248,6 +247,7 @@ export type WalletActions = | GetActiveAccounts | ChangeActivateOrdinals | ChangeActivateRareSats + | SetRareSatsNoticeDismissed | ChangeShowBtcReceiveAlert | ChangeShowOrdinalReceiveAlert | ChangeShowDataCollectionAlert diff --git a/src/app/stores/wallet/reducer.ts b/src/app/stores/wallet/reducer.ts index 6b95f5164..fee58665e 100644 --- a/src/app/stores/wallet/reducer.ts +++ b/src/app/stores/wallet/reducer.ts @@ -1,15 +1,16 @@ import { initialNetworksList } from '@utils/constants'; -import BigNumber from 'bignumber.js'; import { AddAccountKey, ChangeFiatCurrencyKey, ChangeHasActivatedOrdinalsKey, + ChangeHasActivatedRareSatsKey, ChangeNetworkKey, ChangeShowBtcReceiveAlertKey, + ChangeShowDataCollectionAlertKey, ChangeShowOrdinalReceiveAlertKey, - UpdateLedgerAccountsKey, FetchAccountKey, GetActiveAccountsKey, + RareSatsNoticeDismissedKey, ResetWalletKey, SelectAccountKey, SetBrcCoinsListKey, @@ -20,15 +21,13 @@ import { SetStxWalletDataKey, SetWalletKey, SetWalletLockPeriodKey, + SetWalletUnlockedKey, StoreEncryptedSeedKey, + UpdateLedgerAccountsKey, UpdateVisibleCoinListKey, WalletActions, WalletSessionPeriods, WalletState, - SetWalletUnlockedKey, - ChangeShowDataCollectionAlertKey, - RareSatsNoticeDismissedKey, - ChangeHasActivatedRareSatsKey, } from './actions/types'; const initialWalletState: WalletState = { @@ -45,13 +44,13 @@ const initialWalletState: WalletState = { selectedAccount: null, encryptedSeed: '', fiatCurrency: 'USD', - btcFiatRate: new BigNumber(0), - stxBtcRate: new BigNumber(0), - stxBalance: new BigNumber(0), - stxAvailableBalance: new BigNumber(0), - stxLockedBalance: new BigNumber(0), + btcFiatRate: '0', + stxBtcRate: '0', + stxBalance: '0', + stxAvailableBalance: '0', + stxLockedBalance: '0', stxNonce: 0, - btcBalance: new BigNumber(0), + btcBalance: '0', coinsList: null, coins: [], brcCoinsList: [], diff --git a/src/app/ui-library/snackBar.tsx b/src/app/ui-library/snackBar.tsx new file mode 100644 index 000000000..d546d399a --- /dev/null +++ b/src/app/ui-library/snackBar.tsx @@ -0,0 +1,75 @@ +import toast from 'react-hot-toast'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; + +type ToastType = 'success' | 'error' | 'neutral'; + +interface ToastProps { + text: string; + type: ToastType; +} + +const getBackgroundColor = (type: ToastType, theme: any): string => { + const colors = { + success: theme.colors.feedback.success, + error: theme.colors.feedback.error, + neutral: theme.colors.feedback.neutral, + }; + return colors[type] || theme.colors.feedback.neutral; +}; + +const getTextColor = (type: ToastType, theme: any): string => { + const colors = { + success: theme.colors.elevation0, + error: theme.colors.white_0, + neutral: theme.colors.white_0, + }; + return colors[type] || theme.colors.elevation0; +}; + +const ToastContainer = styled.div<{ type: ToastType }>` + display: flex; + flex-direction: row; + background: ${(props) => getBackgroundColor(props.type, props.theme)}; + border-radius: 12px; + box-shadow: 0px 7px 16px -4px rgba(25, 25, 48, 0.25); + height: 44px; + padding: 12px 20px; + width: auto; + max-width: 306px; + align-items: center; + justify-content: space-between; + margin-bottom: 80px; +`; + +const ToastMessage = styled.h1<{ type: ToastType }>` + ${({ theme }) => theme.typography.body_medium_m}; + color: ${(props) => getTextColor(props.type, props.theme)}; + margin-right: 24px; +`; + +const ToastDismissButton = styled.h1<{ type: ToastType }>` + ${({ theme }) => theme.typography.body_medium_m}; + color: ${(props) => getTextColor(props.type, props.theme)}; + background: transparent; + cursor: pointer; +`; + +export function SnackBar({ text, type }: ToastProps) { + const { t } = useTranslation('translation'); + + const dismissToast = () => { + toast.dismiss(); + }; + + return ( + + {text} + + {t('OK')} + + + ); +} + +export default SnackBar; diff --git a/src/app/utils/nfts.ts b/src/app/utils/nfts.ts new file mode 100644 index 000000000..5ab03f46b --- /dev/null +++ b/src/app/utils/nfts.ts @@ -0,0 +1,36 @@ +import { getBnsNftName, NonFungibleToken, StacksCollectionData } from '@secretkeylabs/xverse-core'; + +export const getNftsTabGridItemSubText = (collection: StacksCollectionData) => + collection?.all_nfts?.length > 1 ? `${collection.all_nfts.length} Items` : '1 Item'; + +export const isBnsCollection = (collectionId?: string | null): boolean => + collectionId === 'SP000000000000000000002Q6VF78.bns'; + +// fully_qualified_token_id like: +// SP1E1RNN4JZ7T6Y0JVCSY2TH4918Z590P8JAB9HZM.radboy-first-feat::radboy-first-feat:64 +export const getFullyQualifiedKey = ({ + tokenId, + contractName, + contractAddress, +}: NonFungibleToken['identifier']) => + `${contractAddress}.${contractName}::${contractName}:${tokenId}`; + +export const getIdentifier = (fullyQualifiedKey: string): NonFungibleToken['identifier'] => { + const [principal, , contractName, tokenId] = fullyQualifiedKey.split(':'); + const [contractAddress] = principal.split('.'); + return { + tokenId, + contractName, + contractAddress, + }; +}; + +export const getNftCollectionsGridItemId = ( + nft: NonFungibleToken, + collectionData: StacksCollectionData, +) => + isBnsCollection(collectionData?.collection_id) + ? getBnsNftName(nft) + : nft?.identifier.tokenId + ? `${collectionData?.collection_name} #${nft?.identifier.tokenId}` + : `${collectionData?.collection_name}`; diff --git a/src/assets/img/nftDashboard/bns.svg b/src/assets/img/nftDashboard/bns.svg new file mode 100644 index 000000000..5d77a17ba --- /dev/null +++ b/src/assets/img/nftDashboard/bns.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/img/nftDashboard/ic_nft_diamond.svg b/src/assets/img/nftDashboard/ic_nft_diamond.svg deleted file mode 100644 index b78cce2ce..000000000 --- a/src/assets/img/nftDashboard/ic_nft_diamond.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/assets/img/nftDashboard/nft_user.svg b/src/assets/img/nftDashboard/nft_user.svg deleted file mode 100644 index 0101a3c43..000000000 --- a/src/assets/img/nftDashboard/nft_user.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/locales/en.json b/src/locales/en.json index 4f09fcf17..140f535f4 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -539,7 +539,8 @@ "ERROR_RETRIEVING": "We are having trouble retrieving data.", "TRY_AGAIN": "Please try again later.", "LOAD_MORE": "Load more", - "TOTAL_ITEMS": "{{total}} items", + "TOTAL_ITEMS_one": "{{count}} item", + "TOTAL_ITEMS_other": "{{count}} items", "WEB_GALLERY": "Open gallery", "RECEIVE": "Receive", "SEND": "Send", @@ -630,7 +631,7 @@ "RARITY": "Overall rarity", "CONTRACT_ID": "Contract ID", "ATTRIBUTES": "Attributes", - "VIEW_CONTRACT": "View the contract on", + "VIEW_CONTRACT": "View on", "STACKS_EXPLORER": "Stacks Explorer", "DETAILS": "See detail on", "GAMMA": "Gamma.io", @@ -912,7 +913,7 @@ }, "COMPLETE": { "INSCRIBED": "Ordinal inscribed", - "MESSAGE": "Your ordinal have been successfully inscribed and should appear in a few minutes.", + "MESSAGE": "Your ordinal has been successfully inscribed and should appear in a few minutes.", "SEE_ON": "See on", "BITCOIN_EXPLORER": "mempool", "TRANSACTION_ID": "Transaction ID", @@ -1107,11 +1108,14 @@ "RARE_SAT": "Rare Sat", "INSCRIBED_SAT": "Inscribed Sat" }, - "ORDINALS_COLLECTION_SCREEN": { + "COLLECTIBLE_COLLECTION_SCREEN": { "BACK_TO_GALLERY": "Back to gallery", "COLLECTION_FLOOR_PRICE": "Collection floor price", "EST_PORTFOLIO_VALUE": "Est. portfolio value", "COLLECTION": "Collection", - "LOAD_MORE": "Load more" + "LOAD_MORE": "Load more", + "ERRORS": { + "FAILED_TO_FETCH": "Failed to fetch data" + } } } diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 47da6c8e9..e779d1399 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -7,3 +7,4 @@ declare module '*.jpeg'; declare module '*.jpg'; declare module '*.otf'; declare module '*.ttf'; +declare module 'react-is-visible'; From aa7b7d3f4e80d784bdf73b7f8d2617f789bba809 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Fri, 24 Nov 2023 10:48:29 +0500 Subject: [PATCH 13/28] feat: send flow (#63) * feat: tweak rare sats bundle screen to support new satributes * feat: update send rare sats screen * feat: update confirm screen * fix: UI * fix: resolve comments --------- Co-authored-by: fede erbes --- src/app/components/assetModal/index.tsx | 90 ++++++++++++ .../bundleItem.tsx | 128 ++++++++++++++++++ .../confirmBtcTransactionComponent/index.tsx | 105 +++++++++++++- .../components/recipientComponent/index.tsx | 53 ++++---- .../confirmOrdinalTransaction/index.tsx | 22 +-- src/app/screens/sendRareSat/index.tsx | 49 ++----- src/app/utils/rareSats.ts | 18 +++ src/assets/img/rareSats/satBundle.svg | 5 + 8 files changed, 382 insertions(+), 88 deletions(-) create mode 100644 src/app/components/assetModal/index.tsx create mode 100644 src/app/components/confirmBtcTransactionComponent/bundleItem.tsx create mode 100644 src/assets/img/rareSats/satBundle.svg diff --git a/src/app/components/assetModal/index.tsx b/src/app/components/assetModal/index.tsx new file mode 100644 index 000000000..a7ab49972 --- /dev/null +++ b/src/app/components/assetModal/index.tsx @@ -0,0 +1,90 @@ +import Cross from '@assets/img/dashboard/X.svg'; +import { animated, useSpring } from '@react-spring/web'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { CondensedInscription } from '@secretkeylabs/xverse-core/types'; +import { Inscription } from '@utils/rareSats'; +import styled from 'styled-components'; + +const TransparentButton = styled.button({ + background: 'transparent', + display: 'flex', + alignItems: 'center', + marginLeft: 10, +}); + +const CrossContainer = styled.div({ + display: 'flex', + marginTop: 10, + justifyContent: 'flex-end', + alignItems: 'flex-end', +}); + +const OrdinalOuterImageContainer = styled.div({ + justifyContent: 'center', + alignItems: 'center', + borderRadius: 2, + display: 'flex', + flexDirection: 'column', + flex: 1, +}); + +const OrdinalImageContainer = styled.div({ + width: '50%', +}); + +const OrdinalBackgroundContainer = styled(animated.div)({ + width: '100%', + height: '100%', + top: 0, + left: 0, + bottom: 0, + right: 0, + position: 'fixed', + zIndex: 10, + background: 'rgba(18, 21, 30, 0.8)', + backdropFilter: 'blur(16px)', + padding: 16, + display: 'flex', + flexDirection: 'column', +}); + +interface Props { + show: boolean; + inscription: Inscription; + onClose: () => void; +} + +function AssetModal({ show, inscription, onClose }: Props) { + const consdensedInscription: CondensedInscription = { + ...inscription, + number: inscription.inscription_number, + }; + const styles = useSpring({ + from: { + opacity: 0, + y: 24, + }, + to: { + y: 0, + opacity: 1, + }, + delay: 100, + }); + + return ( + + + + cross + + + + + + + + + ); +} + +export default AssetModal; diff --git a/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx new file mode 100644 index 000000000..cb3281fec --- /dev/null +++ b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx @@ -0,0 +1,128 @@ +import OrdinalIcon from '@assets/img/rareSats/ic_ordinal_small.svg'; +import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; +import { DotsThree, Eye } from '@phosphor-icons/react'; +import { StyledP } from '@ui-library/common.styled'; +import { BundleSatRange, getSatLabel, Inscription } from '@utils/rareSats'; +import { useTranslation } from 'react-i18next'; +import { NumericFormat } from 'react-number-format'; +import styled from 'styled-components'; +import Theme from 'theme'; + +const RangeContainer = styled.div``; + +const Range = styled.div` + display: flex; + border-radius: 6px; + border: 1px solid var(--white-800, rgba(255, 255, 255, 0.2)); + padding: 1px; + flex-wrap: wrap; + flex-direction: row; + align-items: center; +`; + +interface ComponentWithDividerProps { + showDivider: boolean; +} + +const Container = styled.div` + padding-top:${(props) => props.theme.space.s}; + padding-bottom:${(props) => props.theme.space.s}; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + border-bottom: ${(props) => + props.showDivider ? '1px solid rgba(255, 255, 255, 0.10)' : 'transparent'}; + width: 100%; +}`; + +const Column = styled.div` + display: flex; + flex: 1; + flex-direction: column; + align-items: flex-end; +`; + +const SatsText = styled(StyledP)` + width: 100%; + text-align: right; +`; +const InscriptionRow = styled.button` + display: flex; + flex-direction: row; + align-items: center; + background-color: transparent; +`; +const InscriptionText = styled(StyledP)` + text-wrap: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + margin-left: 4px; +`; + +const BundleText = styled(StyledP)` + text-align: right; + width: 100%; +`; + +export function BundleItem({ + item, + ordinalEyePressed, + showDivider, +}: { + item: BundleSatRange; + ordinalEyePressed: (inscription: Inscription) => void; + showDivider?: boolean; +}) { + const { t } = useTranslation('translation'); + + const renderedIcons = () => ( + + + {item.satributes.map((satribute, index) => { + if (index > 4) return null; + if (index === 4) { + return ; + } + return ; + })} + + + ); + + return ( + + {renderedIcons()} + + {getSatLabel(item.satributes)} + 1 ? ' Sats' : ' Sat'} + thousandSeparator + renderText={(value: string) => ( + + {value} + + )} + /> + {item.inscriptions.map((inscription) => ( + { + ordinalEyePressed(inscription); + }} + > + ordinal + + {inscription.inscription_number} + + + + ))} + + + ); +} diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index a39114420..a4abce6fc 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -1,14 +1,18 @@ import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; +import BundleIcon from '@assets/img/rareSats/satBundle.svg'; import AssetIcon from '@assets/img/transactions/Assets.svg'; +import AssetModal from '@components/assetModal'; import ActionButton from '@components/button'; import InfoContainer from '@components/infoContainer'; import RecipientComponent from '@components/recipientComponent'; import TopRow from '@components/topRow'; import TransactionSettingAlert from '@components/transactionSetting'; import TransferFeeView from '@components/transferFeeView'; +import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; +import { CaretDown } from '@phosphor-icons/react'; import { ErrorCodes, getBtcFiatEquivalent, @@ -25,13 +29,17 @@ import { } from '@secretkeylabs/xverse-core/transactions/btc'; import { useMutation } from '@tanstack/react-query'; import Callout from '@ui-library/callout'; +import { StyledP } from '@ui-library/common.styled'; import { CurrencyTypes } from '@utils/constants'; +import { BundleSatRange, Inscription } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; +import Theme from 'theme'; import TransactionDetailComponent from '../transactionDetailComponent'; +import { BundleItem } from './bundleItem'; const OuterContainer = styled.div` display: flex; @@ -55,6 +63,10 @@ interface ButtonProps { isBtcSendBrowserTx?: boolean; } +interface BundleItemContainerProps { + addMargin: boolean; +} + const ButtonContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', @@ -103,14 +115,18 @@ const ErrorText = styled.h1((props) => ({ color: props.theme.colors.danger_medium, })); +const BundleItemsContainer = styled.div` + margin-top: ${(props) => (props.addMargin ? Theme.space.m : 0)}; +`; + interface ReviewTransactionTitleProps { - isOridnalTx: boolean; + centerAligned: boolean; } const ReviewTransactionText = styled.h1((props) => ({ ...props.theme.typography.headline_s, color: props.theme.colors.white_0, marginBottom: props.theme.spacing(16), - textAlign: props.isOridnalTx ? 'center' : 'left', + textAlign: props.centerAligned ? 'center' : 'left', })); const CalloutContainer = styled.div((props) => ({ @@ -118,6 +134,37 @@ const CalloutContainer = styled.div((props) => ({ marginhorizontal: props.theme.spacing(8), })); +const SatsBundle = styled.button` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background-color: ${(props) => props.theme.colors.elevation1}; +`; + +const SatsBundleContainer = styled.div` + display: flex; + flex-direction: column; + margin-bottom: ${(props) => props.theme.space.s}; + border-radius: ${(props) => props.theme.space.s}; + padding: ${(props) => props.theme.space.m}; + background-color: ${(props) => props.theme.colors.elevation1}; +`; + +const Row = styled.div` + display: flex; + flex-direction: row; + align-items: center; +`; + +const BundleTitle = styled(StyledP)` + margin-left: ${(props) => props.theme.space.s}; +`; + +const BundleValue = styled(StyledP)` + margin-right: ${(props) => props.theme.space.xs}; +`; + interface Props { currentFee: BigNumber; feePerVByte: BigNumber; // TODO tim: is this the same as currentFeeRate? refactor to be clear @@ -167,12 +214,15 @@ function ConfirmBtcTransactionComponent({ const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const [loading, setLoading] = useState(false); const { btcAddress, selectedAccount, network, btcFiatRate, feeMultipliers } = useWalletSelector(); + const { selectedSatBundle } = useNftDataSelector(); const { getSeed } = useSeedVault(); const [showFeeSettings, setShowFeeSettings] = useState(false); const [error, setError] = useState(''); const [signedTx, setSignedTx] = useState(signedTxHex); const [total, setTotal] = useState(new BigNumber(0)); const [showFeeWarning, setShowFeeWarning] = useState(false); + const [showBundleDetail, setShowBundleDetail] = useState(false); + const [inscriptionToShow, setInscriptionToShow] = useState(undefined); const { isLoading, data, @@ -376,8 +426,13 @@ function ConfirmBtcTransactionComponent({ return ( <> - {!isBtcSendBrowserTx && !isGalleryOpen && ( - + {!isBtcSendBrowserTx && !isGalleryOpen && } + {inscriptionToShow && ( + setInscriptionToShow(undefined)} + inscription={inscriptionToShow} + /> )} {showFeeWarning && ( @@ -388,7 +443,7 @@ function ConfirmBtcTransactionComponent({ )} {children} - + {t('CONFIRM_TRANSACTION.REVIEW_TRANSACTION')} @@ -401,10 +456,48 @@ function ConfirmBtcTransactionComponent({ )} + {selectedSatBundle && ( + + setShowBundleDetail((prevState) => !prevState)} + > + + bundle + + {t('RARE_SATS.SATS_BUNDLE')} + + + + {`${selectedSatBundle.satributes.length} Rare Sats`} + + + + + {showBundleDetail && + selectedSatBundle.satRanges.map((item: BundleSatRange, index: number) => ( + + { + // show ordinal modal to show asset + setInscriptionToShow(inscription); + }} + showDivider={index !== selectedSatBundle.satRanges.length - 1} + /> + + ))} + + )} + {ordinalTxUtxo ? ( ({ @@ -210,29 +207,31 @@ function RecipientComponent({ )} {heading && {heading}} - - {renderIcon()} - {title} - {currencyType === 'NFT' || currencyType === 'Ordinal' || currencyType === 'RareSat' ? ( - - {value} - {valueDetail && {valueDetail}} - - ) : ( - - {amount}} - /> - {getFiatAmountString(new BigNumber(fiatAmount!))} - - )} - + {value && ( + + {renderIcon()} + {title} + {currencyType === 'NFT' || currencyType === 'Ordinal' || currencyType === 'RareSat' ? ( + + {value} + {valueDetail && {valueDetail}} + + ) : ( + + {amount}} + /> + {getFiatAmountString(new BigNumber(fiatAmount!))} + + )} + + )} {address && ( - +
{showSenderAddress ? ( @@ -242,7 +241,7 @@ function RecipientComponent({ ) : ( )} - +
)}
); diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 4c77769bb..079fe5884 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -1,6 +1,5 @@ import { ConfirmOrdinalsTransactionState, LedgerTransactionType } from '@common/types/ledger'; import AccountHeaderComponent from '@components/accountHeader'; -import BundleAsset from '@components/bundleAsset/bundleAsset'; import ConfirmBtcTransactionComponent from '@components/confirmBtcTransactionComponent'; import BottomBar from '@components/tabBar'; import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; @@ -15,7 +14,6 @@ import OrdinalImage from '@screens/ordinals/ordinalImage'; import { BtcTransactionBroadcastResponse } from '@secretkeylabs/xverse-core/types'; import { useMutation } from '@tanstack/react-query'; import { isLedgerAccount } from '@utils/helper'; -import { getBundleId, getBundleSubText } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -82,9 +80,6 @@ function ConfirmOrdinalTransaction() { const [currentFee, setCurrentFee] = useState(fee); const [currentFeeRate, setCurrentFeeRate] = useState(feePerVByte); - const bundleId = isRareSat && selectedSatBundle ? getBundleId(selectedSatBundle) : ''; - const bundleSubText = isRareSat && selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; - const { isLoading, error: txError, @@ -186,8 +181,7 @@ function ConfirmOrdinalTransaction() { onCancelClick={handleOnCancelClick} onBackButtonClick={handleOnCancelClick} ordinalTxUtxo={ordinalUtxo} - assetDetail={bundleSubText ?? selectedOrdinal?.number.toString()} - assetDetailValue={bundleId ?? ''} + assetDetail={selectedOrdinal ? selectedOrdinal.number.toString() : ''} currentFee={currentFee} setCurrentFee={setCurrentFee} currentFeeRate={currentFeeRate} @@ -195,15 +189,13 @@ function ConfirmOrdinalTransaction() { currencyType={isRareSat ? 'RareSat' : 'Ordinal'} isPartOfBundle={isPartOfABundle} > - - - {selectedSatBundle && isRareSat ? ( - - ) : ( + {selectedOrdinal && ( + + - )} - - + + + )}
{!isGalleryOpen && ( diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx index 58084010b..275e2c4f8 100644 --- a/src/app/screens/sendRareSat/index.tsx +++ b/src/app/screens/sendRareSat/index.tsx @@ -1,14 +1,13 @@ import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import AccountHeaderComponent from '@components/accountHeader'; -import BundleAsset from '@components/bundleAsset/bundleAsset'; import SendForm from '@components/sendForm'; import BottomBar from '@components/tabBar'; import TopRow from '@components/topRow'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import useWalletSelector from '@hooks/useWalletSelector'; import useSeedVault from '@hooks/useSeedVault'; +import useWalletSelector from '@hooks/useWalletSelector'; import { getBtcFiatEquivalent } from '@secretkeylabs/xverse-core/currency'; import { SignedBtcTx, @@ -17,9 +16,8 @@ import { import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { useMutation } from '@tanstack/react-query'; -import { StyledHeading, StyledP } from '@ui-library/common.styled'; +import { StyledHeading } from '@ui-library/common.styled'; import { isLedgerAccount } from '@utils/helper'; -import { getBundleId, getBundleSubText } from '@utils/rareSats'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -37,14 +35,6 @@ const ScrollContainer = styled.div` margin: auto; `; -const Container = styled.div({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - flex: 1, -}); - const BottomBarContainer = styled.div({ marginTop: 'auto', }); @@ -81,17 +71,10 @@ const ButtonImage = styled.img((props) => ({ transform: 'all', })); -const BundleAssetContainer = styled.div((props) => ({ - maxHeight: 148, - width: 148, - display: 'flex', - aspectRatio: 1, - justifyContent: 'center', - alignItems: 'center', - borderRadius: 8, - marginTop: props.theme.spacing(8), - marginBottom: props.theme.spacing(6), -})); +const Heading = styled(StyledHeading)` + margin-top: ${(props) => props.theme.space.m}; + margin-left: ${(props) => props.theme.space.m}; +`; function SendOrdinal() { const { t } = useTranslation('translation'); @@ -206,9 +189,6 @@ function SendOrdinal() { setWarning(''); }; - const heading = selectedSatBundle ? getBundleSubText(selectedSatBundle) : ''; - const subText = selectedSatBundle ? getBundleId(selectedSatBundle) : ''; - return ( <> {isGalleryOpen && ( @@ -227,7 +207,8 @@ function SendOrdinal() { )} - {!isGalleryOpen && } + {!isGalleryOpen && } + {t('SEND.SEND_TO')} - - - - - - {heading} - - - {subText} - - - + /> {!isGalleryOpen && } diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 73f984764..21c7e3e90 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -376,3 +376,21 @@ export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): Bund totalExoticSats, }; }; + +export const getSatLabel = (satributes: RareSatsType[]): string => { + const isLengthGrateThanTwo = satributes.length > 2; + if (satributes.length === 1) { + return `${getRareSatsLabelByType(satributes[0])}`; + } + + // we expect to roadarmor sats be in the first position + if (RoadArmorRareSats.includes(satributes[0] as RoadArmorRareSatsType)) { + return `${getRareSatsLabelByType(satributes[0])} ${t( + isLengthGrateThanTwo ? 'COMMON.COMBO' : `RARE_SATS.RARITY_LABEL.${satributes[1]}`, + )}`; + } + + return isLengthGrateThanTwo + ? `${t('COMMON.COMBO')}` + : `${getRareSatsLabelByType(satributes[0])} ${getRareSatsLabelByType(satributes[1])}`; +}; diff --git a/src/assets/img/rareSats/satBundle.svg b/src/assets/img/rareSats/satBundle.svg new file mode 100644 index 000000000..e9941a7cb --- /dev/null +++ b/src/assets/img/rareSats/satBundle.svg @@ -0,0 +1,5 @@ + + + + + From 00303999b814399bfa67cd1461978ba0516ce1ef Mon Sep 17 00:00:00 2001 From: fede erbes Date: Fri, 24 Nov 2023 14:47:48 +0100 Subject: [PATCH 14/28] feat: add v2 of useGetUtxoOrdinalBundle and use it in ordinal detail screen (#59) * feat: tweak rare sats bundle screen to support new satributes * feat: add v2 of useGetUtxoOrdinalBundle and use it in ordinal detail screen * feat: add sattributes to ordinal details screen (#60) * chore: remove glow from RareSatIcon component * feat: add sattributes to ordinal details screen --------- Co-authored-by: Abdul Haseeb --------- Co-authored-by: Abdul Haseeb --- .../components/rareSatAsset/rareSatAsset.tsx | 3 +- .../components/rareSatIcon/rareSatIcon.tsx | 45 +---- .../ordinals/tempAddressRareSatsMock.ts | 67 ++++++++ .../queries/ordinals/useAddressRareSats.ts | 83 ++++++++- .../nftDashboard/rareSatsTabGridItem.tsx | 59 +++---- .../supportedRarities/rarityTile.tsx | 2 +- src/app/screens/ordinalDetail/index.tsx | 159 ++++++++++++------ .../screens/ordinalDetail/useOrdinalDetail.ts | 8 +- src/app/utils/rareSats.ts | 56 +++--- src/locales/en.json | 3 +- 10 files changed, 329 insertions(+), 156 deletions(-) diff --git a/src/app/components/rareSatAsset/rareSatAsset.tsx b/src/app/components/rareSatAsset/rareSatAsset.tsx index 62e05b485..16cccda59 100644 --- a/src/app/components/rareSatAsset/rareSatAsset.tsx +++ b/src/app/components/rareSatAsset/rareSatAsset.tsx @@ -62,7 +62,6 @@ function RareSatAsset({ item, isCollage = false }: Props) { size={isGallery ? 40 : 24} padding={isGallery ? 8 : 4} bgColor="elevation0" - glow={false} /> )} @@ -75,7 +74,7 @@ function RareSatAsset({ item, isCollage = false }: Props) { ) : ( - + )} diff --git a/src/app/components/rareSatIcon/rareSatIcon.tsx b/src/app/components/rareSatIcon/rareSatIcon.tsx index 1dba9b2e8..8a4c25b13 100644 --- a/src/app/components/rareSatIcon/rareSatIcon.tsx +++ b/src/app/components/rareSatIcon/rareSatIcon.tsx @@ -26,7 +26,7 @@ import SequencePali from '@assets/img/nftDashboard/rareSats/sequence_pali.svg'; import Uncommon from '@assets/img/nftDashboard/rareSats/uncommon.svg'; import Unknown from '@assets/img/nftDashboard/rareSats/unknown.svg'; import Vintage from '@assets/img/nftDashboard/rareSats/vintage.svg'; -import { getRareSatsColorsByRareSatsType, RareSatsType } from '@utils/rareSats'; +import { RareSatsType } from '@utils/rareSats'; import styled from 'styled-components'; import Theme from '../../../theme'; @@ -49,28 +49,6 @@ const Image = styled.img` height: 100%; zindex: 2; `; -type GlowProps = { - color: string; - outerColor: string; - isCollage: boolean; - isGallery: boolean; -}; -const Glow = styled.div((props) => { - const boxShadow = { - 'extension-collage': `0 0 calc(5vw) calc(1.5vw) ${props.color}`, - 'extension-one-item': `0 0 calc(12vw) calc(2vw) ${props.color}`, - 'gallery-collage': `0 0 calc(3.5vw) calc(0.8vw) ${props.color}`, - 'gallery-one-item': `0 0 calc(7vw) calc(1.5vw) ${props.color}`, - }[`${props.isGallery ? 'gallery' : 'extension'}-${props.isCollage ? 'collage' : 'one-item'}`]; - return { - position: 'absolute', - zIndex: 1, - width: '10%', - height: '10%', - borderRadius: '100%', - boxShadow, - }; -}); interface Props { type: RareSatsType; @@ -78,20 +56,9 @@ interface Props { bgColor?: keyof (typeof Theme)['colors']['background']; padding?: number; isDynamicSize?: boolean; - isCollage?: boolean; - glow?: boolean; } -function RareSatIcon({ - type, - size = 24, - bgColor, - padding = 0, - isDynamicSize = false, - isCollage = false, - glow = true, -}: Props) { - const isGallery: boolean = document.documentElement.clientWidth > 360; +function RareSatIcon({ type, size = 24, bgColor, padding = 0, isDynamicSize = false }: Props) { const src = { EPIC: Epic, LEGENDARY: Legendary, @@ -128,17 +95,9 @@ function RareSatIcon({ return null; } const backgroundColor = bgColor ? Theme.colors.background[bgColor] : 'transparent'; - const { color, backgroundColor: outerColor } = getRareSatsColorsByRareSatsType(type) ?? { - color: 'transparent', - backgroundColor: 'transparent', - }; - return ( - {glow && type !== 'UNKNOWN' && ( - - )} {type} diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts index 83670d08a..b637a23f6 100644 --- a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts +++ b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts @@ -8,6 +8,71 @@ export type Response = { results: ApiBundleV2[]; }; +export const inscriptionPartOfBundle: ApiBundleV2 & { xVersion: number } = { + block_height: 803128, + txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', + value: 100, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 10, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000001', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 11, + offset: 1, + range: { + start: '34234320000003', + end: '34234320000004', + }, + satributes: [], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067474, + }, + ], + }, + ], + xVersion: 1, +}; + +export const exoticInscriptionNotPartOfBundle: ApiBundleV2 & { xVersion: number } = { + block_height: 803128, + txid: 'b143d94bb084eb429c3d3d4e8ebc9ee7b6a070a3b9b1a92849fe4059f8c2da09', + value: 1, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 10, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000001', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], + inscriptions: [ + { + content_type: 'text/html', + id: 'b143d94bb084eb429c3d3d4e8ebc9ee7b6a070a3b9b1a92849fe4059f8c2da09i0', + inscription_number: 32218693, + }, + ], + }, + ], + xVersion: 1, +}; + export const mockData: Response = { xVersion: 1, limit: 30, @@ -85,6 +150,7 @@ export const mockTestCase1: Response = { }; // TestCase 2 - 3 bundles +const { xVersion, ...bundle } = inscriptionPartOfBundle; export const mockTestCase3: Response = { xVersion: 1, limit: 30, @@ -282,6 +348,7 @@ export const mockTestCase3: Response = { }, ], }, + bundle, { block_height: 803128, txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d2', diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 126248408..56abc5c38 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -7,9 +7,20 @@ import { import { XVERSE_API_BASE_URL } from '@secretkeylabs/xverse-core/constant'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; import { handleRetries, InvalidParamsError } from '@utils/query'; -import { mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { + ApiBundleV2, + mapRareSatsAPIResponseToRareSats, + mapRareSatsAPIResponseToRareSatsV2, +} from '@utils/rareSats'; import axios from 'axios'; -import { mockData, mockTestCase1, mockTestCase3, Response } from './tempAddressRareSatsMock'; +import { + exoticInscriptionNotPartOfBundle, + inscriptionPartOfBundle, + mockData, + mockTestCase1, + mockTestCase3, + Response, +} from './tempAddressRareSatsMock'; const PAGE_SIZE = 30; @@ -140,6 +151,74 @@ export const useAddressRareSats = () => { }); }; +export const getUtxoOrdinalBundleV2 = async ( + network: NetworkType, + txid: string, + vout: number, +): Promise => { + const response = await axios.get( + `${XVERSE_API_BASE_URL(network)}/v2/ordinal-utxo/${txid}:${vout}`, + ); + return response.data; +}; + +export const useGetUtxoOrdinalBundleV2 = ( + output?: string, + shouldMakeTheCall?: boolean, + ordinalNumber?: number, +) => { + const { network } = useWalletSelector(); + const getUtxoOrdinalBundleByOutput = async () => { + if (!output) { + throw new InvalidParamsError('output is required'); + } + + const customOrdinalAddress = localStorage.getItem('ordinalAddress'); + const useProdApi = localStorage.getItem('useProdApi'); + if (!(useProdApi || customOrdinalAddress)) { + if (output === `${inscriptionPartOfBundle.txid}:${inscriptionPartOfBundle.vout}`) { + return inscriptionPartOfBundle; + } + + if ( + output === + `${exoticInscriptionNotPartOfBundle.txid}:${exoticInscriptionNotPartOfBundle.vout}` + ) { + return exoticInscriptionNotPartOfBundle; + } + } + + const [txid, vout] = output.split(':'); + const bundleResponse = await getUtxoOrdinalBundleV2(network.type, txid, parseInt(vout, 10)); + return bundleResponse; + }; + + const { data, isLoading } = useQuery({ + enabled: !!(output && shouldMakeTheCall), + queryKey: ['rare-sats', output], + queryFn: getUtxoOrdinalBundleByOutput, + retry: handleRetries, + staleTime: 1 * 60 * 1000, // 1 min + }); + + const bundle = data?.txid ? mapRareSatsAPIResponseToRareSatsV2(data) : undefined; + const inscriptionRange = bundle?.satRanges.find((range) => + range.inscriptions.some((inscription) => inscription.inscription_number === ordinalNumber), + ); + const ordinalSatributes = + inscriptionRange?.satributes.filter((satribute) => satribute !== 'UNKNOWN') ?? []; + const exoticRangesCount = (bundle?.satributes.filter((range) => !range.includes('UNKNOWN')) ?? []) + .length; + const isPartOfABundle = exoticRangesCount > ordinalSatributes.length; + + return { + bundle, + isPartOfABundle, + ordinalSatributes, + isLoading, + }; +}; + export const useGetUtxoOrdinalBundle = (output?: string, shouldMakeTheCall?: boolean) => { const { network } = useWalletSelector(); const getUtxoOrdinalBundleByOutput = async () => { diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx index 81ac6fa62..e15132389 100644 --- a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -43,39 +43,40 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: const renderedIcons = () => { let totalIconsDisplayed = 0; let totalTilesDisplayed = 0; + return bundle.satributes + .filter((satributes) => !(satributes.includes('UNKNOWN') && bundle.satributes.length > 1)) + .map((sats, index) => { + if (totalIconsDisplayed > maxItems) { + return null; + } - return bundle.satributes.map((sats, index) => { - if (totalIconsDisplayed > maxItems) { - return null; - } - - if (totalIconsDisplayed >= maxItems - 1) { - totalIconsDisplayed += 1; + if (totalIconsDisplayed >= maxItems - 1) { + totalIconsDisplayed += 1; + return ( + + + +{bundle.satributes.length - totalTilesDisplayed} + + + ); + } + totalTilesDisplayed += 1; return ( - - - +{bundle.satributes.length - totalTilesDisplayed} - + + {sats.map((sattribute, indexSattributes) => { + totalIconsDisplayed += 1; + if (totalIconsDisplayed >= maxItems - 1) { + return null; + } + // eslint-disable-next-line react/no-array-index-key + return ; + })} + {totalIconsDisplayed > maxItems - 2 ? ( + + ) : null} ); - } - totalTilesDisplayed += 1; - return ( - - {sats.map((sattribute, indexSattributes) => { - totalIconsDisplayed += 1; - if (totalIconsDisplayed >= maxItems - 1) { - return null; - } - // eslint-disable-next-line react/no-array-index-key - return ; - })} - {totalIconsDisplayed > maxItems - 2 ? ( - - ) : null} - - ); - }); + }); }; const bundleId = getFormattedTxIdVoutFromBundle(bundle); diff --git a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx index bc7e2c2df..a62697f9d 100644 --- a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx @@ -39,7 +39,7 @@ function RarityTile({ type }: Props) { return ( - + {getRareSatsLabelByType(type)} {t(`RARITY_DETAIL.${type.toUpperCase()}`)} diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index 53a5279f8..c7263af91 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -5,14 +5,18 @@ import AlertMessage from '@components/alertMessage'; import { BetterBarLoader } from '@components/barLoader'; import ActionButton from '@components/button'; import CollectibleDetailTile from '@components/collectibleDetailTile'; +import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; import Separator from '@components/separator'; import SquareButton from '@components/squareButton'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; import WebGalleryButton from '@components/webGalleryButton'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import { ArrowRight, ArrowUp, CubeTransparent, Share } from '@phosphor-icons/react'; +import { ArrowUp, Share } from '@phosphor-icons/react'; import OrdinalImage from '@screens/ordinals/ordinalImage'; +import Callout from '@ui-library/callout'; +import { StyledP } from '@ui-library/common.styled'; +import { getRareSatsColorsByRareSatsType, getRareSatsLabelByType } from '@utils/rareSats'; import { useTranslation } from 'react-i18next'; import { Tooltip } from 'react-tooltip'; import styled from 'styled-components'; @@ -89,8 +93,8 @@ const ExtensionOrdinalsContainer = styled.div((props) => ({ justifyContent: 'center', alignItems: 'center', borderRadius: props.theme.radius(1), - marginBottom: props.theme.spacing(12), marginTop: props.theme.spacing(12), + marginBottom: props.theme.space.m, })); const OrdinalTitleText = styled.h1((props) => ({ @@ -109,7 +113,6 @@ const DescriptionText = styled.h1((props) => ({ ...props.theme.typography.headline_l, color: props.theme.colors.white_0, fontSize: 24, - marginBottom: props.theme.spacing(8), })); const NftOwnedByText = styled.h1((props) => ({ @@ -164,7 +167,7 @@ const MintLimitContainer = styled.div((props) => ({ marginLeft: props.theme.spacing(30), })); -const DescriptionContainer = styled.h1((props) => ({ +const DescriptionContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'column', marginBottom: props.theme.spacing(30), @@ -270,40 +273,6 @@ const Text = styled.h1((props) => ({ marginLeft: props.theme.spacing(2), })); -const RareSatsBundleContainer = styled.div((props) => ({ - display: 'flex', - flex: 1, - flexDirection: 'row', - padding: props.theme.spacing(8), - marginBottom: props.theme.spacing(8), - border: `1px solid ${props.theme.colors.white_800}`, - borderRadius: '12px', -})); -const CubeTransparentIcon = styled(CubeTransparent)((props) => ({ - color: props.theme.colors.white_200, - marginRight: props.theme.spacing(8), -})); -const RareSatsBundleTextDescription = styled.div((props) => ({ - ...props.theme.typography.body_m, - color: props.theme.colors.white_200, -})); -const BundleLinkContainer = styled.button((props) => ({ - display: 'inline-flex', - flexDirection: 'row', - alignItems: 'center', - marginTop: props.theme.spacing(4), - backgroundColor: 'transparent', - color: props.theme.colors.white_0, - transition: 'background-color 0.2s ease, opacity 0.2s ease', - ':hover': { - color: props.theme.colors.white_200, - }, -})); -const BundleLinkText = styled.div((props) => ({ - ...props.theme.typography.body_medium_m, - marginRight: props.theme.spacing(1), -})); - const GalleryButtonContainer = styled.div` width: 190px; border-radius: 12px; @@ -314,9 +283,12 @@ const RowButtonContainer = styled.div((props) => ({ flexDirection: 'row', justifyContent: 'center', columnGap: props.theme.spacing(11), - paddingBottom: props.theme.spacing(16), - marginBottom: props.theme.spacing(4), - marginTop: props.theme.spacing(4), + marginBottom: props.theme.space.l, + marginTop: props.theme.space.m, + width: '100%', +})); + +const Divider = styled.div((props) => ({ width: '100%', borderBottom: `1px solid ${props.theme.colors.elevation3}`, })); @@ -379,8 +351,49 @@ const InfoContainer = styled.div((props) => ({ padding: `0 ${props.theme.spacing(8)}px`, })); +const RareSatsBundleCallout = styled(Callout)((props) => ({ + width: props.isGallery ? 400 : '100%', + marginBottom: props.isGallery ? 0 : props.theme.space.l, + marginTop: props.isGallery ? props.theme.space.xs : 0, +})); + +const SatributesIconsContainer = styled.div((props) => ({ + display: 'inline-flex', + flexDirection: 'row', + marginTop: props.isGallery ? props.theme.space.m : 0, +})); + +const SatributesBadgeContainer = styled.div((props) => ({ + marginTop: props.isGallery ? 0 : props.theme.space.m, +})); +const SatributesBadges = styled.div((props) => ({ + display: 'inline-flex', + flexDirection: 'row', + flexWrap: 'wrap', + maxWidth: props.isGallery ? 400 : '100%', + marginTop: props.theme.space.s, +})); +const Badge = styled.div<{ backgroundColor?: string; isLastItem: boolean }>((props) => ({ + display: 'inline-flex', + flexDirection: 'row', + alignItems: 'center', + backgroundColor: props.backgroundColor, + padding: `${props.theme.space.s} ${props.theme.space.s}`, + borderRadius: props.theme.radius(2), + border: `1px solid ${props.theme.colors.elevation3}`, + marginRight: props.isLastItem ? 0 : props.theme.space.xs, + marginBottom: props.theme.space.xs, +})); +const SatributeBadgeLabel = styled(StyledP)` + margin-left: ${(props) => props.theme.space.xs}; +`; +const DataItemsContainer = styled.div` + margin-top: ${(props) => props.theme.space.l}; +`; + function OrdinalDetailScreen() { const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); + const { t: commonT } = useTranslation('translation', { keyPrefix: 'COMMON' }); const ordinalDetails = useOrdinalDetail(); const { ordinal, @@ -390,6 +403,7 @@ function OrdinalDetailScreen() { showSendOridnalsAlert, isBrc20Ordinal, isPartOfABundle, + ordinalSatributes, isGalleryOpen, brc20InscriptionStatus, brc20InscriptionStatusColor, @@ -573,18 +587,48 @@ function OrdinalDetailScreen() { }; const rareSats = isPartOfABundle && ( - - -
- - {t('RARE_SATS_BUNDLE_DESCRIPTION')} - - - {t('RARE_SATS_BUNDLE_LINK')} - - -
-
+ + ); + + const showSatributes = ordinalSatributes.length > 0; + const satributesIcons = showSatributes && ( + + {ordinalSatributes.map((satribute) => ( + + ))} + + ); + const stributesBadges = showSatributes && ( + + + {commonT('SATTRIBUTES')} + + + {ordinalSatributes.map((satribute, index) => { + const { backgroundColor } = getRareSatsColorsByRareSatsType(satribute) ?? { + color: 'transparent', + backgroundColor: 'transparent', + }; + return ( + = ordinalSatributes.length} + > + + + {getRareSatsLabelByType(satribute)} + + + ); + })} + + ); const extensionView = isLoading ? ( @@ -627,6 +671,7 @@ function OrdinalDetailScreen() { + {satributesIcons} } @@ -649,6 +694,8 @@ function OrdinalDetailScreen() { /> {rareSats} + + {stributesBadges} {isBrc20Ordinal ? showBrc20OrdinalDetail(false) : ordinalDetailAttributes} {t('VIEW_IN')} @@ -714,6 +761,7 @@ function OrdinalDetailScreen() { : ordinal?.collection_name || t('INSCRIPTION')} {ordinal?.number} + {satributesIcons} {t('OWNED_BY')} {`${ordinalsAddress.substring( @@ -752,7 +800,10 @@ function OrdinalDetailScreen() { {t('DATA')} {rareSats} - {isBrc20Ordinal ? showBrc20OrdinalDetail(true) : ordinalDetailAttributes} + + {stributesBadges} + {isBrc20Ordinal ? showBrc20OrdinalDetail(true) : ordinalDetailAttributes} + {t('VIEW_IN')} {t('ORDINAL_VIEWER')} diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts index 7704e5b78..a98b78775 100644 --- a/src/app/screens/ordinalDetail/useOrdinalDetail.ts +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -1,4 +1,4 @@ -import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; +import { useGetUtxoOrdinalBundleV2 } from '@hooks/queries/ordinals/useAddressRareSats'; import useInscriptionCollectionMarketData from '@hooks/queries/ordinals/useCollectionMarketData'; import useAddressInscription from '@hooks/queries/ordinals/useInscription'; import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; @@ -33,9 +33,10 @@ export default function useOrdinalDetail() { const { isPending, pendingTxHash } = usePendingOrdinalTxs(ordinalData?.tx_id); const textContent = useTextOrdinalContent(ordinalData!); const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); - const { bundle, isPartOfABundle } = useGetUtxoOrdinalBundle( + const { bundle, isPartOfABundle, ordinalSatributes } = useGetUtxoOrdinalBundleV2( ordinalData?.output, hasActivatedRareSatsKey, + ordinalData?.number, ); const theme = useTheme(); const { t } = useTranslation('translation', { keyPrefix: 'NFT_DETAIL_SCREEN' }); @@ -128,7 +129,8 @@ export default function useOrdinalDetail() { ordinalsAddress, showSendOridnalsAlert, isBrc20Ordinal, - isPartOfABundle, + isPartOfABundle: isPartOfABundle && hasActivatedRareSatsKey, + ordinalSatributes: hasActivatedRareSatsKey ? ordinalSatributes : [], isGalleryOpen, brc20InscriptionStatus, brc20InscriptionStatusColor, diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 21c7e3e90..736438b86 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -76,37 +76,39 @@ export const getRarityLabelByRareSatsType = (rareSatsType: RareSatsType) => common: '--', }[rareSatsType]); -export const getRareSatsColorsByRareSatsType = (rareSatsType: RareSatsType) => - ({ - unknown: { +export const getRareSatsColorsByRareSatsType = (rareSatsType: RareSatsType) => { + const colors: Partial> = { + UNKNOWN: { color: 'rgb(175,186,189)', backgroundColor: 'rgba(175,186,189,0.20)', }, - uncommon: { + UNCOMMON: { color: 'rgb(215, 105, 254)', backgroundColor: 'rgba(215, 105, 254, 0.20)', }, - rare: { + RARE: { color: 'rgb(131, 113, 242)', backgroundColor: 'rgba(131, 113, 242, 0.20)', }, - epic: { + EPIC: { color: 'rgb(145, 226, 96)', backgroundColor: 'rgba(145, 226, 96, 0.20)', }, - legendary: { + LEGENDARY: { color: 'rgb(255,205,120)', backgroundColor: 'rgba(255,205,120,0.20)', }, - mythic: { + MYTHIC: { color: 'rgb(255,244,203)', backgroundColor: 'rgba(255,244,203, 0.20)', }, - common: { + COMMON: { color: 'rgb(216,216,216)', backgroundColor: 'rgba(216,216,216,0.20)', }, - }[rareSatsType ?? 'common']); + }; + return colors[rareSatsType]; +}; type SatInscription = { id: string; @@ -346,28 +348,40 @@ export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): Bund ...satRangeProps, totalSats: Number(BigInt(satRange.range.end) - BigInt(satRange.range.start)), yearMined: year_mined, + // we want to common/unknown inscriptions to be shown as a additional row from common/unknown row + satributes: + !satRange.satributes.length && satRange.inscriptions.length + ? (['UNKNOWN'] as RareSatsType[]) + : satRange.satributes, }; }); - // we map this previous to a possible push of a common unknown range cause we don't need to show the icon rare sats tab. We only show it if the bundle is fully common/unknown + // if totalExotics doesn't match the value of the bundle, it means that the bundle is not fully exotic and we need to add a common unknown sat range more + let totalExoticSats = 0; + let totalCommonUnknownInscribedSats = 0; + satRanges.forEach((satRange) => { + if (satRange.satributes.includes('UNKNOWN')) { + totalCommonUnknownInscribedSats += satRange.totalSats; + } else { + totalExoticSats += satRange.totalSats; + } + }); + if (totalExoticSats !== apiBundle.value) { + satRanges.push({ + ...commonUnknownRange, + totalSats: apiBundle.value - (totalExoticSats + totalCommonUnknownInscribedSats), + }); + } + const inscriptions = satRanges.reduce( (acc, curr) => [...acc, ...curr.inscriptions], - [] as BundleV2['satRanges'][0]['inscriptions'], + [] as Inscription[], ); const satributes = satRanges.reduce( (acc, curr) => [...acc, curr.satributes], [] as RareSatsType[][], ); - // if totalExotics doesn't match the value of the bundle, it means that the bundle is not fully exotic and we need to add a common unknown sat range more - const totalExoticSats = satRanges.reduce((acc, curr) => acc + curr.totalSats, 0); - if (totalExoticSats !== apiBundle.value) { - satRanges.push({ - ...commonUnknownRange, - totalSats: apiBundle.value - totalExoticSats, - }); - } - return { ...generalBundleInfo, satRanges, diff --git a/src/locales/en.json b/src/locales/en.json index fc3679718..a9deaff7f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -3,7 +3,8 @@ "INSCRIPTION": "Inscription", "SEND": "Send", "COMBO": "Combo", - "SATS": "Sats" + "SATS": "Sats", + "SATTRIBUTES": "Sattributes" }, "LANDING_SCREEN": { "SCREEN_TITLE": "Wallet for Stacks & Bitcoin", From 568430a4bc00fd18c87c4cfcad7e6a749272a6b3 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Fri, 24 Nov 2023 20:18:17 +0500 Subject: [PATCH 15/28] feat: send inscriptions that belong to a rare sat (#64) * feat: tweak rare sats bundle screen to support new satributes * feat: add v2 of useGetUtxoOrdinalBundle and use it in ordinal detail screen * feat: ordinal bundle in confirm screen * fix: add missing ordinal number --------- Co-authored-by: fede erbes --- .../confirmBtcTransactionComponent/index.tsx | 19 +++++++++++-------- .../confirmOrdinalTransaction/index.tsx | 8 +++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index a4abce6fc..5e07116e7 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -31,7 +31,7 @@ import { useMutation } from '@tanstack/react-query'; import Callout from '@ui-library/callout'; import { StyledP } from '@ui-library/common.styled'; import { CurrencyTypes } from '@utils/constants'; -import { BundleSatRange, Inscription } from '@utils/rareSats'; +import { BundleSatRange, BundleV2, Inscription } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -180,6 +180,7 @@ interface Props { isBtcSendBrowserTx?: boolean; currencyType?: CurrencyTypes; isPartOfBundle?: boolean; + ordinalBundle?: BundleV2; currentFeeRate: BigNumber; setCurrentFee: (feeRate: BigNumber) => void; setCurrentFeeRate: (feeRate: BigNumber) => void; @@ -203,6 +204,7 @@ function ConfirmBtcTransactionComponent({ isBtcSendBrowserTx, isPartOfBundle, currencyType, + ordinalBundle, currentFeeRate, setCurrentFee, setCurrentFeeRate, @@ -223,6 +225,8 @@ function ConfirmBtcTransactionComponent({ const [showFeeWarning, setShowFeeWarning] = useState(false); const [showBundleDetail, setShowBundleDetail] = useState(false); const [inscriptionToShow, setInscriptionToShow] = useState(undefined); + + const bundle = selectedSatBundle ?? ordinalBundle ?? undefined; const { isLoading, data, @@ -456,7 +460,7 @@ function ConfirmBtcTransactionComponent({ )} - {selectedSatBundle && ( + {bundle && ( - {`${selectedSatBundle.satributes.length} Rare Sats`} + {`${ + bundle.satributes.length + } ${t('NFT_DASHBOARD_SCREEN.RARE_SATS')}`} {showBundleDetail && - selectedSatBundle.satRanges.map((item: BundleSatRange, index: number) => ( + bundle.satRanges.map((item: BundleSatRange, index: number) => ( ))} diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 079fe5884..205724ba3 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -2,7 +2,7 @@ import { ConfirmOrdinalsTransactionState, LedgerTransactionType } from '@common/ import AccountHeaderComponent from '@components/accountHeader'; import ConfirmBtcTransactionComponent from '@components/confirmBtcTransactionComponent'; import BottomBar from '@components/tabBar'; -import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; +import { useGetUtxoOrdinalBundleV2 } from '@hooks/queries/ordinals/useAddressRareSats'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; @@ -73,7 +73,7 @@ function ConfirmOrdinalTransaction() { fee = BigNumber(fee); } - const { selectedOrdinal, selectedSatBundle } = useNftDataSelector(); + const { selectedOrdinal } = useNftDataSelector(); const { setSelectedOrdinalDetails } = useOrdinalDataReducer(); const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); const { refetch } = useBtcWalletData(); @@ -127,9 +127,10 @@ function ConfirmOrdinalTransaction() { } }, [txError]); - const { isPartOfABundle } = useGetUtxoOrdinalBundle( + const { bundle: ordinalBundle, isPartOfABundle } = useGetUtxoOrdinalBundleV2( selectedOrdinal?.output, hasActivatedRareSatsKey, + selectedOrdinal?.number, ); const handleOnConfirmClick = (txHex: string) => { @@ -188,6 +189,7 @@ function ConfirmOrdinalTransaction() { setCurrentFeeRate={setCurrentFeeRate} currencyType={isRareSat ? 'RareSat' : 'Ordinal'} isPartOfBundle={isPartOfABundle} + ordinalBundle={ordinalBundle} > {selectedOrdinal && ( From 54995359fbbf2b7a05e6a3c34608e1ddce01faaa Mon Sep 17 00:00:00 2001 From: fede erbes Date: Mon, 27 Nov 2023 09:19:25 +0100 Subject: [PATCH 16/28] feat: add sat bundle layout to sign psbt screen (#65) * chore: move bundle from ConfirmBtcTransactionComponent to it own component * chore: use getSatLabel from utils in RareSatsBundleGridItem * feat: tweak useDetectOrdinalInSignPsbt hook to use V2 of rare sats api and implement sats bundle component in SignPsbtRequest screen --- .../confirmBtcTransactionComponent/bundle.tsx | 108 +++++++++ .../confirmBtcTransactionComponent/index.tsx | 94 +------- .../components/recipientComponent/index.tsx | 2 +- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 35 +-- .../rareSatsBundle/rareSatsBundleGridItem.tsx | 29 +-- .../signPsbtRequest/bundleItemsComponent.tsx | 219 ------------------ src/app/screens/signPsbtRequest/index.tsx | 29 ++- src/locales/en.json | 3 +- 8 files changed, 154 insertions(+), 365 deletions(-) create mode 100644 src/app/components/confirmBtcTransactionComponent/bundle.tsx delete mode 100644 src/app/screens/signPsbtRequest/bundleItemsComponent.tsx diff --git a/src/app/components/confirmBtcTransactionComponent/bundle.tsx b/src/app/components/confirmBtcTransactionComponent/bundle.tsx new file mode 100644 index 000000000..f0f864c3d --- /dev/null +++ b/src/app/components/confirmBtcTransactionComponent/bundle.tsx @@ -0,0 +1,108 @@ +import BundleIcon from '@assets/img/rareSats/satBundle.svg'; +import AssetModal from '@components/assetModal'; +import { CaretDown } from '@phosphor-icons/react'; +import { StyledP } from '@ui-library/common.styled'; +import { BundleSatRange, BundleV2, Inscription } from '@utils/rareSats'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; +import Theme from 'theme'; +import { BundleItem } from './bundleItem'; + +interface BundleItemContainerProps { + addMargin: boolean; +} + +const BundleItemsContainer = styled.div` + margin-top: ${(props) => (props.addMargin ? props.theme.space.m : 0)}; +`; + +const SatsBundleContainer = styled.div` + display: flex; + flex-direction: column; + margin-bottom: ${(props) => props.theme.space.s}; + border-radius: ${(props) => props.theme.space.s}; + padding: ${(props) => props.theme.space.m}; + background-color: ${(props) => props.theme.colors.elevation1}; +`; + +const SatsBundleButton = styled.button` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background-color: ${(props) => props.theme.colors.elevation1}; +`; + +const Row = styled.div` + display: flex; + flex-direction: row; + align-items: center; +`; + +const BundleTitle = styled(StyledP)` + margin-left: ${(props) => props.theme.space.s}; +`; + +const BundleValue = styled(StyledP)` + margin-right: ${(props) => props.theme.space.xs}; +`; + +const Title = styled(StyledP)((props) => ({ + marginBottom: props.theme.space.xs, +})); + +function SatsBundle({ bundle, title }: { bundle: BundleV2; title?: string }) { + const [showBundleDetail, setShowBundleDetail] = useState(false); + const [inscriptionToShow, setInscriptionToShow] = useState(undefined); + + const { t } = useTranslation('translation'); + + return ( + <> + {inscriptionToShow && ( + setInscriptionToShow(undefined)} + inscription={inscriptionToShow} + /> + )} + + {title && {title}} + setShowBundleDetail((prevState) => !prevState)} + > + + bundle + + {t('RARE_SATS.SATS_BUNDLE')} + + + + {`${bundle.totalExoticSats} ${t( + 'NFT_DASHBOARD_SCREEN.RARE_SATS', + )}`} + + + + + {showBundleDetail && + bundle.satRanges.map((item: BundleSatRange, index: number) => ( + + { + // show ordinal modal to show asset + setInscriptionToShow(inscription); + }} + showDivider={index !== bundle.satRanges.length - 1} + /> + + ))} + + + ); +} + +export default SatsBundle; diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 5e07116e7..84e40e7ae 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -1,7 +1,5 @@ import SettingIcon from '@assets/img/dashboard/faders_horizontal.svg'; -import BundleIcon from '@assets/img/rareSats/satBundle.svg'; import AssetIcon from '@assets/img/transactions/Assets.svg'; -import AssetModal from '@components/assetModal'; import ActionButton from '@components/button'; import InfoContainer from '@components/infoContainer'; import RecipientComponent from '@components/recipientComponent'; @@ -12,7 +10,6 @@ import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; -import { CaretDown } from '@phosphor-icons/react'; import { ErrorCodes, getBtcFiatEquivalent, @@ -29,17 +26,15 @@ import { } from '@secretkeylabs/xverse-core/transactions/btc'; import { useMutation } from '@tanstack/react-query'; import Callout from '@ui-library/callout'; -import { StyledP } from '@ui-library/common.styled'; import { CurrencyTypes } from '@utils/constants'; -import { BundleSatRange, BundleV2, Inscription } from '@utils/rareSats'; +import { BundleV2 } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; -import Theme from 'theme'; import TransactionDetailComponent from '../transactionDetailComponent'; -import { BundleItem } from './bundleItem'; +import SatsBundle from './bundle'; const OuterContainer = styled.div` display: flex; @@ -63,10 +58,6 @@ interface ButtonProps { isBtcSendBrowserTx?: boolean; } -interface BundleItemContainerProps { - addMargin: boolean; -} - const ButtonContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', @@ -115,10 +106,6 @@ const ErrorText = styled.h1((props) => ({ color: props.theme.colors.danger_medium, })); -const BundleItemsContainer = styled.div` - margin-top: ${(props) => (props.addMargin ? Theme.space.m : 0)}; -`; - interface ReviewTransactionTitleProps { centerAligned: boolean; } @@ -134,37 +121,6 @@ const CalloutContainer = styled.div((props) => ({ marginhorizontal: props.theme.spacing(8), })); -const SatsBundle = styled.button` - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - background-color: ${(props) => props.theme.colors.elevation1}; -`; - -const SatsBundleContainer = styled.div` - display: flex; - flex-direction: column; - margin-bottom: ${(props) => props.theme.space.s}; - border-radius: ${(props) => props.theme.space.s}; - padding: ${(props) => props.theme.space.m}; - background-color: ${(props) => props.theme.colors.elevation1}; -`; - -const Row = styled.div` - display: flex; - flex-direction: row; - align-items: center; -`; - -const BundleTitle = styled(StyledP)` - margin-left: ${(props) => props.theme.space.s}; -`; - -const BundleValue = styled(StyledP)` - margin-right: ${(props) => props.theme.space.xs}; -`; - interface Props { currentFee: BigNumber; feePerVByte: BigNumber; // TODO tim: is this the same as currentFeeRate? refactor to be clear @@ -223,8 +179,6 @@ function ConfirmBtcTransactionComponent({ const [signedTx, setSignedTx] = useState(signedTxHex); const [total, setTotal] = useState(new BigNumber(0)); const [showFeeWarning, setShowFeeWarning] = useState(false); - const [showBundleDetail, setShowBundleDetail] = useState(false); - const [inscriptionToShow, setInscriptionToShow] = useState(undefined); const bundle = selectedSatBundle ?? ordinalBundle ?? undefined; const { @@ -431,13 +385,6 @@ function ConfirmBtcTransactionComponent({ <> {!isBtcSendBrowserTx && !isGalleryOpen && } - {inscriptionToShow && ( - setInscriptionToShow(undefined)} - inscription={inscriptionToShow} - /> - )} {showFeeWarning && ( )} - {bundle && ( - - setShowBundleDetail((prevState) => !prevState)} - > - - bundle - - {t('RARE_SATS.SATS_BUNDLE')} - - - - {`${ - bundle.satributes.length - } ${t('NFT_DASHBOARD_SCREEN.RARE_SATS')}`} - - - - - {showBundleDetail && - bundle.satRanges.map((item: BundleSatRange, index: number) => ( - - { - // show ordinal modal to show asset - setInscriptionToShow(inscription); - }} - showDivider={index !== bundle.satRanges.length - 1} - /> - - ))} - - )} + {bundle && } {ordinalTxUtxo ? ( ({ const RecipientTitleText = styled.p((props) => ({ ...props.theme.body_medium_m, color: props.theme.colors.white_200, - marginBottom: 16, + marginBottom: props.theme.space.xs, })); const RowContainer = styled.div({ diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index 36fe692b7..fa0a59a8e 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -1,32 +1,37 @@ -import { getUtxoOrdinalBundle, ParsedPSBT } from '@secretkeylabs/xverse-core'; -import { BundleItem, mapRareSatsAPIResponseToRareSats } from '@utils/rareSats'; +import { ParsedPSBT } from '@secretkeylabs/xverse-core'; +import { BundleSatRange, BundleV2, mapRareSatsAPIResponseToRareSatsV2 } from '@utils/rareSats'; import { isAxiosError } from 'axios'; import { useEffect, useState } from 'react'; +import { getUtxoOrdinalBundleV2 } from './queries/ordinals/useAddressRareSats'; import useWalletSelector from './useWalletSelector'; +type InputsBundle = Pick; + const useDetectOrdinalInSignPsbt = (parsedPsbt: undefined | ParsedPSBT) => { const [loading, setLoading] = useState(false); const [userReceivesOrdinal, setUserReceivesOrdinal] = useState(false); - const [bundleItemsData, setBundleItemsData] = useState([]); + const [bundleItemsData, setBundleItemsData] = useState({ + value: 0, + satRanges: [], + totalExoticSats: 0, + }); const { ordinalsAddress, network } = useWalletSelector(); async function handleOrdinalAndOrdinalInfo() { - const bundleItems: BundleItem[] = []; + const satRanges: BundleSatRange[] = []; + let value = 0; + let totalExoticSats = 0; if (parsedPsbt) { setLoading(true); await Promise.all( parsedPsbt.inputs.map(async (input) => { try { - const data = await getUtxoOrdinalBundle(network.type, input.txid, input.index); - - const bundle = mapRareSatsAPIResponseToRareSats(data); - bundle.items.forEach((item) => { - // we don't show unknown items for now - if (item.type === 'unknown') { - return; - } - bundleItems.push(item); - }); + const data = await getUtxoOrdinalBundleV2(network.type, input.txid, input.index); + + const bundle = mapRareSatsAPIResponseToRareSatsV2(data); + satRanges.push(...bundle.satRanges); + value += bundle.value; + totalExoticSats += bundle.totalExoticSats; } catch (e) { // we get back a 404 if the UTXO is not found, so it is likely this is a UTXO from an unpublished txn if (!isAxiosError(e) || e.response?.status !== 404) { @@ -37,7 +42,7 @@ const useDetectOrdinalInSignPsbt = (parsedPsbt: undefined | ParsedPSBT) => { }), ); - setBundleItemsData(bundleItems); + setBundleItemsData({ value, satRanges, totalExoticSats }); setLoading(false); parsedPsbt.outputs.forEach(async (output) => { diff --git a/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx index 91ea7c8a9..e4fcc4f37 100644 --- a/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx +++ b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx @@ -1,13 +1,6 @@ import ExoticSatsRow from '@components/exoticSatsRow/exoticSatsRow'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -import { - BundleSatRange, - getRareSatsLabelByType, - RareSatsType, - RoadArmorRareSats, - RoadArmorRareSatsType, -} from '@utils/rareSats'; -import { useTranslation } from 'react-i18next'; +import { BundleSatRange, getSatLabel } from '@utils/rareSats'; import styled from 'styled-components'; const RangeContainer = styled.div` @@ -30,26 +23,6 @@ const Container = styled.div((props) => ({ })); export function RareSatsBundleGridItem({ item }: { item: BundleSatRange }) { - const { t } = useTranslation('translation'); - - const getSatLabel = (satributes: RareSatsType[]) => { - const isLengthGrateThanTwo = satributes.length > 2; - if (satributes.length === 1) { - return getRareSatsLabelByType(satributes[0]); - } - - // we expect to roadarmor sats be in the first position - if (RoadArmorRareSats.includes(satributes[0] as RoadArmorRareSatsType)) { - return `${getRareSatsLabelByType(satributes[0])} ${t( - isLengthGrateThanTwo ? 'COMMON.COMBO' : `RARE_SATS.RARITY_LABEL.${satributes[1]}`, - )}`; - } - - return isLengthGrateThanTwo - ? t('COMMON.COMBO') - : `${getRareSatsLabelByType(satributes[0])} ${getRareSatsLabelByType(satributes[1])}`; - }; - return ( ({ - display: 'flex', - flexDirection: 'column', - background: props.theme.colors.elevation1, - borderRadius: 12, - padding: '16px 16px', - justifyContent: 'center', - marginBottom: 12, -})); - -const RecipientTitleText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white_200, - marginBottom: 10, -})); - -const RowContainer = styled.div({ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', -}); - -const TransparentButton = styled.button({ - background: 'transparent', - display: 'flex', - alignItems: 'center', - marginLeft: 10, -}); - -const Icon = styled.img((props) => ({ - marginRight: props.theme.spacing(4), - width: 32, - height: 32, - borderRadius: 30, -})); - -const TitleText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white_200, -})); - -const ValueText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white_0, -})); - -const SubValueText = styled.h1((props) => ({ - ...props.theme.body_m, - fontSize: 12, - color: props.theme.colors.white_400, -})); - -const InscriptionText = styled.h1((props) => ({ - ...props.theme.body_medium_m, - fontSize: 21, - marginTop: 24, - textAlign: 'center', - color: props.theme.colors.white[0], - overflowWrap: 'break-word', - wordWrap: 'break-word', - wordBreak: 'break-word', -})); - -const ColumnContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - flex: 1, - justifyContent: 'flex-end', - alignItems: 'flex-end', - marginTop: 12, -}); - -const CrossContainer = styled.div({ - display: 'flex', - marginTop: 10, - justifyContent: 'flex-end', - alignItems: 'flex-end', -}); - -const OrdinalOuterImageContainer = styled.div({ - justifyContent: 'center', - alignItems: 'center', - borderRadius: 2, - display: 'flex', - flexDirection: 'column', - flex: 1, -}); - -const OrdinalImageContainer = styled.div({ - width: '50%', -}); - -const OrdinalBackgroundContainer = styled(animated.div)({ - width: '100%', - height: '100%', - top: 0, - left: 0, - bottom: 0, - right: 0, - position: 'fixed', - zIndex: 10, - background: 'rgba(18, 21, 30, 0.8)', - backdropFilter: 'blur(16px)', - padding: 16, - display: 'flex', - flexDirection: 'column', -}); - -const EyeIcon = styled.img({ - width: 20, - height: 20, -}); - -interface Props { - item: BundleItem; - userReceivesOrdinal: boolean; -} -function BundleItemsComponent({ item, userReceivesOrdinal }: Props) { - const { t } = useTranslation('translation'); - const [showOrdinal, setShowOrdinal] = useState(false); - const styles = useSpring({ - from: { - opacity: 0, - y: 24, - }, - to: { - y: 0, - opacity: 1, - }, - delay: 100, - }); - const onButtonClick = () => { - setShowOrdinal(true); - }; - - const onCrossClick = () => { - setShowOrdinal(false); - }; - const getItemId = () => { - if (item.type === 'inscription') { - return item.inscription.id; - } - if (item.type === 'inscribed-sat' || item.type === 'rare-sat') { - return item.number; - } - return ''; - }; - const itemSubText = getBundleItemSubText({ - satType: item.type, - rareSatsType: item.rarity_ranking, - }); - const getDetail = () => { - if (item.type === 'inscription' || item.type === 'inscribed-sat') { - return item.inscription.content_type; - } - return itemSubText; - }; - const getTitle = () => { - if (item.type === 'inscription') { - return t('COMMON.INSCRIPTION'); - } - if (item.type === 'inscribed-sat') { - return t('RARE_SATS.INSCRIBED_SAT'); - } - return t('RARE_SATS.RARE_SAT'); - }; - return ( - <> - {showOrdinal && ( - - - - cross - - - - - - - {`${getTitle()} ${getItemId()} `} - - - )} - - - {userReceivesOrdinal - ? t('CONFIRM_TRANSACTION.YOU_WILL_RECEIVE') - : t('CONFIRM_TRANSACTION.YOU_WILL_TRANSFER')} - - - - {getTitle()} - - - {getTruncatedAddress(String(getItemId()))} - - - - - {getDetail()} - - - - - ); -} - -export default BundleItemsComponent; diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index f85e8297f..201ba64c9 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -5,6 +5,7 @@ import { ledgerDelay } from '@common/utils/ledger'; import AccountHeaderComponent from '@components/accountHeader'; import BottomModal from '@components/bottomModal'; import ActionButton from '@components/button'; +import SatsBundle from '@components/confirmBtcTransactionComponent/bundle'; import InputOutputComponent from '@components/confirmBtcTransactionComponent/inputOutputComponent'; import InfoContainer from '@components/infoContainer'; import LedgerConnectionView from '@components/ledger/connectLedgerView'; @@ -19,6 +20,7 @@ import { getBtcFiatEquivalent, satsToBtc, signLedgerPSBT } from '@secretkeylabs/ import { Transport as TransportType } from '@secretkeylabs/xverse-core/ledger/types'; import { parsePsbt, psbtBase64ToHex } from '@secretkeylabs/xverse-core/transactions/psbt'; import { isLedgerAccount } from '@utils/helper'; +import { BundleV2 } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { decodeToken } from 'jsontokens'; import { useEffect, useMemo, useState } from 'react'; @@ -28,7 +30,6 @@ import { useLocation, useNavigate } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; import { SignTransactionOptions } from 'sats-connect'; import styled from 'styled-components'; -import BundleItemsComponent from './bundleItemsComponent'; const OuterContainer = styled.div` display: flex; @@ -105,6 +106,9 @@ function SignPsbtRequest() { const { t: signatureRequestTranslate } = useTranslation('translation', { keyPrefix: 'SIGNATURE_REQUEST', }); + const { t: rareSatsTranslate } = useTranslation('translation', { + keyPrefix: 'RARE_SATS', + }); const [expandInputOutputView, setExpandInputOutputView] = useState(false); const { payload, confirmSignPsbt, cancelSignPsbt, getSigningAddresses } = useSignPsbtTx(); const [isSigning, setIsSigning] = useState(false); @@ -352,15 +356,12 @@ function SignPsbtRequest() { {t('REVIEW_TRANSACTION')} {!payload.broadcast && } - {bundleItemsData && - bundleItemsData.map((bundleItem, index) => ( - - ))} + {bundleItemsData && ( + + )} + {payload.broadcast ? ( Date: Mon, 27 Nov 2023 17:34:09 +0500 Subject: [PATCH 17/28] feat: show callout if ordinal holds a rare sat (#66) --- .../components/confirmBtcTransactionComponent/index.tsx | 7 +++++++ src/app/screens/confirmOrdinalTransaction/index.tsx | 9 ++++++++- src/locales/en.json | 3 ++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 84e40e7ae..a9c55ec23 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -137,6 +137,7 @@ interface Props { currencyType?: CurrencyTypes; isPartOfBundle?: boolean; ordinalBundle?: BundleV2; + holdsRareSats?: boolean; currentFeeRate: BigNumber; setCurrentFee: (feeRate: BigNumber) => void; setCurrentFeeRate: (feeRate: BigNumber) => void; @@ -161,6 +162,7 @@ function ConfirmBtcTransactionComponent({ isPartOfBundle, currencyType, ordinalBundle, + holdsRareSats, currentFeeRate, setCurrentFee, setCurrentFeeRate, @@ -406,6 +408,11 @@ function ConfirmBtcTransactionComponent({ /> )} + {holdsRareSats && ( + + + + )} {bundle && } diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 205724ba3..5f5a373ea 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -127,12 +127,18 @@ function ConfirmOrdinalTransaction() { } }, [txError]); - const { bundle: ordinalBundle, isPartOfABundle } = useGetUtxoOrdinalBundleV2( + const { + bundle: ordinalBundle, + isPartOfABundle, + ordinalSatributes, + } = useGetUtxoOrdinalBundleV2( selectedOrdinal?.output, hasActivatedRareSatsKey, selectedOrdinal?.number, ); + const holdsRareSats = ordinalSatributes?.length > 0; + const handleOnConfirmClick = (txHex: string) => { if (isLedgerAccount(selectedAccount)) { const txType: LedgerTransactionType = 'ORDINALS'; @@ -190,6 +196,7 @@ function ConfirmOrdinalTransaction() { currencyType={isRareSat ? 'RareSat' : 'Ordinal'} isPartOfBundle={isPartOfABundle} ordinalBundle={ordinalBundle} + holdsRareSats={!!holdsRareSats} > {selectedOrdinal && ( diff --git a/src/locales/en.json b/src/locales/en.json index fb744c45e..31e565c08 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -579,7 +579,8 @@ "RARE_SATS_NOTICE_TITLE": "Don't see your rare sat?", "RARE_SATS_NOTICE_DETAIL": "Currently, Xverse only supports the Rodarmor rarity index. Your sats may have other attributes.", "SEE_SUPPORTED": "See supported rarity scale", - "FROM_RARE_SAT_BUNDLE": "This inscription belongs to the same bundle as other assets. Transferring it will involve transferring the full bundle." + "FROM_RARE_SAT_BUNDLE": "This inscription belongs to the same bundle as other assets. Transferring it will involve transferring the full bundle.", + "HOLDS_RARE_SAT": "This inscription holds a rare sat." }, "RESTORE_FUND_SCREEN": { "TITLE": "Restore assets", From af58f153bdb78cfbc409ba9519bc33d629e1caa3 Mon Sep 17 00:00:00 2001 From: fede erbes Date: Tue, 28 Nov 2023 09:50:56 +0100 Subject: [PATCH 18/28] chore: move methods and utils to core, remove v2 suffix and clean up code (#67) * chore: remove unknown type and unify it with common * fix: go back navigation when navigating from inscription to bundle screen * chore: move methods and utils to core, remove v2 suffix and clean up code --- package-lock.json | 124 +---- package.json | 2 +- src/app/components/assetModal/index.tsx | 8 +- .../components/bundleAsset/bundleAsset.tsx | 42 -- .../collectibleCollage/collectibleCollage.tsx | 16 +- .../confirmBtcTransactionComponent/bundle.tsx | 13 +- .../bundleItem.tsx | 12 +- .../confirmBtcTransactionComponent/index.tsx | 4 +- .../exoticSatsRow/exoticSatsRow.tsx | 4 +- .../components/rareSatAsset/rareSatAsset.tsx | 85 ---- .../components/rareSatIcon/rareSatIcon.tsx | 5 +- .../ordinals/tempAddressRareSatsMock.ts | 24 +- .../queries/ordinals/useAddressRareSats.ts | 131 +----- src/app/hooks/useDetectOrdinalInSignPsbt.ts | 16 +- .../confirmOrdinalTransaction/index.tsx | 4 +- .../screens/nftDashboard/collectiblesTabs.tsx | 10 +- .../nftDashboard/inscriptionsTabGridItem.tsx | 10 +- .../nftDashboard/rareSatsTabGridItem.tsx | 9 +- .../nftDashboard/supportedRarities/index.tsx | 4 +- .../supportedRarities/rarityTile.tsx | 3 +- .../screens/nftDashboard/useNftDashboard.tsx | 6 +- src/app/screens/ordinalDetail/index.tsx | 5 +- .../screens/ordinalDetail/useOrdinalDetail.ts | 7 +- src/app/screens/rareSatsBundle/index.tsx | 14 +- .../rareSatsBundle/rareSatsBundleGridItem.tsx | 3 +- .../screens/rareSatsDetail/rareSatsDetail.tsx | 440 +----------------- src/app/screens/signPsbtRequest/index.tsx | 10 +- src/app/stores/nftData/actions/types.ts | 5 +- src/app/utils/inscriptions.ts | 10 - src/app/utils/rareSats.test.ts | 186 -------- src/app/utils/rareSats.ts | 395 +--------------- src/locales/en.json | 5 +- 32 files changed, 133 insertions(+), 1479 deletions(-) delete mode 100644 src/app/components/bundleAsset/bundleAsset.tsx delete mode 100644 src/app/components/rareSatAsset/rareSatAsset.tsx delete mode 100644 src/app/utils/rareSats.test.ts diff --git a/package-lock.json b/package-lock.json index 736fcde5f..de2fc7cdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "3.0.0", + "@secretkeylabs/xverse-core": "3.1.1-e148aa5", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", @@ -3408,9 +3408,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "3.0.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.0.0/90bd130bc7b3f9c0739e65d34772d6a550b5818d", - "integrity": "sha512-dtPkHY+VSNf/iwta3cSO2ZsKxdURTM4E+FPCwrotXc85MfxO0MIjyRa4VlOCtHsj8fNS2yH+KHg3uClLK9+WiQ==", + "version": "3.1.1-e148aa5", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.1.1-e148aa5/052344a16abd8ca22ae92643c209ac586c004241", + "integrity": "sha512-J52vNGjglWUQ8PHV5t/bPBFDs5bSXBzaPFHVe6KlFs90BFsAFsD9gdGMB0M9wGJgPFNQc820XZne11YJGbmllw==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -3664,15 +3664,6 @@ "@scure/base": "~1.1.0" } }, - "node_modules/@stacks/auth/node_modules/@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, "node_modules/@stacks/auth/node_modules/@stacks/encryption": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", @@ -3689,15 +3680,6 @@ "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@stacks/auth/node_modules/@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "dependencies": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } - }, "node_modules/@stacks/common": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", @@ -3920,7 +3902,6 @@ "version": "6.8.1", "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "peer": true, "dependencies": { "@stacks/common": "^6.8.1", "cross-fetch": "^3.1.5" @@ -3958,24 +3939,6 @@ } ] }, - "node_modules/@stacks/profile/node_modules/@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "node_modules/@stacks/profile/node_modules/@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "dependencies": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } - }, "node_modules/@stacks/profile/node_modules/@stacks/transactions": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", @@ -4033,15 +3996,6 @@ "@scure/base": "~1.1.0" } }, - "node_modules/@stacks/storage/node_modules/@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, "node_modules/@stacks/storage/node_modules/@stacks/encryption": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", @@ -4058,15 +4012,6 @@ "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@stacks/storage/node_modules/@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "dependencies": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } - }, "node_modules/@stacks/transactions": { "version": "4.3.8", "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-4.3.8.tgz", @@ -21501,9 +21446,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "3.0.0", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.0.0/90bd130bc7b3f9c0739e65d34772d6a550b5818d", - "integrity": "sha512-dtPkHY+VSNf/iwta3cSO2ZsKxdURTM4E+FPCwrotXc85MfxO0MIjyRa4VlOCtHsj8fNS2yH+KHg3uClLK9+WiQ==", + "version": "3.1.1-e148aa5", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.1.1-e148aa5/052344a16abd8ca22ae92643c209ac586c004241", + "integrity": "sha512-J52vNGjglWUQ8PHV5t/bPBFDs5bSXBzaPFHVe6KlFs90BFsAFsD9gdGMB0M9wGJgPFNQc820XZne11YJGbmllw==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", @@ -21721,15 +21666,6 @@ "@scure/base": "~1.1.0" } }, - "@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, "@stacks/encryption": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", @@ -21745,15 +21681,6 @@ "ripemd160-min": "^0.0.6", "varuint-bitcoin": "^1.1.2" } - }, - "@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "requires": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } } } }, @@ -21972,7 +21899,6 @@ "version": "6.8.1", "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "peer": true, "requires": { "@stacks/common": "^6.8.1", "cross-fetch": "^3.1.5" @@ -22004,24 +21930,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==" }, - "@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "requires": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } - }, "@stacks/transactions": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", @@ -22069,15 +21977,6 @@ "@scure/base": "~1.1.0" } }, - "@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, "@stacks/encryption": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", @@ -22093,15 +21992,6 @@ "ripemd160-min": "^0.0.6", "varuint-bitcoin": "^1.1.2" } - }, - "@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "requires": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" - } } } }, diff --git a/package.json b/package.json index 8dcc16c02..8eab65572 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "3.0.0", + "@secretkeylabs/xverse-core": "3.1.1-e148aa5", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", diff --git a/src/app/components/assetModal/index.tsx b/src/app/components/assetModal/index.tsx index a7ab49972..a0274acc9 100644 --- a/src/app/components/assetModal/index.tsx +++ b/src/app/components/assetModal/index.tsx @@ -1,8 +1,7 @@ import Cross from '@assets/img/dashboard/X.svg'; import { animated, useSpring } from '@react-spring/web'; import OrdinalImage from '@screens/ordinals/ordinalImage'; -import { CondensedInscription } from '@secretkeylabs/xverse-core/types'; -import { Inscription } from '@utils/rareSats'; +import { CondensedInscription, SatRangeInscription } from '@secretkeylabs/xverse-core'; import styled from 'styled-components'; const TransparentButton = styled.button({ @@ -49,12 +48,11 @@ const OrdinalBackgroundContainer = styled(animated.div)({ }); interface Props { - show: boolean; - inscription: Inscription; + inscription: SatRangeInscription; onClose: () => void; } -function AssetModal({ show, inscription, onClose }: Props) { +function AssetModal({ inscription, onClose }: Props) { const consdensedInscription: CondensedInscription = { ...inscription, number: inscription.inscription_number, diff --git a/src/app/components/bundleAsset/bundleAsset.tsx b/src/app/components/bundleAsset/bundleAsset.tsx deleted file mode 100644 index 284534cba..000000000 --- a/src/app/components/bundleAsset/bundleAsset.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; -import { Bundle } from '@utils/rareSats'; -import styled from 'styled-components'; - -import CollectibleCollage from '../collectibleCollage/collectibleCollage'; - -const ImageContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - aspect-ratio: 1; - overflow: hidden; - border-radius: ${(props) => props.theme.radius(1)}px; -`; - -const IndividualAssetContainer = styled.div` - display: flex; - width: 100%; - background: ${(props) => props.theme.colors.elevation1}; -`; - -interface Props { - bundle: Bundle; -} - -function BundleAsset({ bundle }: Props) { - const isMoreThanOneItem = bundle.items?.length > 1; - return ( - - {isMoreThanOneItem ? ( - - ) : ( - - - - )} - - ); -} - -export default BundleAsset; diff --git a/src/app/components/collectibleCollage/collectibleCollage.tsx b/src/app/components/collectibleCollage/collectibleCollage.tsx index e15ee56c5..c875cda75 100644 --- a/src/app/components/collectibleCollage/collectibleCollage.tsx +++ b/src/app/components/collectibleCollage/collectibleCollage.tsx @@ -1,7 +1,6 @@ -import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; import Nft from '@screens/nftDashboard/nft'; -import { NonFungibleToken } from '@secretkeylabs/xverse-core'; -import { BundleItem } from '@utils/rareSats'; +import OrdinalImage from '@screens/ordinals/ordinalImage'; +import { CondensedInscription, NonFungibleToken } from '@secretkeylabs/xverse-core'; import styled from 'styled-components'; const CollageContainer = styled.div` @@ -39,10 +38,11 @@ const RemainingAmountOfAssets = styled.div((props) => ({ }, })); -function CollectibleCollage({ items }: { items: Array }) { +function CollectibleCollage({ items }: { items: Array }) { const moreThanFourItems = items.length > 4; - const isBundleItem = (item: any): boolean => (item as BundleItem).rarity_ranking !== undefined; + const isStacksNft = (item: CondensedInscription | NonFungibleToken): boolean => + 'asset_identifier' in item; return ( {items.slice(0, 4).map((item, index) => ( @@ -53,10 +53,10 @@ function CollectibleCollage({ items }: { items: Array+{items.length - 4}

) : // Conditionally render RareSatAsset if item is a BundleItem otherwise render Nft - isBundleItem(item) ? ( - - ) : ( + isStacksNft(item) ? ( + ) : ( + )} ))} diff --git a/src/app/components/confirmBtcTransactionComponent/bundle.tsx b/src/app/components/confirmBtcTransactionComponent/bundle.tsx index f0f864c3d..84b728b71 100644 --- a/src/app/components/confirmBtcTransactionComponent/bundle.tsx +++ b/src/app/components/confirmBtcTransactionComponent/bundle.tsx @@ -1,13 +1,13 @@ import BundleIcon from '@assets/img/rareSats/satBundle.svg'; import AssetModal from '@components/assetModal'; import { CaretDown } from '@phosphor-icons/react'; +import { Bundle, BundleSatRange, SatRangeInscription } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; -import { BundleSatRange, BundleV2, Inscription } from '@utils/rareSats'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Theme from 'theme'; -import { BundleItem } from './bundleItem'; +import BundleItem from './bundleItem'; interface BundleItemContainerProps { addMargin: boolean; @@ -52,9 +52,11 @@ const Title = styled(StyledP)((props) => ({ marginBottom: props.theme.space.xs, })); -function SatsBundle({ bundle, title }: { bundle: BundleV2; title?: string }) { +function SatsBundle({ bundle, title }: { bundle: Bundle; title?: string }) { const [showBundleDetail, setShowBundleDetail] = useState(false); - const [inscriptionToShow, setInscriptionToShow] = useState(undefined); + const [inscriptionToShow, setInscriptionToShow] = useState( + undefined, + ); const { t } = useTranslation('translation'); @@ -62,7 +64,6 @@ function SatsBundle({ bundle, title }: { bundle: BundleV2; title?: string }) { <> {inscriptionToShow && ( setInscriptionToShow(undefined)} inscription={inscriptionToShow} /> @@ -92,7 +93,7 @@ function SatsBundle({ bundle, title }: { bundle: BundleV2; title?: string }) { { + ordinalEyePressed={(inscription: SatRangeInscription) => { // show ordinal modal to show asset setInscriptionToShow(inscription); }} diff --git a/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx index cb3281fec..18cc33db3 100644 --- a/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx +++ b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx @@ -1,9 +1,9 @@ import OrdinalIcon from '@assets/img/rareSats/ic_ordinal_small.svg'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; import { DotsThree, Eye } from '@phosphor-icons/react'; +import { BundleSatRange, SatRangeInscription } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; -import { BundleSatRange, getSatLabel, Inscription } from '@utils/rareSats'; -import { useTranslation } from 'react-i18next'; +import { getSatLabel } from '@utils/rareSats'; import { NumericFormat } from 'react-number-format'; import styled from 'styled-components'; import Theme from 'theme'; @@ -66,17 +66,15 @@ const BundleText = styled(StyledP)` width: 100%; `; -export function BundleItem({ +function BundleItem({ item, ordinalEyePressed, showDivider, }: { item: BundleSatRange; - ordinalEyePressed: (inscription: Inscription) => void; + ordinalEyePressed: (inscription: SatRangeInscription) => void; showDivider?: boolean; }) { - const { t } = useTranslation('translation'); - const renderedIcons = () => ( @@ -126,3 +124,5 @@ export function BundleItem({
); } + +export default BundleItem; diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index a9c55ec23..d6abee2c3 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -11,6 +11,7 @@ import useOrdinalsByAddress from '@hooks/useOrdinalsByAddress'; import useSeedVault from '@hooks/useSeedVault'; import useWalletSelector from '@hooks/useWalletSelector'; import { + Bundle, ErrorCodes, getBtcFiatEquivalent, ResponseError, @@ -27,7 +28,6 @@ import { import { useMutation } from '@tanstack/react-query'; import Callout from '@ui-library/callout'; import { CurrencyTypes } from '@utils/constants'; -import { BundleV2 } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { ReactNode, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -136,7 +136,7 @@ interface Props { isBtcSendBrowserTx?: boolean; currencyType?: CurrencyTypes; isPartOfBundle?: boolean; - ordinalBundle?: BundleV2; + ordinalBundle?: Bundle; holdsRareSats?: boolean; currentFeeRate: BigNumber; setCurrentFee: (feeRate: BigNumber) => void; diff --git a/src/app/components/exoticSatsRow/exoticSatsRow.tsx b/src/app/components/exoticSatsRow/exoticSatsRow.tsx index 2ba9b4740..838f98f7c 100644 --- a/src/app/components/exoticSatsRow/exoticSatsRow.tsx +++ b/src/app/components/exoticSatsRow/exoticSatsRow.tsx @@ -1,6 +1,6 @@ import OrdinalIcon from '@assets/img/rareSats/ic_ordinal_small.svg'; +import { SatRangeInscription } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; -import { Inscription } from '@utils/rareSats'; import { ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { NumericFormat } from 'react-number-format'; @@ -69,7 +69,7 @@ function ExoticSatsRow({ }: { title: string; satAmount: number; - inscriptions: Inscription[]; + inscriptions: SatRangeInscription[]; icons: ReactNode; }) { const { t } = useTranslation('translation', { keyPrefix: 'COMMON' }); diff --git a/src/app/components/rareSatAsset/rareSatAsset.tsx b/src/app/components/rareSatAsset/rareSatAsset.tsx deleted file mode 100644 index 16cccda59..000000000 --- a/src/app/components/rareSatAsset/rareSatAsset.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -import OrdinalImage from '@screens/ordinals/ordinalImage'; -import { Inscription } from '@secretkeylabs/xverse-core'; -import { BundleItem } from '@utils/rareSats'; -import styled from 'styled-components'; - -const Container = styled.div` - width: 100%; - height: 100%; -`; - -const InscriptionContainer = styled.div` - width: 100%; - height: 100%; - position: relative; - border-radius: 8px; - overflow: hidden; -`; - -const RareSatIconContainer = styled.div<{ isGallery: boolean }>((props) => ({ - display: 'flex', - position: 'absolute', - zIndex: 1, - left: props.isGallery ? 20 : 8, - top: props.isGallery ? 20 : 8, -})); - -const RareSatsContainer = styled.div((props) => ({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: '100%', - aspectRatio: '1', - overflow: 'hidden', - position: 'relative', - backgroundColor: props.theme.colors.elevation1, - borderRadius: 8, -})); - -const DynamicSizeContainer = styled.div<{ isCollage: boolean }>((props) => ({ - width: props.isCollage ? '40%' : '50%', - height: props.isCollage ? '40%' : '50%', -})); - -interface Props { - item: BundleItem; - isCollage?: boolean; -} - -function RareSatAsset({ item, isCollage = false }: Props) { - const isGallery: boolean = document.documentElement.clientWidth > 360; - const isInscription = item.type === 'inscription' || item.type === 'inscribed-sat'; - - return ( - - {isInscription ? ( - - {!isCollage && !!item.rarity_ranking && item.rarity_ranking !== 'COMMON' && ( - - - - )} - - - ) : ( - - - - - - )} - - ); -} - -export default RareSatAsset; diff --git a/src/app/components/rareSatIcon/rareSatIcon.tsx b/src/app/components/rareSatIcon/rareSatIcon.tsx index 8a4c25b13..39715b138 100644 --- a/src/app/components/rareSatIcon/rareSatIcon.tsx +++ b/src/app/components/rareSatIcon/rareSatIcon.tsx @@ -26,9 +26,8 @@ import SequencePali from '@assets/img/nftDashboard/rareSats/sequence_pali.svg'; import Uncommon from '@assets/img/nftDashboard/rareSats/uncommon.svg'; import Unknown from '@assets/img/nftDashboard/rareSats/unknown.svg'; import Vintage from '@assets/img/nftDashboard/rareSats/vintage.svg'; -import { RareSatsType } from '@utils/rareSats'; +import { RareSatsType } from '@secretkeylabs/xverse-core'; import styled from 'styled-components'; - import Theme from '../../../theme'; const Container = styled.div<{ bgColor: string; padding: number }>((props) => ({ @@ -65,7 +64,7 @@ function RareSatIcon({ type, size = 24, bgColor, padding = 0, isDynamicSize = fa MYTHIC: Mythic, RARE: Rare, UNCOMMON: Uncommon, - UNKNOWN: Unknown, + COMMON: Unknown, BLACK_LEGENDARY: BlackLegendary, BLACK_EPIC: BlackEpic, BLACK_RARE: BlackRare, diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts index b637a23f6..237e4a25f 100644 --- a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts +++ b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts @@ -1,14 +1,6 @@ -import { ApiBundleV2 } from '@utils/rareSats'; +import { AddressBundleResponse, UtxoBundleResponse } from '@secretkeylabs/xverse-core'; -export type Response = { - xVersion: number; - limit: number; - offset: number; - total: number; - results: ApiBundleV2[]; -}; - -export const inscriptionPartOfBundle: ApiBundleV2 & { xVersion: number } = { +export const inscriptionPartOfBundle: UtxoBundleResponse = { block_height: 803128, txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', value: 100, @@ -46,7 +38,7 @@ export const inscriptionPartOfBundle: ApiBundleV2 & { xVersion: number } = { xVersion: 1, }; -export const exoticInscriptionNotPartOfBundle: ApiBundleV2 & { xVersion: number } = { +export const exoticInscriptionNotPartOfBundle: UtxoBundleResponse = { block_height: 803128, txid: 'b143d94bb084eb429c3d3d4e8ebc9ee7b6a070a3b9b1a92849fe4059f8c2da09', value: 1, @@ -73,7 +65,7 @@ export const exoticInscriptionNotPartOfBundle: ApiBundleV2 & { xVersion: number xVersion: 1, }; -export const mockData: Response = { +export const mockData: AddressBundleResponse = { xVersion: 1, limit: 30, offset: 0, @@ -141,7 +133,7 @@ export const mockData: Response = { }; // TestCase 1 - Empty response -export const mockTestCase1: Response = { +export const mockTestCase1: AddressBundleResponse = { xVersion: 1, limit: 30, offset: 0, @@ -151,7 +143,7 @@ export const mockTestCase1: Response = { // TestCase 2 - 3 bundles const { xVersion, ...bundle } = inscriptionPartOfBundle; -export const mockTestCase3: Response = { +export const mockTestCase3: AddressBundleResponse = { xVersion: 1, limit: 30, offset: 0, @@ -238,7 +230,7 @@ export const mockTestCase3: Response = { offset: 10000, range: { start: '34234320010001', - end: '34234320010001', + end: '34234320010002', }, satributes: ['PIZZA'], inscriptions: [ @@ -296,7 +288,7 @@ export const mockTestCase3: Response = { offset: 3, range: { start: '34234320010001', - end: '34234320010001', + end: '34234320010002', }, satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], inscriptions: [ diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 56abc5c38..466605de2 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -2,64 +2,21 @@ import useWalletSelector from '@hooks/useWalletSelector'; import { getAddressUtxoOrdinalBundles, getUtxoOrdinalBundle, - NetworkType, + mapRareSatsAPIResponseToBundle, } from '@secretkeylabs/xverse-core'; -import { XVERSE_API_BASE_URL } from '@secretkeylabs/xverse-core/constant'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; import { handleRetries, InvalidParamsError } from '@utils/query'; -import { - ApiBundleV2, - mapRareSatsAPIResponseToRareSats, - mapRareSatsAPIResponseToRareSatsV2, -} from '@utils/rareSats'; -import axios from 'axios'; import { exoticInscriptionNotPartOfBundle, inscriptionPartOfBundle, mockData, mockTestCase1, mockTestCase3, - Response, } from './tempAddressRareSatsMock'; const PAGE_SIZE = 30; -// TODO: move this to xverse-core -export const getAddressUtxoOrdinalBundlesV2 = async ( - network: NetworkType, - address: string, - offset: number, - limit: number, - options?: { - /** Filter out unconfirmed UTXOs */ - hideUnconfirmed?: boolean; - /** Filter out UTXOs that only have one or more inscriptions (and no rare sats) */ - hideInscriptionOnly?: boolean; - }, -) => { - const params: Record = { - offset, - limit, - }; - - if (options?.hideUnconfirmed) { - params.hideUnconfirmed = 'true'; - } - if (options?.hideInscriptionOnly) { - params.hideInscriptionOnly = 'true'; - } - - const response = await axios.get( - `${XVERSE_API_BASE_URL(network)}/v2/address/${address}/ordinal-utxo`, - { - params, - }, - ); - - return response.data; -}; - -export const useAddressRareSatsV2 = () => { +export const useAddressRareSats = () => { const { ordinalsAddress, network } = useWalletSelector(); const getRareSatsByAddress = async ({ pageParam = 0 }) => { @@ -93,42 +50,9 @@ export const useAddressRareSatsV2 = () => { return mockData; } - const bundleResponse = await getAddressUtxoOrdinalBundlesV2( - network.type, - customOrdinalAddress ?? ordinalsAddress, - pageParam, - PAGE_SIZE, - { - hideUnconfirmed: true, - hideInscriptionOnly: true, - }, - ); - return bundleResponse; - }; - - return useInfiniteQuery(['rare-sats', ordinalsAddress], getRareSatsByAddress, { - retry: handleRetries, - getNextPageParam: (lastPage, allPages) => { - const currentLength = allPages.map((page) => page.results).flat().length; - if (currentLength < lastPage.total) { - return currentLength; - } - }, - staleTime: 1 * 60 * 1000, // 1 min - }); -}; - -export const useAddressRareSats = () => { - const { ordinalsAddress, network } = useWalletSelector(); - - const getRareSatsByAddress = async ({ pageParam = 0 }) => { - if (!ordinalsAddress) { - throw new InvalidParamsError('ordinalsAddress is required'); - } - const bundleResponse = await getAddressUtxoOrdinalBundles( network.type, - ordinalsAddress, + customOrdinalAddress ?? ordinalsAddress, pageParam, PAGE_SIZE, { @@ -151,18 +75,7 @@ export const useAddressRareSats = () => { }); }; -export const getUtxoOrdinalBundleV2 = async ( - network: NetworkType, - txid: string, - vout: number, -): Promise => { - const response = await axios.get( - `${XVERSE_API_BASE_URL(network)}/v2/ordinal-utxo/${txid}:${vout}`, - ); - return response.data; -}; - -export const useGetUtxoOrdinalBundleV2 = ( +export const useGetUtxoOrdinalBundle = ( output?: string, shouldMakeTheCall?: boolean, ordinalNumber?: number, @@ -189,7 +102,7 @@ export const useGetUtxoOrdinalBundleV2 = ( } const [txid, vout] = output.split(':'); - const bundleResponse = await getUtxoOrdinalBundleV2(network.type, txid, parseInt(vout, 10)); + const bundleResponse = await getUtxoOrdinalBundle(network.type, txid, parseInt(vout, 10)); return bundleResponse; }; @@ -201,13 +114,13 @@ export const useGetUtxoOrdinalBundleV2 = ( staleTime: 1 * 60 * 1000, // 1 min }); - const bundle = data?.txid ? mapRareSatsAPIResponseToRareSatsV2(data) : undefined; + const bundle = data?.txid ? mapRareSatsAPIResponseToBundle(data) : undefined; const inscriptionRange = bundle?.satRanges.find((range) => range.inscriptions.some((inscription) => inscription.inscription_number === ordinalNumber), ); const ordinalSatributes = - inscriptionRange?.satributes.filter((satribute) => satribute !== 'UNKNOWN') ?? []; - const exoticRangesCount = (bundle?.satributes.filter((range) => !range.includes('UNKNOWN')) ?? []) + inscriptionRange?.satributes.filter((satribute) => satribute !== 'COMMON') ?? []; + const exoticRangesCount = (bundle?.satributes.filter((range) => !range.includes('COMMON')) ?? []) .length; const isPartOfABundle = exoticRangesCount > ordinalSatributes.length; @@ -218,31 +131,3 @@ export const useGetUtxoOrdinalBundleV2 = ( isLoading, }; }; - -export const useGetUtxoOrdinalBundle = (output?: string, shouldMakeTheCall?: boolean) => { - const { network } = useWalletSelector(); - const getUtxoOrdinalBundleByOutput = async () => { - if (!output) { - throw new InvalidParamsError('output is required'); - } - - const [txid, vout] = output.split(':'); - const bundleResponse = await getUtxoOrdinalBundle(network.type, txid, parseInt(vout, 10)); - return bundleResponse; - }; - - const { data, isLoading } = useQuery({ - enabled: !!(output && shouldMakeTheCall), - queryKey: ['rare-sats', output, network.type], - queryFn: getUtxoOrdinalBundleByOutput, - retry: handleRetries, - staleTime: 1 * 60 * 1000, // 1 min - }); - const bundle = data?.txid ? mapRareSatsAPIResponseToRareSats(data) : undefined; - - return { - bundle, - isPartOfABundle: (bundle?.items ?? []).length > 1, - isLoading, - }; -}; diff --git a/src/app/hooks/useDetectOrdinalInSignPsbt.ts b/src/app/hooks/useDetectOrdinalInSignPsbt.ts index fa0a59a8e..c98eaf079 100644 --- a/src/app/hooks/useDetectOrdinalInSignPsbt.ts +++ b/src/app/hooks/useDetectOrdinalInSignPsbt.ts @@ -1,11 +1,15 @@ -import { ParsedPSBT } from '@secretkeylabs/xverse-core'; -import { BundleSatRange, BundleV2, mapRareSatsAPIResponseToRareSatsV2 } from '@utils/rareSats'; +import { + Bundle, + BundleSatRange, + getUtxoOrdinalBundle, + mapRareSatsAPIResponseToBundle, + ParsedPSBT, +} from '@secretkeylabs/xverse-core'; import { isAxiosError } from 'axios'; import { useEffect, useState } from 'react'; -import { getUtxoOrdinalBundleV2 } from './queries/ordinals/useAddressRareSats'; import useWalletSelector from './useWalletSelector'; -type InputsBundle = Pick; +type InputsBundle = Pick; const useDetectOrdinalInSignPsbt = (parsedPsbt: undefined | ParsedPSBT) => { const [loading, setLoading] = useState(false); @@ -26,9 +30,9 @@ const useDetectOrdinalInSignPsbt = (parsedPsbt: undefined | ParsedPSBT) => { await Promise.all( parsedPsbt.inputs.map(async (input) => { try { - const data = await getUtxoOrdinalBundleV2(network.type, input.txid, input.index); + const data = await getUtxoOrdinalBundle(network.type, input.txid, input.index); - const bundle = mapRareSatsAPIResponseToRareSatsV2(data); + const bundle = mapRareSatsAPIResponseToBundle(data); satRanges.push(...bundle.satRanges); value += bundle.value; totalExoticSats += bundle.totalExoticSats; diff --git a/src/app/screens/confirmOrdinalTransaction/index.tsx b/src/app/screens/confirmOrdinalTransaction/index.tsx index 5f5a373ea..9fc647be0 100644 --- a/src/app/screens/confirmOrdinalTransaction/index.tsx +++ b/src/app/screens/confirmOrdinalTransaction/index.tsx @@ -2,7 +2,7 @@ import { ConfirmOrdinalsTransactionState, LedgerTransactionType } from '@common/ import AccountHeaderComponent from '@components/accountHeader'; import ConfirmBtcTransactionComponent from '@components/confirmBtcTransactionComponent'; import BottomBar from '@components/tabBar'; -import { useGetUtxoOrdinalBundleV2 } from '@hooks/queries/ordinals/useAddressRareSats'; +import { useGetUtxoOrdinalBundle } from '@hooks/queries/ordinals/useAddressRareSats'; import useBtcWalletData from '@hooks/queries/useBtcWalletData'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useOrdinalDataReducer from '@hooks/stores/useOrdinalReducer'; @@ -131,7 +131,7 @@ function ConfirmOrdinalTransaction() { bundle: ordinalBundle, isPartOfABundle, ordinalSatributes, - } = useGetUtxoOrdinalBundleV2( + } = useGetUtxoOrdinalBundle( selectedOrdinal?.output, hasActivatedRareSatsKey, selectedOrdinal?.number, diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx index 80f81c289..9da473254 100644 --- a/src/app/screens/nftDashboard/collectiblesTabs.tsx +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -1,7 +1,11 @@ import ActionButton from '@components/button'; import WrenchErrorMessage from '@components/wrenchErrorMessage'; +import { + Bundle, + mapRareSatsAPIResponseToBundle, + UtxoOrdinalBundle, +} from '@secretkeylabs/xverse-core'; import { StyledP, StyledTab, StyledTabList } from '@ui-library/common.styled'; -import { ApiBundleV2, BundleV2, mapRareSatsAPIResponseToRareSatsV2 } from '@utils/rareSats'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useSearchParams } from 'react-router-dom'; @@ -242,8 +246,8 @@ export default function CollectiblesTabs({ rareSatsQuery.data?.pages ?.map((page) => page?.results) .flat() - .map((utxo: ApiBundleV2) => mapRareSatsAPIResponseToRareSatsV2(utxo)) - .map((bundle: BundleV2) => ( + .map((utxo: UtxoOrdinalBundle) => mapRareSatsAPIResponseToBundle(utxo)) + .map((bundle: Bundle) => ( ) : !isCollection(collection) || collection.thumbnail_inscriptions.length === 1 ? ( // eslint-disable-line no-nested-ternary - + ) : collection.category === 'brc-20' ? ( ) : ( - + )} diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx index e15132389..092b49c5f 100644 --- a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -2,8 +2,9 @@ import ExoticSatsRow from '@components/exoticSatsRow/exoticSatsRow'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { DotsThree } from '@phosphor-icons/react'; +import { Bundle } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; -import { BundleV2, getFormattedTxIdVoutFromBundle } from '@utils/rareSats'; +import { getFormattedTxIdVoutFromBundle } from '@utils/rareSats'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import Theme from 'theme'; @@ -30,12 +31,12 @@ const Pressable = styled.button((props) => ({ marginBottom: props.theme.space.s, })); -function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: number }) { +function RareSatsTabGridItem({ bundle, maxItems }: { bundle: Bundle; maxItems: number }) { const navigate = useNavigate(); const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); const handleOnClick = () => { - // exotics v1 wont show rage details only bundle details + // exotics v1 wont show range details only bundle details setSelectedSatBundleDetails(bundle); navigate('/nft-dashboard/rare-sats-bundle'); }; @@ -44,7 +45,7 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: BundleV2; maxItems: let totalIconsDisplayed = 0; let totalTilesDisplayed = 0; return bundle.satributes - .filter((satributes) => !(satributes.includes('UNKNOWN') && bundle.satributes.length > 1)) + .filter((satributes) => !(satributes.includes('COMMON') && bundle.satributes.length > 1)) .map((sats, index) => { if (totalIconsDisplayed > maxItems) { return null; diff --git a/src/app/screens/nftDashboard/supportedRarities/index.tsx b/src/app/screens/nftDashboard/supportedRarities/index.tsx index 8b429aecc..3bb81b2cb 100644 --- a/src/app/screens/nftDashboard/supportedRarities/index.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/index.tsx @@ -1,8 +1,8 @@ import TopRow from '@components/topRow'; import { ArrowUpRight } from '@phosphor-icons/react'; +import { RoadArmorRareSats, Sattributes } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; import { BLOG_LINK } from '@utils/constants'; -import { RareSats } from '@utils/rareSats'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; @@ -53,7 +53,7 @@ const MainContainer = styled.div({ backgroundColor: Theme.colors.elevation0, }); -const rarityTypes = RareSats.filter((rareSat) => rareSat !== 'common'); +const rarityTypes = [...RoadArmorRareSats, ...Sattributes]; function SupportedRarities() { const navigate = useNavigate(); diff --git a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx index a62697f9d..b54809b8a 100644 --- a/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/rarityTile.tsx @@ -1,5 +1,6 @@ import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -import { getRareSatsLabelByType, RareSatsType } from '@utils/rareSats'; +import { RareSatsType } from '@secretkeylabs/xverse-core'; +import { getRareSatsLabelByType } from '@utils/rareSats'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; diff --git a/src/app/screens/nftDashboard/useNftDashboard.tsx b/src/app/screens/nftDashboard/useNftDashboard.tsx index aed656aab..7476b8e84 100644 --- a/src/app/screens/nftDashboard/useNftDashboard.tsx +++ b/src/app/screens/nftDashboard/useNftDashboard.tsx @@ -1,6 +1,6 @@ import ActionButton from '@components/button'; import useAddressInscriptionCollections from '@hooks/queries/ordinals/useAddressInscriptionCollections'; -import { useAddressRareSatsV2 } from '@hooks/queries/ordinals/useAddressRareSats'; +import { useAddressRareSats } from '@hooks/queries/ordinals/useAddressRareSats'; import useStacksCollectibles from '@hooks/queries/useStacksCollectibles'; import useWalletSelector from '@hooks/useWalletSelector'; import { Wrench } from '@phosphor-icons/react'; @@ -76,7 +76,7 @@ export type NftDashboardState = { isOrdinalReceiveAlertVisible: boolean; stacksNftsQuery: ReturnType; inscriptionsQuery: ReturnType; - rareSatsQuery: ReturnType; + rareSatsQuery: ReturnType; openInGalleryView: () => void; onReceiveModalOpen: () => void; onReceiveModalClose: () => void; @@ -107,7 +107,7 @@ export const useNftDashboard = (): NftDashboardState => { const [isOrdinalReceiveAlertVisible, setIsOrdinalReceiveAlertVisible] = useState(false); const stacksNftsQuery = useStacksCollectibles(); const inscriptionsQuery = useAddressInscriptionCollections(); - const rareSatsQuery = useAddressRareSatsV2(); + const rareSatsQuery = useAddressRareSats(); const totalInscriptions = inscriptionsQuery.data?.pages?.[0]?.total_inscriptions ?? 0; const totalNfts = stacksNftsQuery.data?.total_nfts ?? 0; diff --git a/src/app/screens/ordinalDetail/index.tsx b/src/app/screens/ordinalDetail/index.tsx index c7263af91..13d056b27 100644 --- a/src/app/screens/ordinalDetail/index.tsx +++ b/src/app/screens/ordinalDetail/index.tsx @@ -610,10 +610,7 @@ function OrdinalDetailScreen() { {ordinalSatributes.map((satribute, index) => { - const { backgroundColor } = getRareSatsColorsByRareSatsType(satribute) ?? { - color: 'transparent', - backgroundColor: 'transparent', - }; + const backgroundColor = getRareSatsColorsByRareSatsType(satribute) ?? 'transparent'; return ( { - if (!bundle) { + if (!bundle || !ordinalData) { return; } + setSelectedOrdinalDetails(ordinalData); setSelectedSatBundleDetails(bundle); navigate('/nft-dashboard/rare-sats-bundle'); }; diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx index fff4692f5..9eb6eb796 100644 --- a/src/app/screens/rareSatsBundle/index.tsx +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -12,6 +12,7 @@ import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; import useWalletSelector from '@hooks/useWalletSelector'; import { ArrowRight, ArrowUp } from '@phosphor-icons/react'; +import { BundleSatRange } from '@secretkeylabs/xverse-core'; import { StyledHeading, StyledP } from '@ui-library/common.styled'; import { getBtcTxStatusUrl, @@ -19,7 +20,6 @@ import { isInOptions, isLedgerAccount, } from '@utils/helper'; -import { BundleSatRange } from '@utils/rareSats'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -162,7 +162,7 @@ function RareSatsBundle() { const { t } = useTranslation('translation'); const navigate = useNavigate(); const { network, selectedAccount, ordinalsAddress } = useWalletSelector(); - const { selectedSatBundle: bundle } = useNftDataSelector(); + const { selectedSatBundle: bundle, selectedOrdinal } = useNftDataSelector(); const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle?.txid); const [showSendOrdinalsAlert, setShowSendOrdinalsAlert] = useState(false); const { setSelectedSatBundleDetails } = useSatBundleDataReducer(); @@ -172,7 +172,7 @@ function RareSatsBundle() { useResetUserFlow('/rare-sats-bundle'); const handleBackButtonClick = () => { - navigate('/nft-dashboard?tab=rareSats'); + navigate(-1); setSelectedSatBundleDetails(null); }; @@ -213,6 +213,10 @@ function RareSatsBundle() { const isEmpty = !bundle?.satRanges?.length; + const goBackText = selectedOrdinal?.id + ? t('SEND.MOVE_TO_ASSET_DETAIL') + : t('NFT_DETAIL_SCREEN.MOVE_TO_ASSET_DETAIL'); + return ( <> {isGalleryOpen ? ( @@ -227,9 +231,7 @@ function RareSatsBundle() { diff --git a/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx index e4fcc4f37..881e06587 100644 --- a/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx +++ b/src/app/screens/rareSatsBundle/rareSatsBundleGridItem.tsx @@ -1,6 +1,7 @@ import ExoticSatsRow from '@components/exoticSatsRow/exoticSatsRow'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; -import { BundleSatRange, getSatLabel } from '@utils/rareSats'; +import { BundleSatRange } from '@secretkeylabs/xverse-core'; +import { getSatLabel } from '@utils/rareSats'; import styled from 'styled-components'; const RangeContainer = styled.div` diff --git a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx index b5bb2b9a0..c3ee17fec 100644 --- a/src/app/screens/rareSatsDetail/rareSatsDetail.tsx +++ b/src/app/screens/rareSatsDetail/rareSatsDetail.tsx @@ -1,42 +1,12 @@ -import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; import AccountHeaderComponent from '@components/accountHeader'; -import AlertMessage from '@components/alertMessage'; -import ActionButton from '@components/button'; -import RareSatAsset from '@components/rareSatAsset/rareSatAsset'; import BottomTabBar from '@components/tabBar'; import TopRow from '@components/topRow'; -import WebGalleryButton from '@components/webGalleryButton'; -import usePendingOrdinalTxs from '@hooks/queries/usePendingOrdinalTx'; -import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; -import useWalletSelector from '@hooks/useWalletSelector'; -import { ArrowRight, ArrowUp, Circle } from '@phosphor-icons/react'; -import Callout from '@ui-library/callout'; -import { XVERSE_ORDIVIEW_URL } from '@utils/constants'; -import { - getBtcTxStatusUrl, - getTruncatedAddress, - isInOptions, - isLedgerAccount, -} from '@utils/helper'; -import { - BundleItem, - getBundleItemId, - getBundleItemSubText, - getRareSatsColorsByRareSatsType, - getRareSatsLabelByType, - getRarityLabelByRareSatsType, -} from '@utils/rareSats'; -import { useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; +import { StyledP } from '@ui-library/common.styled'; +import { useMemo } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; - -interface DetailSectionProps { - isGalleryOpen?: boolean; -} const Container = styled.div` display: flex; @@ -50,223 +20,19 @@ const Container = styled.div` } `; -const SendButtonContainer = styled.div` - width: ${(props) => (props.isGalleryOpen ? '222px' : '155px')}; -`; - -const BackButtonContainer = styled.div((props) => ({ - display: 'flex', - flexDirection: 'row', - marginTop: props.theme.spacing(40), -})); - -const ExtensionContainer = styled.div({ - display: 'flex', - flexDirection: 'column', - marginTop: 8, - marginBottom: 40, - alignItems: 'center', - flex: 1, -}); - -const RareSatsContainer = styled.div((props) => ({ - maxWidth: 450, - width: '60%', - display: 'flex', - aspectRatio: '1', - flexDirection: 'column', - justifyContent: 'flex-start', - alignItems: 'flex-start', - borderRadius: 8, - marginBottom: props.theme.spacing(12), -})); - -const ExtensionRareSatsContainer = styled.div<{ isInscription?: boolean }>((props) => ({ - maxHeight: props.isInscription ? 148 : 64, - width: props.isInscription ? 148 : 64, - display: 'flex', - aspectRatio: '1', - justifyContent: 'center', - alignItems: 'center', - borderRadius: 8, - marginBottom: props.theme.spacing(12), - marginTop: props.theme.spacing(12), -})); - -const RareSatsTitleText = styled.h1((props) => ({ - ...props.theme.headline_m, - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const RareSatsGalleryTitleText = styled.p((props) => ({ - ...props.theme.headline_l, - color: props.theme.colors.white['0'], - marginBottom: props.theme.spacing(12), -})); - -const DescriptionText = styled.p((props) => ({ - ...props.theme.headline_l, - color: props.theme.colors.white['0'], - fontSize: 24, - marginBottom: props.theme.spacing(16), -})); - const BottomBarContainer = styled.div({ marginTop: 'auto', }); -const RowContainer = styled.div((props) => ({ - display: 'flex', - alignItems: 'flex-start', - marginTop: props.theme.spacing(6), - flexDirection: 'row', -})); - -const ColumnContainer = styled.div({ - display: 'flex', - alignItems: 'flex-start', - flexDirection: 'column', - width: '100%', -}); - -const DescriptionContainer = styled.div((props) => ({ - display: 'flex', - flex: 1, - marginLeft: props.theme.spacing(20), - flexDirection: 'column', - marginBottom: props.theme.spacing(30), -})); - -const StyledWebGalleryButton = styled(WebGalleryButton)` - color: ${(props) => props.theme.colors.white_200}; - margin-top: ${(props) => props.theme.space.xs}; -`; - -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', -})); - -const Button = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-start', - alignItems: 'center', - background: 'transparent', - marginBottom: props.theme.spacing(12), -})); - -const AssetDetailButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, - color: props.theme.colors.white['0'], - textAlign: 'center', -})); - -const SatTypeText = styled.p((props) => ({ - ...props.theme[props.isGalleryOpen ? 'body_bold_l' : 'body_bold_m'], - color: props.theme.colors.white['400'], - textAlign: props.isGalleryOpen ? 'left' : 'center', - textTransform: 'capitalize', -})); - -const DetailSection = styled.div((props) => ({ - display: 'flex', - flexDirection: !props.isGalleryOpen ? 'row' : 'column', - justifyContent: 'space-between', - width: '100%', -})); - -const RareSatRankingBadge = styled.div<{ bgColor: string }>((props) => ({ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - borderRadius: '30px', - backgroundColor: props.bgColor, - marginTop: props.theme.spacing(1), - padding: '5px 10px', -})); - -const RareSatRankingBadgeText = styled.div((props) => ({ - ...props.theme.body_medium_s, - marginLeft: props.theme.spacing(4), -})); - -const StyledCallout = styled(Callout)((props) => ({ - marginBottom: props.theme.space.l, -})); - -const BundleRarityLinkContainer = styled.button((props) => ({ - marginTop: props.isGalleryOpen ? props.theme.space.l : props.theme.space.m, - display: 'inline-flex', - alignSelf: props.isGalleryOpen ? 'flex-start' : 'center', - flexDirection: 'row', - marginBottom: props.isGalleryOpen ? props.theme.spacing(14) : 0, - alignItems: 'center', - backgroundColor: 'transparent', - color: props.theme.colors.white_0, - transition: 'background-color 0.2s ease, opacity 0.2s ease', - ':hover': { - color: props.theme.colors.action.classicLight, - opacity: 0.6, - }, -})); -const BundleRarityTextLink = styled.p((props) => ({ - ...props.theme.body_medium_m, - color: props.theme.colors.white_200, - marginRight: props.theme.spacing(1), -})); -const ArrowRightIcon = styled(ArrowRight)((props) => ({ - color: props.theme.colors.white_200, -})); -const Divider = styled.div((props) => ({ - width: '100%', - height: '1px', - backgroundColor: props.theme.colors.white_900, - marginTop: props.theme.spacing(20), - marginBottom: props.theme.spacing(4), -})); -const Flex1 = styled.div(() => ({ - flex: 1, - width: '100%', -})); -const ViewInExplorerButton = styled.button((props) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'transparent', - marginTop: props.theme.space.xxl, - width: '100%', -})); - +// TODO: this screen will be re-implemented in future iteration of exotics sats function RareSatsDetailScreen() { - const { t } = useTranslation('translation'); const navigate = useNavigate(); const location = useLocation(); - const { ordinalsAddress, network, selectedAccount } = useWalletSelector(); - const { selectedSatBundle, selectedSatBundleItemIndex } = useNftDataSelector(); - const [showSendOridnalsAlert, setshowSendOridnalsAlert] = useState(false); + const { setSelectedSatBundleItemIndex } = useSatBundleDataReducer(); useResetUserFlow('/rare-sats-detail'); - const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); - - const bundle = selectedSatBundle!; - const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle.txid); - const itemIndex = selectedSatBundleItemIndex!; - const item = bundle.items[itemIndex] as BundleItem | undefined; - // when going back, selectedSatBundleItemIndex is set tu null and we don't want to render anything - if (!item) { - return null; - } - - const isBundle = bundle.items.length < 2; - const isUnknown = item?.type === 'unknown'; - const isInscription = item?.type === 'inscription' || item?.type === 'inscribed-sat'; + const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); const handleBackButtonClick = () => { // only go back if there is history @@ -278,191 +44,6 @@ function RareSatsDetailScreen() { setSelectedSatBundleItemIndex(null); }; - const openInGalleryView = async () => { - await chrome.tabs.create({ - url: chrome.runtime.getURL('options.html#/nft-dashboard/rare-sats-detail'), - }); - }; - - const showAlert = () => { - setshowSendOridnalsAlert(true); - }; - - const onCloseAlert = () => { - setshowSendOridnalsAlert(false); - }; - - const handleSendRareSats = async () => { - if (isPending) { - return showAlert(); - } - - if (isLedgerAccount(selectedAccount) && !isInOptions()) { - await chrome.tabs.create({ - url: chrome.runtime.getURL('options.html#/nft-dashboard/send-rare-sat'), - }); - return; - } - - navigate('/nft-dashboard/send-rare-sat'); - }; - - const handleRedirectToTx = () => { - if (pendingTxHash) { - window.open(getBtcTxStatusUrl(pendingTxHash, network), '_blank', 'noopener,noreferrer'); - } - }; - - const handleRarityScale = () => { - navigate('/nft-dashboard/supported-rarity-scale'); - }; - - const openInOrdinalsExplorer = () => { - if (!isInscription) { - return; - } - window.open(`${XVERSE_ORDIVIEW_URL(network.type)}/inscription/${item.inscription.id}`); - }; - - const { color, backgroundColor } = getRareSatsColorsByRareSatsType(item.rarity_ranking); - - const satsRanking = ( - - - - {getRareSatsLabelByType(item.rarity_ranking)} - - - } - /> - ); - const satsValue = ( - - ); - const satsRarity = ( - - ); - const ownedBy = ( - - ); - const id = ( - - ); - const title = getBundleItemId(bundle, itemIndex); - const sendActionSection = isBundle ? ( - <> - - } - text={t('COMMON.SEND')} - onPress={handleSendRareSats} - /> - - - {t('RARE_SATS.RARITY_LINK_TEXT')} - - - - ) : ( - - ); - - const extensionView = ( - - - {getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking })} - - {title} - - - - - {sendActionSection} - - - - {!isUnknown && {satsRanking}} - {isBundle ? satsValue : satsRarity} - - - {!isUnknown && isBundle && {satsRarity}} - {isUnknown ? id : ownedBy} - - - {isInscription && ( - - - - )} - - ); - - const galleryView = ( - - - - - - {getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking })} - - {title} - {sendActionSection} - - - - - - {t('NFT_DETAIL_SCREEN.DESCRIPTION')} - - - {!isUnknown && {satsRanking}} - {isBundle ? satsValue : satsRarity} - - - {!isUnknown && isBundle && {satsRarity}} - {isUnknown ? id : ownedBy} - - - {isInscription && ( - - - - )} - - - - ); - return ( <> {isGalleryOpen ? ( @@ -471,16 +52,7 @@ function RareSatsDetailScreen() { )} - {showSendOridnalsAlert && ( - - )} - {isGalleryOpen && selectedSatBundle !== null ? galleryView : extensionView} + TODO {!isGalleryOpen && ( diff --git a/src/app/screens/signPsbtRequest/index.tsx b/src/app/screens/signPsbtRequest/index.tsx index 201ba64c9..a5709c04c 100644 --- a/src/app/screens/signPsbtRequest/index.tsx +++ b/src/app/screens/signPsbtRequest/index.tsx @@ -16,11 +16,15 @@ import useDetectOrdinalInSignPsbt from '@hooks/useDetectOrdinalInSignPsbt'; import useSignPsbtTx from '@hooks/useSignPsbtTx'; import useWalletSelector from '@hooks/useWalletSelector'; import Transport from '@ledgerhq/hw-transport-webusb'; -import { getBtcFiatEquivalent, satsToBtc, signLedgerPSBT } from '@secretkeylabs/xverse-core'; +import { + Bundle, + getBtcFiatEquivalent, + satsToBtc, + signLedgerPSBT, +} from '@secretkeylabs/xverse-core'; import { Transport as TransportType } from '@secretkeylabs/xverse-core/ledger/types'; import { parsePsbt, psbtBase64ToHex } from '@secretkeylabs/xverse-core/transactions/psbt'; import { isLedgerAccount } from '@utils/helper'; -import { BundleV2 } from '@utils/rareSats'; import BigNumber from 'bignumber.js'; import { decodeToken } from 'jsontokens'; import { useEffect, useMemo, useState } from 'react'; @@ -359,7 +363,7 @@ function SignPsbtRequest() { {bundleItemsData && ( )} 1 ? `${collection.total_inscriptions} Items` : '1 Item'; }; - -export const mapCondensedInscriptionToBundleItem = ( - inscription: CondensedInscription, -): BundleItem => ({ - inscription, - type: 'inscription', - rarity_ranking: 'COMMON', // TODO eventually want to fetch this rarity and display it -}); diff --git a/src/app/utils/rareSats.test.ts b/src/app/utils/rareSats.test.ts deleted file mode 100644 index d42203c7a..000000000 --- a/src/app/utils/rareSats.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { ApiBundle, Bundle, mapRareSatsAPIResponseToRareSats } from './rareSats'; - -describe('rareSats', () => { - describe('mapRareSatsAPIResponseToRareSats', () => { - const testCases: Array<{ name: string; input: ApiBundle; expected: Bundle }> = [ - { - name: 'mixed (sats, inscriptions)', - input: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - sats: [ - { - number: '32234503563456', - offset: 0, - rarity_ranking: 'epic', - }, - { - number: '0', - offset: 100, - rarity_ranking: 'mythic', - }, - ], - inscriptions: [ - { - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', - offset: 0, - content_type: 'image/jpeg', - }, - { - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', - offset: 500, - content_type: 'text/html', - }, - ], - }, - expected: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - items: [ - { - inscription: { - content_type: 'text/html', - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', - }, - rarity_ranking: 'common', - type: 'inscription', - }, - { - inscription: { - content_type: 'image/jpeg', - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', - }, - rarity_ranking: 'epic', - type: 'inscribed-sat', - number: '32234503563456', - }, - { - number: '0', - rarity_ranking: 'mythic', - type: 'rare-sat', - }, - ], - }, - }, - { - name: 'only rare sats', - input: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - sats: [ - { - number: '32234503563456', - offset: 0, - rarity_ranking: 'epic', - }, - { - number: '0', - offset: 100, - rarity_ranking: 'mythic', - }, - ], - inscriptions: [], - }, - expected: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - items: [ - { - number: '32234503563456', - rarity_ranking: 'epic', - type: 'rare-sat', - }, - { - number: '0', - rarity_ranking: 'mythic', - type: 'rare-sat', - }, - ], - }, - }, - { - name: 'only inscriptions', - input: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - sats: [], - inscriptions: [ - { - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', - offset: 0, - content_type: 'image/jpeg', - }, - { - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', - offset: 500, - content_type: 'text/html', - }, - ], - }, - expected: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - items: [ - { - inscription: { - content_type: 'image/jpeg', - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei0', - }, - rarity_ranking: 'common', - type: 'inscription', - }, - { - inscription: { - content_type: 'text/html', - id: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262ei1', - }, - rarity_ranking: 'common', - type: 'inscription', - }, - ], - }, - }, - { - name: 'unknown', - input: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - sats: [], - inscriptions: [], - }, - expected: { - txid: '10f78695a5f83dc2c508fffceb479e49423cf5d538c680864e56c0020c7f262e', - vout: 0, - block_height: 803440, - value: 600, - items: [ - { - type: 'unknown', - rarity_ranking: 'unknown', - }, - ], - }, - }, - ]; - - testCases.forEach(({ name, input, expected }) => { - test(name, () => { - expect(mapRareSatsAPIResponseToRareSats(input)).toEqual(expected); - }); - }); - }); -}); diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 736438b86..00bf055f9 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -1,396 +1,29 @@ +import { + Bundle, + RareSatsType, + RoadArmorRareSats, + RoadArmorRareSatsType, +} from '@secretkeylabs/xverse-core'; import { t } from 'i18next'; import { getTruncatedAddress } from './helper'; -export const RoadArmorRareSats = [ - 'MYTHIC', - 'LEGENDARY', - 'EPIC', - 'RARE', - 'UNCOMMON', - 'COMMON', -] as const; -export type RoadArmorRareSatsType = (typeof RoadArmorRareSats)[number]; - -export const Sattributes = [ - 'BLACK_LEGENDARY', - 'BLACK_EPIC', - 'BLACK_RARE', - 'BLACK_UNCOMMON', - 'FIBONACCI', - '1D_PALINDROME', - '2D_PALINDROME', - '3D_PALINDROME', - 'SEQUENCE_PALINDROME', - 'PERFECT_PALINCEPTION', - 'PALIBLOCK_PALINDROME', - 'PALINDROME', - 'NAME_PALINDROME', - 'ALPHA', - 'OMEGA', - 'FIRST_TRANSACTION', - 'BLOCK9', - 'BLOCK78', - 'NAKAMOTO', - 'VINTAGE', - 'PIZZA', - 'JPEG', - 'HITMAN', - 'SILK_ROAD', -] as const; -export type SattributesType = (typeof Sattributes)[number]; - -// TODO: remove unknown and unify with common -export const RareSats = [...RoadArmorRareSats, 'UNKNOWN', ...Sattributes] as const; -export type RareSatsType = (typeof RareSats)[number]; - export const getRareSatsLabelByType = (type: RareSatsType) => t(`RARE_SATS.RARITY_LABEL.${type}`); -export type SatType = 'inscription' | 'rare-sat' | 'inscribed-sat' | 'unknown'; - -export const getBundleItemSubText = ({ - satType, - rareSatsType, -}: { - satType: SatType; - rareSatsType?: RareSatsType; -}) => - ({ - inscription: t('COMMON.INSCRIPTION'), - 'rare-sat': t('RARE_SATS.SAT_TYPES.RARE_SAT', { - type: getRareSatsLabelByType(rareSatsType ?? 'UNKNOWN'), - }), - 'inscribed-sat': t('RARE_SATS.SAT_TYPES.INSCRIBED_RARE_SAT', { - type: getRareSatsLabelByType(rareSatsType ?? 'UNKNOWN'), - }), - unknown: t('RARE_SATS.SAT_TYPES.UNKNOWN_RARE_SAT'), - }[satType]); - -// TODO: make number separator dynamic by locale, extension only supports en-US for now so this is not a priority -export const getRarityLabelByRareSatsType = (rareSatsType: RareSatsType) => - ({ - mythic: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '1 / 2.1' }), - legendary: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '5 / 2.1' }), - epic: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '32 / 2.1' }), - rare: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '3,437 / 2.1' }), - uncommon: t('RARE_SATS.RARITY_RANKING_POSITION', { position: '6,929,999 / 2.1' }), - common: '--', - }[rareSatsType]); - export const getRareSatsColorsByRareSatsType = (rareSatsType: RareSatsType) => { - const colors: Partial> = { - UNKNOWN: { - color: 'rgb(175,186,189)', - backgroundColor: 'rgba(175,186,189,0.20)', - }, - UNCOMMON: { - color: 'rgb(215, 105, 254)', - backgroundColor: 'rgba(215, 105, 254, 0.20)', - }, - RARE: { - color: 'rgb(131, 113, 242)', - backgroundColor: 'rgba(131, 113, 242, 0.20)', - }, - EPIC: { - color: 'rgb(145, 226, 96)', - backgroundColor: 'rgba(145, 226, 96, 0.20)', - }, - LEGENDARY: { - color: 'rgb(255,205,120)', - backgroundColor: 'rgba(255,205,120,0.20)', - }, - MYTHIC: { - color: 'rgb(255,244,203)', - backgroundColor: 'rgba(255,244,203, 0.20)', - }, - COMMON: { - color: 'rgb(216,216,216)', - backgroundColor: 'rgba(216,216,216,0.20)', - }, + const colors: Partial> = { + UNCOMMON: 'rgba(215, 105, 254, 0.20)', + RARE: 'rgba(131, 113, 242, 0.20)', + EPIC: 'rgba(145, 226, 96, 0.20)', + LEGENDARY: 'rgba(255,205,120,0.20)', + MYTHIC: 'rgba(255,244,203, 0.20)', + COMMON: 'rgba(175,186,189,0.20)', }; return colors[rareSatsType]; }; -type SatInscription = { - id: string; - offset: number; - content_type: string; -}; - -type Sat = { number: string; offset: number; rarity_ranking: Lowercase }; - -export type ApiBundle = { - txid: string; - vout: number; - block_height: number; - value: number; - sats: Array; - inscriptions: Array; -}; - -export type BundleItem = - | { - type: 'rare-sat'; - rarity_ranking: RoadArmorRareSatsType; - number: string; - } - | { - type: 'inscribed-sat'; - rarity_ranking: RoadArmorRareSatsType; - number: string; - inscription: { - id: string; - content_type: string; - }; - } - | { - type: 'inscription'; - rarity_ranking: RoadArmorRareSatsType; - inscription: { - id: string; - content_type: string; - }; - } - | { - type: 'unknown'; - rarity_ranking: 'UNKNOWN'; - }; - -export type Bundle = Omit & { - items: Array; -}; - -export const mapRareSatsAPIResponseToRareSats = (apiBundles: ApiBundle): Bundle => { - const generalBundleInfo = { - txid: apiBundles.txid, - vout: apiBundles.vout, - block_height: apiBundles.block_height, - value: apiBundles.value, - }; - - // unknown - if (!apiBundles.sats.length && !apiBundles.inscriptions.length) { - return { ...generalBundleInfo, items: [{ type: 'unknown', rarity_ranking: 'UNKNOWN' }] }; - } - - // only rare sats - if (!apiBundles.inscriptions.length) { - return { - ...generalBundleInfo, - items: apiBundles.sats.map((sat) => ({ - type: 'rare-sat', - rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, - number: sat.number, - })), - }; - } - - // can be mixed - const satsObject = apiBundles.sats.reduce((acc, sat) => { - acc[sat.offset] = sat; - return acc; - }, {} as Record); - - const inscriptionsObject: Record = {}; - const items: Array = []; - - apiBundles.inscriptions.forEach((inscription) => { - inscriptionsObject[inscription.offset] = inscription; - - if (satsObject[inscription.offset]) { - return; - } - items.push({ - type: 'inscription', - rarity_ranking: 'COMMON', - inscription: { - id: inscription.id, - content_type: inscription.content_type, - }, - }); - }); - - apiBundles.sats.forEach((sat) => { - const inscription = inscriptionsObject[sat.offset]; - if (!inscription) { - return items.push({ - type: 'rare-sat', - rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, - number: sat.number, - }); - } - items.push({ - type: 'inscribed-sat', - rarity_ranking: sat.rarity_ranking.toUpperCase() as RoadArmorRareSatsType, - number: sat.number, - inscription: { - id: inscription.id, - content_type: inscription.content_type, - }, - }); - }); - - return { - ...generalBundleInfo, - items, - }; -}; - -export const getFormattedTxIdVoutFromBundle = (bundle: Bundle | BundleV2) => +export const getFormattedTxIdVoutFromBundle = (bundle: Bundle) => `${getTruncatedAddress(bundle.txid, 6)}:${bundle.vout}`; -export const getBundleId = (bundle: Bundle): string => { - if ( - bundle.items.length === 1 && - bundle.items[0].type !== 'unknown' && - bundle.items[0].type !== 'inscription' - ) { - return bundle.items[0].number; - } - - return getFormattedTxIdVoutFromBundle(bundle); -}; - -export const getBundleSubText = (bundle: Bundle): string => { - if (bundle.items.length > 1) { - return t('RARE_SATS.RARE_SATS_BUNDLE'); - } - - const item = bundle.items[0]; - return getBundleItemSubText({ satType: item.type, rareSatsType: item.rarity_ranking }); -}; - -export const getBundleItemId = (bundle: Bundle, index: number): string => { - const item = bundle.items[index]; - if (item.type === 'unknown') { - return getFormattedTxIdVoutFromBundle(bundle); - } - if (item.type === 'inscription' || item.type === 'inscribed-sat') { - return getTruncatedAddress(item.inscription.id, 6); - } - return item.number; -}; - -// TODO: once we define the layout changes for inscriptions and buy/sell confirmation screen we can remove old implementation and remove the v2 from here -export type Inscription = { - id: string; - content_type: string; - inscription_number: number; -}; - -export type BundleSatRange = Omit & { - totalSats: number; - yearMined: number; -}; - -export type BundleV2 = Omit & { - satRanges: BundleSatRange[]; - inscriptions: Inscription[]; - satributes: RareSatsType[][]; - totalExoticSats: number; -}; - -export type ApiBundleSatRange = { - range: { - start: string; - end: string; - }; - year_mined: number; - block: number; - offset: number; - satributes: RareSatsType[]; - inscriptions: Inscription[]; -}; - -export type ApiBundleV2 = { - txid: string; - vout: number; - block_height?: number; - value: number; - sat_ranges: ApiBundleSatRange[]; -}; - -export const mapRareSatsAPIResponseToRareSatsV2 = (apiBundle: ApiBundleV2): BundleV2 => { - const generalBundleInfo = { - txid: apiBundle.txid, - vout: apiBundle.vout, - block_height: apiBundle.block_height, - value: apiBundle.value, - }; - - const commonUnknownRange: BundleSatRange = { - range: { - start: '0', - end: '0', - }, - yearMined: 0, - block: 0, - offset: 0, - satributes: ['UNKNOWN'], - inscriptions: [], - totalSats: apiBundle.value, - }; - - // if bundle has and empty sat ranges, it means that it's a common/unknown bundle - if (!apiBundle.sat_ranges.length) { - return { - ...generalBundleInfo, - satRanges: [commonUnknownRange], - inscriptions: [], - satributes: [['UNKNOWN']], - totalExoticSats: 0, - }; - } - - const satRanges = apiBundle.sat_ranges.map((satRange) => { - // eslint-disable-next-line @typescript-eslint/naming-convention - const { year_mined, ...satRangeProps } = satRange; - return { - ...satRangeProps, - totalSats: Number(BigInt(satRange.range.end) - BigInt(satRange.range.start)), - yearMined: year_mined, - // we want to common/unknown inscriptions to be shown as a additional row from common/unknown row - satributes: - !satRange.satributes.length && satRange.inscriptions.length - ? (['UNKNOWN'] as RareSatsType[]) - : satRange.satributes, - }; - }); - - // if totalExotics doesn't match the value of the bundle, it means that the bundle is not fully exotic and we need to add a common unknown sat range more - let totalExoticSats = 0; - let totalCommonUnknownInscribedSats = 0; - satRanges.forEach((satRange) => { - if (satRange.satributes.includes('UNKNOWN')) { - totalCommonUnknownInscribedSats += satRange.totalSats; - } else { - totalExoticSats += satRange.totalSats; - } - }); - if (totalExoticSats !== apiBundle.value) { - satRanges.push({ - ...commonUnknownRange, - totalSats: apiBundle.value - (totalExoticSats + totalCommonUnknownInscribedSats), - }); - } - - const inscriptions = satRanges.reduce( - (acc, curr) => [...acc, ...curr.inscriptions], - [] as Inscription[], - ); - const satributes = satRanges.reduce( - (acc, curr) => [...acc, curr.satributes], - [] as RareSatsType[][], - ); - - return { - ...generalBundleInfo, - satRanges, - inscriptions, - satributes, - totalExoticSats, - }; -}; - export const getSatLabel = (satributes: RareSatsType[]): string => { const isLengthGrateThanTwo = satributes.length > 2; if (satributes.length === 1) { diff --git a/src/locales/en.json b/src/locales/en.json index 31e565c08..ad16f84f3 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1074,9 +1074,8 @@ }, "RARE_SATS": { "RARITY_LABEL": { - "UNKNOWN": "Common/Unknown", "UNCOMMON": "Uncommon", - "COMMON": "Common", + "COMMON": "Common/Unknown", "RARE": "Rare", "EPIC": "Epic", "LEGENDARY": "Legendary", @@ -1116,7 +1115,7 @@ "EPIC": "The first sat of each halving epoch.", "RARE": "The first sat of each difficulty adjustment period.", "UNCOMMON": "The first sat of each block.", - "UNKNOWN": "A sat of unknown rarity.", + "COMMON": "A sat of unknown rarity.", "BLACK_LEGENDARY": "The last sat of each cycle.", "BLACK_EPIC": "The last sat of each halving epoch.", "BLACK_RARE": "The last sat of each difficulty adjustment period.", From e35723a8106db7582e3d63bc0ff34d19ea098fea Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Tue, 28 Nov 2023 15:11:52 +0500 Subject: [PATCH 19/28] feat: confirm ordinal screen gallery view (#68) * refactor: send rare sats screen, update gallery UI * feat: confirm screen gallery UI update * chore: remove console log, used space object --------- Co-authored-by: fede erbes --- .../confirmBtcTransactionComponent/index.tsx | 17 +- src/app/routes/index.tsx | 8 + .../screens/confirmBtcTransaction/index.tsx | 1 + .../confirmOrdinalTransaction/index.tsx | 108 +++---- src/app/screens/sendOrdinal/index.tsx | 2 +- src/app/screens/sendRareSat/index.tsx | 287 ++++++++++-------- 6 files changed, 214 insertions(+), 209 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index d6abee2c3..910a822e5 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -3,7 +3,6 @@ import AssetIcon from '@assets/img/transactions/Assets.svg'; import ActionButton from '@components/button'; import InfoContainer from '@components/infoContainer'; import RecipientComponent from '@components/recipientComponent'; -import TopRow from '@components/topRow'; import TransactionSettingAlert from '@components/transactionSetting'; import TransferFeeView from '@components/transferFeeView'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; @@ -36,6 +35,10 @@ import styled from 'styled-components'; import TransactionDetailComponent from '../transactionDetailComponent'; import SatsBundle from './bundle'; +interface ContainerProps { + horizontalSpacing: boolean; +} + const OuterContainer = styled.div` display: flex; flex-direction: column; @@ -43,15 +46,16 @@ const OuterContainer = styled.div` &::-webkit-scrollbar { display: none; } + flex-grow: 1; `; -const Container = styled.div((props) => ({ +const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', flex: 1, marginTop: props.theme.spacing(11), - marginLeft: props.theme.spacing(8), - marginRight: props.theme.spacing(8), + marginLeft: props.horizontalSpacing ? props.theme.spacing(8) : 0, + marginRight: props.horizontalSpacing ? props.theme.spacing(8) : 0, })); interface ButtonProps { @@ -136,6 +140,7 @@ interface Props { isBtcSendBrowserTx?: boolean; currencyType?: CurrencyTypes; isPartOfBundle?: boolean; + horizontalSpacing?: boolean; ordinalBundle?: Bundle; holdsRareSats?: boolean; currentFeeRate: BigNumber; @@ -162,6 +167,7 @@ function ConfirmBtcTransactionComponent({ isPartOfBundle, currencyType, ordinalBundle, + horizontalSpacing, holdsRareSats, currentFeeRate, setCurrentFee, @@ -386,8 +392,7 @@ function ConfirmBtcTransactionComponent({ return ( <> - {!isBtcSendBrowserTx && !isGalleryOpen && } - + {showFeeWarning && ( ), }, + { + path: 'nft-dashboard/confirm-ordinal-tx/:id', + element: ( + + + + ), + }, { path: 'nft-dashboard/supported-rarity-scale', element: , diff --git a/src/app/screens/confirmBtcTransaction/index.tsx b/src/app/screens/confirmBtcTransaction/index.tsx index 59ee95294..88e011e49 100644 --- a/src/app/screens/confirmBtcTransaction/index.tsx +++ b/src/app/screens/confirmBtcTransaction/index.tsx @@ -236,6 +236,7 @@ function ConfirmBtcTransaction() { setCurrentFee={setCurrentFee} currentFeeRate={currentFeeRate} setCurrentFeeRate={setCurrentFeeRate} + horizontalSpacing > {ordinalsInBtc && ordinalsInBtc.length > 0 && ( ({ - marginTop: props.theme.spacing(3), -})); +import SendLayout from '../../layouts/sendLayout'; const Container = styled.div({ display: 'flex', @@ -57,7 +39,6 @@ const NftContainer = styled.div((props) => ({ })); function ConfirmOrdinalTransaction() { - const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; const { selectedAccount, hasActivatedRareSatsKey } = useWalletSelector(); const navigate = useNavigate(); const btcClient = useBtcClient(); @@ -162,58 +143,45 @@ function ConfirmOrdinalTransaction() { }; useResetUserFlow('/confirm-ordinal-tx'); + const handleBackButtonClick = () => { + navigate(-1); + }; + const hideBackButton = location.key === 'default'; return ( - <> - {isGalleryOpen && ( - <> - - {/* - - */} - - )} - - - {selectedOrdinal && ( - - - - - - )} - - - {!isGalleryOpen && ( - - - + + + {selectedOrdinal && ( + + + + + )} - - + + ); } export default ConfirmOrdinalTransaction; diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index 75a49e6b8..a171c38a0 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -157,7 +157,7 @@ function SendOrdinal() { useEffect(() => { if (data) { - navigate(`/confirm-ordinal-tx/${selectedOrdinal?.id}`, { + navigate(`/nft-dashboard/confirm-ordinal-tx/${selectedOrdinal?.id}`, { state: { signedTxHex: data.signedTx, recipientAddress, diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx index 275e2c4f8..a3d1ba6a8 100644 --- a/src/app/screens/sendRareSat/index.tsx +++ b/src/app/screens/sendRareSat/index.tsx @@ -1,8 +1,4 @@ -import ArrowLeft from '@assets/img/dashboard/arrow_left.svg'; -import AccountHeaderComponent from '@components/accountHeader'; -import SendForm from '@components/sendForm'; -import BottomBar from '@components/tabBar'; -import TopRow from '@components/topRow'; +import ActionButton from '@components/button'; import useNftDataSelector from '@hooks/stores/useNftDataSelector'; import useBtcClient from '@hooks/useBtcClient'; import { useResetUserFlow } from '@hooks/useResetUserFlow'; @@ -16,68 +12,91 @@ import { import { ErrorCodes, ResponseError, UTXO } from '@secretkeylabs/xverse-core/types'; import { validateBtcAddress } from '@secretkeylabs/xverse-core/wallet'; import { useMutation } from '@tanstack/react-query'; +import Callout from '@ui-library/callout'; import { StyledHeading } from '@ui-library/common.styled'; -import { isLedgerAccount } from '@utils/helper'; -import { useEffect, useMemo, useState } from 'react'; +import InputFeedback, { InputFeedbackProps, isDangerFeedback } from '@ui-library/inputFeedback'; +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +import SendLayout from '../../layouts/sendLayout'; -const ScrollContainer = styled.div` +const Container = styled.div` display: flex; - flex: 1; flex-direction: column; - overflow-y: auto; - &::-webkit-scrollbar { - display: none; - } - width: 360px; - margin: auto; + justify-content: space-between; + flex-grow: 1; `; -const BottomBarContainer = styled.div({ - marginTop: 'auto', -}); +const StyledSendTo = styled(StyledHeading)` + margin-bottom: ${(props) => props.theme.space.l}; +`; + +const NextButtonContainer = styled.div((props) => ({ + position: 'sticky', + bottom: 0, + paddingBottom: props.theme.space.s, + paddingTop: props.theme.space.s, + backgroundColor: props.theme.colors.elevation0, +})); -const ButtonContainer = styled.div((props) => ({ +const InputGroup = styled.div` + margin-top: ${(props) => props.theme.spacing(8)}px; +`; + +const Label = styled.label((props) => ({ + ...props.theme.typography.body_medium_m, + color: props.theme.colors.white_200, display: 'flex', - flexDirection: 'row', - marginLeft: '15%', - marginTop: props.theme.spacing(40), + flex: 1, })); -const Button = styled.button((props) => ({ +const AmountInputContainer = styled.div<{ error: boolean }>((props) => ({ display: 'flex', flexDirection: 'row', - justifyContent: 'flex-end', alignItems: 'center', + marginTop: props.theme.space.xs, + marginBottom: props.theme.space.xs, + border: props.error + ? `1px solid ${props.theme.colors.danger_dark_200}` + : `1px solid ${props.theme.colors.white_800}`, + backgroundColor: props.theme.colors.elevation_n1, borderRadius: props.theme.radius(1), - backgroundColor: 'transparent', - opacity: 0.8, - marginTop: props.theme.spacing(5), + paddingLeft: props.theme.space.s, + paddingRight: props.theme.space.s, + height: 44, })); -const ButtonText = styled.div((props) => ({ - ...props.theme.body_xs, - fontWeight: 400, - fontSize: 14, - color: props.theme.colors.white['0'], - textAlign: 'center', +const InputFieldContainer = styled.div(() => ({ + flex: 1, })); -const ButtonImage = styled.img((props) => ({ - marginRight: props.theme.spacing(3), - alignSelf: 'center', - transform: 'all', +const InputField = styled.input((props) => ({ + ...props.theme.typography.body_m, + backgroundColor: 'transparent', + color: props.theme.colors.white_0, + width: '100%', + border: 'transparent', +})); + +const ErrorContainer = styled.div((props) => ({ + marginTop: props.theme.space.xs, + marginBottom: props.theme.space.l, })); -const Heading = styled(StyledHeading)` - margin-top: ${(props) => props.theme.space.m}; - margin-left: ${(props) => props.theme.space.m}; +const RowContainer = styled.div({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', +}); + +const StyledCallout = styled(Callout)` + margin-bottom: ${(props) => props.theme.spacing(14)}px; `; function SendOrdinal() { - const { t } = useTranslation('translation'); + const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); const navigate = useNavigate(); const { selectedSatBundle } = useNftDataSelector(); const btcClient = useBtcClient(); @@ -86,60 +105,50 @@ function SendOrdinal() { useWalletSelector(); const { getSeed } = useSeedVault(); const [ordinalUtxo, setOrdinalUtxo] = useState(undefined); - const [error, setError] = useState(''); const [recipientAddress, setRecipientAddress] = useState(''); - const [warning, setWarning] = useState(''); + const [recipientError, setRecipientError] = useState(null); useResetUserFlow('/send-rare-sat'); - const address: string | undefined = useMemo( - () => (location.state ? location.state.recipientAddress : undefined), - [location.state], - ); - const isGalleryOpen: boolean = useMemo(() => document.documentElement.clientWidth > 360, []); - - const signTransaction = async (recipient: string) => { - const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); - const ordUtxo = addressUtxos.find( - (utxo) => - `${utxo.txid}:${utxo.vout}` === `${selectedSatBundle?.txid}:${selectedSatBundle?.vout}`, - ); - setOrdinalUtxo(ordUtxo); - if (ordUtxo) { - const seedPhrase = await getSeed(); - const signedTx = await signOrdinalSendTransaction( - recipient, - ordUtxo, - btcAddress, - Number(selectedAccount?.id), - seedPhrase, - network.type, - [ordUtxo], - ); - - return signedTx; - } - }; - const { isLoading, data, error: txError, mutate, } = useMutation({ - mutationFn: signTransaction, + mutationFn: async (recipient) => { + const addressUtxos = await btcClient.getUnspentUtxos(ordinalsAddress); + const ordUtxo = addressUtxos.find( + (utxo) => + `${utxo.txid}:${utxo.vout}` === `${selectedSatBundle?.txid}:${selectedSatBundle?.vout}`, + ); + setOrdinalUtxo(ordUtxo); + if (ordUtxo) { + const seedPhrase = await getSeed(); + const signedTx = await signOrdinalSendTransaction( + recipient, + ordUtxo, + btcAddress, + Number(selectedAccount?.id), + seedPhrase, + network.type, + [ordUtxo], + ); + return signedTx; + } + }, }); useEffect(() => { if (data) { - navigate(`/confirm-ordinal-tx/${selectedSatBundle?.txid}`, { + navigate(`/nft-dashboard/confirm-ordinal-tx/${selectedSatBundle?.txid}`, { state: { signedTxHex: data.signedTx, recipientAddress, fee: data.fee, feePerVByte: data.feePerVByte, - fiatFee: getBtcFiatEquivalent(data.fee, btcFiatRate), + fiatFee: getBtcFiatEquivalent(data.fee, new BigNumber(btcFiatRate)), total: data.total, - fiatTotal: getBtcFiatEquivalent(data.total, btcFiatRate), + fiatTotal: getBtcFiatEquivalent(data.total, new BigNumber(btcFiatRate)), ordinalUtxo, isRareSat: true, }, @@ -149,11 +158,12 @@ function SendOrdinal() { useEffect(() => { if (txError) { + console.log('txError', txError); if (Number(txError) === ErrorCodes.InSufficientBalance) { - setError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); + setRecipientError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); } else if (Number(txError) === ErrorCodes.InSufficientBalanceWithTxFee) { - setError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); - } else setError(txError.toString()); + setRecipientError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); + } else setRecipientError(txError); } }, [txError]); // eslint-disable-line react-hooks/exhaustive-deps @@ -161,71 +171,84 @@ function SendOrdinal() { navigate(-1); }; - function validateFields(associatedAddress: string): boolean { - if (!associatedAddress) { - setError(t('SEND.ERRORS.ADDRESS_REQUIRED')); + const validateRecipientAddress = (address: string): boolean => { + if (!address) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_REQUIRED') }); return false; } - - if (!validateBtcAddress({ btcAddress: associatedAddress, network: network.type })) { - setError(t('SEND.ERRORS.ADDRESS_INVALID')); + if ( + !validateBtcAddress({ + btcAddress: address, + network: network.type, + }) + ) { + setRecipientError({ variant: 'danger', message: t('ERRORS.ADDRESS_INVALID') }); return false; } - + if (address === ordinalsAddress || address === btcAddress) { + setRecipientError({ variant: 'info', message: t('YOU_ARE_TRANSFERRING_TO_YOURSELF') }); + return true; + } + setRecipientError(null); return true; - } + }; - const onPressNext = async (associatedAddress: string) => { - setRecipientAddress(associatedAddress); - if (validateFields(associatedAddress)) { - mutate(associatedAddress); + const onPressNext = async () => { + if (validateRecipientAddress(recipientAddress)) { + mutate(recipientAddress); } }; - const handleInputChange = (inputAddress: string) => { - if (inputAddress === ordinalsAddress) { - return setWarning(t('SEND.YOU_ARE_TRANSFERRING_TO_YOURSELF')); - } - setWarning(''); + const handleAddressChange = (e: React.ChangeEvent) => { + validateRecipientAddress(e.target.value); + setRecipientAddress(e.target.value); }; + const isNextEnabled = !isDangerFeedback(recipientError) && !!recipientAddress; + + // hide back button if there is no history + const hideBackButton = location.key === 'default'; + return ( - <> - {isGalleryOpen && ( - <> - - {!isLedgerAccount(selectedAccount) && ( - - - - )} - - )} - - {!isGalleryOpen && } - {t('SEND.SEND_TO')} - - {!isGalleryOpen && } - - + + +
+ + {t('SEND_TO')} + + + + + + + + + + + + {recipientError && } + + + +
+ + + +
+
); } From 28d822342cfb13c92a31451dd6c125d1136ac1f5 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Wed, 29 Nov 2023 16:31:11 +0500 Subject: [PATCH 20/28] fix: testing issues (#69) * fix: spacing issues * added scrollbar in rare sat detail * fix: scrollbar in confirm screen * fix: scrollbar in rarity screen * fix: send errors * removed console log * fix: rare sat bundle navigation * fix: rare detail text * fix: confirm UI * fix: rare sats bundle navigation --- .../confirmBtcTransactionComponent/index.tsx | 28 ++++++++----------- src/app/layouts/sendLayout.tsx | 3 +- .../screens/confirmBtcTransaction/index.tsx | 1 - .../nftDashboard/rareSatsTabGridItem.tsx | 2 +- .../nftDashboard/supportedRarities/index.tsx | 5 ++-- .../screens/ordinalDetail/useOrdinalDetail.ts | 2 +- src/app/screens/rareSatsBundle/index.tsx | 12 ++++++-- src/app/screens/sendNft/index.tsx | 1 + src/app/screens/sendOrdinal/index.tsx | 1 + src/app/screens/sendRareSat/index.tsx | 11 +++++--- src/locales/en.json | 6 ++-- 11 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 910a822e5..7b3bb2e30 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -35,27 +35,25 @@ import styled from 'styled-components'; import TransactionDetailComponent from '../transactionDetailComponent'; import SatsBundle from './bundle'; -interface ContainerProps { - horizontalSpacing: boolean; +interface MainContainerProps { + isGalleryOpen: boolean; } -const OuterContainer = styled.div` +const OuterContainer = styled.div` display: flex; flex-direction: column; - overflow-y: auto; - &::-webkit-scrollbar { - display: none; - } + flex: 1; flex-grow: 1; + ...${(props) => (props.isGalleryOpen ? props.theme.scrollbar : {})}; `; -const Container = styled.div((props) => ({ +const Container = styled.div((props) => ({ display: 'flex', flexDirection: 'column', flex: 1, marginTop: props.theme.spacing(11), - marginLeft: props.horizontalSpacing ? props.theme.spacing(8) : 0, - marginRight: props.horizontalSpacing ? props.theme.spacing(8) : 0, + marginLeft: props.theme.space.m, + marginRight: props.theme.space.m, })); interface ButtonProps { @@ -66,8 +64,8 @@ const ButtonContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', position: 'relative', - marginLeft: props.theme.spacing(8), - marginRight: props.theme.spacing(8), + marginLeft: props.theme.space.m, + marginRight: props.theme.space.m, marginBottom: props.isBtcSendBrowserTx ? props.theme.spacing(20) : props.theme.spacing(5), })); @@ -140,7 +138,6 @@ interface Props { isBtcSendBrowserTx?: boolean; currencyType?: CurrencyTypes; isPartOfBundle?: boolean; - horizontalSpacing?: boolean; ordinalBundle?: Bundle; holdsRareSats?: boolean; currentFeeRate: BigNumber; @@ -167,7 +164,6 @@ function ConfirmBtcTransactionComponent({ isPartOfBundle, currencyType, ordinalBundle, - horizontalSpacing, holdsRareSats, currentFeeRate, setCurrentFee, @@ -391,8 +387,8 @@ function ConfirmBtcTransactionComponent({ return ( <> - - + + {showFeeWarning && ( props.theme.colors.elevation3}; border-radius: ${(props) => props.theme.space.s}; - padding: ${(props) => props.theme.space.l} ${(props) => props.theme.space.m}; + padding: ${(props) => props.theme.space.l} 0; padding-bottom: ${(props) => props.theme.space.xxl}; margin-top: ${(props) => props.theme.space.xxxxl}; } @@ -51,6 +51,7 @@ const Button = styled.button` display: flex; background-color: transparent; margin-bottom: ${(props) => props.theme.space.l}; + margin-left: ${(props) => props.theme.space.s}; `; function SendLayout({ diff --git a/src/app/screens/confirmBtcTransaction/index.tsx b/src/app/screens/confirmBtcTransaction/index.tsx index 88e011e49..59ee95294 100644 --- a/src/app/screens/confirmBtcTransaction/index.tsx +++ b/src/app/screens/confirmBtcTransaction/index.tsx @@ -236,7 +236,6 @@ function ConfirmBtcTransaction() { setCurrentFee={setCurrentFee} currentFeeRate={currentFeeRate} setCurrentFeeRate={setCurrentFeeRate} - horizontalSpacing > {ordinalsInBtc && ordinalsInBtc.length > 0 && ( { // exotics v1 wont show range details only bundle details setSelectedSatBundleDetails(bundle); - navigate('/nft-dashboard/rare-sats-bundle'); + navigate('/nft-dashboard/rare-sats-bundle', { state: { source: 'RareSatsTab' } }); }; const renderedIcons = () => { diff --git a/src/app/screens/nftDashboard/supportedRarities/index.tsx b/src/app/screens/nftDashboard/supportedRarities/index.tsx index 3bb81b2cb..9e75db492 100644 --- a/src/app/screens/nftDashboard/supportedRarities/index.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/index.tsx @@ -45,13 +45,14 @@ const Container = styled.div((props) => ({ width: props.isGallery ? 580 : '100%', })); -const MainContainer = styled.div({ +const MainContainer = styled.div((props) => ({ + ...props.theme.scrollbar, display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', backgroundColor: Theme.colors.elevation0, -}); +})); const rarityTypes = [...RoadArmorRareSats, ...Sattributes]; diff --git a/src/app/screens/ordinalDetail/useOrdinalDetail.ts b/src/app/screens/ordinalDetail/useOrdinalDetail.ts index 487107974..9ba917938 100644 --- a/src/app/screens/ordinalDetail/useOrdinalDetail.ts +++ b/src/app/screens/ordinalDetail/useOrdinalDetail.ts @@ -110,7 +110,7 @@ export default function useOrdinalDetail() { } setSelectedOrdinalDetails(ordinalData); setSelectedSatBundleDetails(bundle); - navigate('/nft-dashboard/rare-sats-bundle'); + navigate('/nft-dashboard/rare-sats-bundle', { state: { source: 'OrdinalDetail' } }); }; const onCopyClick = () => { diff --git a/src/app/screens/rareSatsBundle/index.tsx b/src/app/screens/rareSatsBundle/index.tsx index 9eb6eb796..c6beccec5 100644 --- a/src/app/screens/rareSatsBundle/index.tsx +++ b/src/app/screens/rareSatsBundle/index.tsx @@ -22,7 +22,7 @@ import { } from '@utils/helper'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import OrdinalAttributeComponent from '../ordinalDetail/ordinalAttributeComponent'; import { RareSatsBundleGridItem } from './rareSatsBundleGridItem'; @@ -33,7 +33,9 @@ interface DetailSectionProps { /* layout */ const Container = styled.div` + ...${(props) => props.theme.scrollbar}; overflow-y: auto; + padding-bottom: ${(props) => props.theme.space.l}; `; const PageHeader = styled.div` @@ -161,6 +163,8 @@ const SeeRarityContainer = styled.div` function RareSatsBundle() { const { t } = useTranslation('translation'); const navigate = useNavigate(); + const location = useLocation(); + const { source } = location.state || {}; const { network, selectedAccount, ordinalsAddress } = useWalletSelector(); const { selectedSatBundle: bundle, selectedOrdinal } = useNftDataSelector(); const { isPending, pendingTxHash } = usePendingOrdinalTxs(bundle?.txid); @@ -172,7 +176,11 @@ function RareSatsBundle() { useResetUserFlow('/rare-sats-bundle'); const handleBackButtonClick = () => { - navigate(-1); + if (source === 'OrdinalDetail') { + navigate(-1); + } else { + navigate('/nft-dashboard?tab=rareSats'); + } setSelectedSatBundleDetails(null); }; diff --git a/src/app/screens/sendNft/index.tsx b/src/app/screens/sendNft/index.tsx index 84ff4a26e..82276c7c5 100644 --- a/src/app/screens/sendNft/index.tsx +++ b/src/app/screens/sendNft/index.tsx @@ -29,6 +29,7 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; + padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index a171c38a0..7e049a0fa 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -32,6 +32,7 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; + padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx index a3d1ba6a8..a6dca4503 100644 --- a/src/app/screens/sendRareSat/index.tsx +++ b/src/app/screens/sendRareSat/index.tsx @@ -27,6 +27,7 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; + padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` @@ -158,12 +159,14 @@ function SendOrdinal() { useEffect(() => { if (txError) { - console.log('txError', txError); if (Number(txError) === ErrorCodes.InSufficientBalance) { - setRecipientError(t('SEND.ERRORS.INSUFFICIENT_BALANCE')); + setRecipientError({ variant: 'danger', message: t('ERRORS.INSUFFICIENT_BALANCE') }); } else if (Number(txError) === ErrorCodes.InSufficientBalanceWithTxFee) { - setRecipientError(t('SEND.ERRORS.INSUFFICIENT_BALANCE_FEES')); - } else setRecipientError(txError); + setRecipientError({ + variant: 'danger', + message: t('ERRORS.INSUFFICIENT_BALANCE_FEES'), + }); + } else setRecipientError({ variant: 'danger', message: txError.toString() }); } }, [txError]); // eslint-disable-line react-hooks/exhaustive-deps diff --git a/src/locales/en.json b/src/locales/en.json index ad16f84f3..7f1dc04a6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1125,10 +1125,10 @@ "2D_PALINDROME": "Sats with palindromic number, composed of only 2 digit (ex: 8888822288888).", "3D_PALINDROME": "Sats with palindromic number, composed of only 3 digit (ex: 8885522255888).", "SEQUENCE_PALINDROME": "Sats with palindromic number, and a sequence of at least 3 consecutive identical digits (ex: 3275433345723).", - "PERFECT_PALINCEPTION": "Sats with palindromic number made of a subsequence which is also a palindrome of at least 2 distinct digits", + "PERFECT_PALINCEPTION": "Sats with palindromic number made of a subsequence which is also a palindrome of at least 2 distinct digits.", "PALIBLOCK_PALINDROME": "Sats with palindromic number, in a block with a palindromic number.", - "PALINDROME": "Sats with palindromic number (ex: 3275431345723)", - "NAME_PALINDROME": "Sats with palindromic names (ex: abcba)", + "PALINDROME": "Sats with palindromic number (ex: 3275431345723).", + "NAME_PALINDROME": "Sats with palindromic names (ex: abcba).", "ALPHA": "The first sats in each bitcoin. They always end in at least 8 zeros.", "OMEGA": "The last sats in each bitcoin. They always end in at least 8 nines.", "FIRST_TRANSACTION": "Sats from the 10 bitcoins Satoshi Nakamoto sent Hal Finney in the first bitcoin transaction.", From e574270758ecccc55d7ce8e6d917e99d0971e91f Mon Sep 17 00:00:00 2001 From: fede erbes Date: Wed, 29 Nov 2023 18:12:09 +0100 Subject: [PATCH 21/28] fix: logic and ui in RareSatsTabGridItem component (#692) --- package-lock.json | 14 +- package.json | 2 +- .../exoticSatsRow/exoticSatsRow.tsx | 21 +- .../ordinals/tempAddressRareSatsMock.ts | 269 +++++++++++++++++- .../queries/ordinals/useAddressRareSats.ts | 9 +- .../screens/nftDashboard/collectiblesTabs.tsx | 2 +- .../nftDashboard/rareSatsTabGridItem.tsx | 91 ++++-- .../nftDashboard/supportedRarities/index.tsx | 4 +- src/app/utils/rareSats.ts | 6 +- 9 files changed, 365 insertions(+), 53 deletions(-) diff --git a/package-lock.json b/package-lock.json index f2b34ceea..2dd688aec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "3.1.1-e148aa5", + "@secretkeylabs/xverse-core": "4.0.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", @@ -1727,9 +1727,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "3.1.1-e148aa5", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.1.1-e148aa5/052344a16abd8ca22ae92643c209ac586c004241", - "integrity": "sha512-J52vNGjglWUQ8PHV5t/bPBFDs5bSXBzaPFHVe6KlFs90BFsAFsD9gdGMB0M9wGJgPFNQc820XZne11YJGbmllw==", + "version": "4.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/4.0.0/b2776f6bd4a6eb065b31eafd6ab198c486af7b8d", + "integrity": "sha512-u4XBHz8VYeQGFtpjxfOIMMcx6OAusQx02j/fAanwURHAbgeX8P90esY4s8rtAFcOV16dGRqA/HHEIusnt3d6+Q==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -16046,9 +16046,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "3.1.1-e148aa5", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/3.1.1-e148aa5/052344a16abd8ca22ae92643c209ac586c004241", - "integrity": "sha512-J52vNGjglWUQ8PHV5t/bPBFDs5bSXBzaPFHVe6KlFs90BFsAFsD9gdGMB0M9wGJgPFNQc820XZne11YJGbmllw==", + "version": "4.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/4.0.0/b2776f6bd4a6eb065b31eafd6ab198c486af7b8d", + "integrity": "sha512-u4XBHz8VYeQGFtpjxfOIMMcx6OAusQx02j/fAanwURHAbgeX8P90esY4s8rtAFcOV16dGRqA/HHEIusnt3d6+Q==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/secp256k1": "^1.7.1", diff --git a/package.json b/package.json index a917366f4..797339ffe 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "3.1.1-e148aa5", + "@secretkeylabs/xverse-core": "4.0.0", "@stacks/connect": "^6.10.2", "@stacks/encryption": "4.3.5", "@stacks/stacks-blockchain-api-types": "6.1.1", diff --git a/src/app/components/exoticSatsRow/exoticSatsRow.tsx b/src/app/components/exoticSatsRow/exoticSatsRow.tsx index 838f98f7c..9af5e101e 100644 --- a/src/app/components/exoticSatsRow/exoticSatsRow.tsx +++ b/src/app/components/exoticSatsRow/exoticSatsRow.tsx @@ -66,10 +66,12 @@ function ExoticSatsRow({ satAmount, inscriptions, icons, + showNumberOfInscriptions = false, }: { title: string; satAmount: number; inscriptions: SatRangeInscription[]; + showNumberOfInscriptions?: boolean; icons: ReactNode; }) { const { t } = useTranslation('translation', { keyPrefix: 'COMMON' }); @@ -90,14 +92,25 @@ function ExoticSatsRow({ )} /> - {inscriptions.map((inscription) => ( - + {showNumberOfInscriptions && inscriptions.length ? ( + ordinal - {inscription.inscription_number} + {inscriptions.length > 1 + ? `+${inscriptions.length}` + : inscriptions[0].inscription_number} - ))} + ) : ( + inscriptions.map((inscription) => ( + + ordinal + + {inscription.inscription_number} + + + )) + )} {icons} diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts index 237e4a25f..39a3684a6 100644 --- a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts +++ b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts @@ -141,13 +141,13 @@ export const mockTestCase1: AddressBundleResponse = { results: [], }; -// TestCase 2 - 3 bundles +// TestCase 3 - 6 bundles const { xVersion, ...bundle } = inscriptionPartOfBundle; export const mockTestCase3: AddressBundleResponse = { xVersion: 1, limit: 30, offset: 0, - total: 5, + total: 6, results: [ { block_height: 803128, @@ -181,6 +181,16 @@ export const mockTestCase3: AddressBundleResponse = { id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', inscription_number: 123141212, }, + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141213, + }, + { + content_type: 'text/plain;charset=utf-8', + id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', + inscription_number: 123141214, + }, ], }, { @@ -221,7 +231,7 @@ export const mockTestCase3: AddressBundleResponse = { start: '34234320000000', end: '34234320010000', }, - satributes: ['MYTHIC', 'BLOCK78'], + satributes: ['MYTHIC'], inscriptions: [], }, { @@ -232,7 +242,7 @@ export const mockTestCase3: AddressBundleResponse = { start: '34234320010001', end: '34234320010002', }, - satributes: ['PIZZA'], + satributes: ['PIZZA', 'BLOCK78', 'BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], inscriptions: [ { content_type: 'text/plain;charset=utf-8', @@ -327,6 +337,17 @@ export const mockTestCase3: AddressBundleResponse = { value: 100, vout: 0, sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME', 'BLOCK9_450', 'VINTAGE', 'SILK_ROAD'], + inscriptions: [], + }, { year_mined: 2009, block: 9, @@ -340,6 +361,91 @@ export const mockTestCase3: AddressBundleResponse = { }, ], }, + { + block_height: 803128, + txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d1', + value: 100, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['UNCOMMON'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['NAKAMOTO'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['SILK_ROAD'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['SEQUENCE_PALINDROME'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['PERFECT_PALINCEPTION'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['VINTAGE'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 9, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000003', + }, + satributes: ['MYTHIC'], + inscriptions: [], + }, + ], + }, bundle, { block_height: 803128, @@ -350,3 +456,158 @@ export const mockTestCase3: AddressBundleResponse = { }, ], }; + +// TestCase 4 - 4 bundles with unsupported types +export const mockTestCase4: AddressBundleResponse = { + xVersion: 1, + limit: 30, + offset: 0, + total: 5, + results: [ + { + block_height: 803128, + txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', + value: 10, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 11, + offset: 1, + range: { + start: '34234320000003', + end: '34234320000004', + }, + satributes: ['1D_PALINDROME', '2D_PALINDROME', 'BLOCK9_450'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 11, + offset: 2, + range: { + start: '34234320000003', + end: '34234320000004', + }, + satributes: ['PIZZA', 'BLOCK9_450'], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067475, + }, + ], + }, + { + year_mined: 2009, + block: 10, + offset: 0, + range: { + start: '34234320000000', + end: '34234320000001', + }, + satributes: ['BLOCK9_450'], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067474, + }, + ], + }, + { + year_mined: 2009, + block: 11, + offset: 3, + range: { + start: '34234320000004', + end: '34234320000005', + }, + satributes: ['BLOCK9_450'], + inscriptions: [], + }, + ], + }, + { + block_height: 803128, + txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', + value: 10, + vout: 0, + sat_ranges: [ + { + year_mined: 2009, + block: 11, + offset: 0, + range: { + start: '34234320000003', + end: '34234320000004', + }, + satributes: ['EPIC', '1D_PALINDROME', '2D_PALINDROME', 'BLOCK9_450', 'VINTAGE'], + inscriptions: [], + }, + { + year_mined: 2009, + block: 11, + offset: 1, + range: { + start: '34234320000003', + end: '34234320000004', + }, + satributes: ['PIZZA', 'BLOCK9_450'], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067475, + }, + ], + }, + { + year_mined: 2009, + block: 10, + offset: 2, + range: { + start: '34234320000000', + end: '34234320000001', + }, + satributes: ['BLOCK9_450', 'BLOCK78', 'FIBONACCI'], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067474, + }, + ], + }, + { + year_mined: 2009, + block: 10, + offset: 3, + range: { + start: '34234320000000', + end: '34234320000001', + }, + satributes: ['BLOCK9_450', 'BLOCK78', 'FIBONACCI', 'BLACK_EPIC'], + inscriptions: [ + { + content_type: 'image/png', + id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', + inscription_number: 11067473, + }, + ], + }, + { + year_mined: 2009, + block: 11, + offset: 4, + range: { + start: '34234320000004', + end: '34234320000005', + }, + satributes: ['BLOCK9_450'], + inscriptions: [], + }, + ], + }, + ], +}; diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 466605de2..6c588956e 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -12,6 +12,7 @@ import { mockData, mockTestCase1, mockTestCase3, + mockTestCase4, } from './tempAddressRareSatsMock'; const PAGE_SIZE = 30; @@ -41,12 +42,18 @@ export const useAddressRareSats = () => { throw new Error('Error response from API'); } - // 1 BUNDLE with 4 sat ranges + // 6 bundles with different combinations of sats and inscriptions const testcase3 = localStorage.getItem('testcase3'); if (testcase3) { return mockTestCase3; } + // 2 bundles with different combinations of sats and inscriptions but with unsupported types + const testcase4 = localStorage.getItem('testcase4'); + if (testcase4) { + return mockTestCase4; + } + return mockData; } diff --git a/src/app/screens/nftDashboard/collectiblesTabs.tsx b/src/app/screens/nftDashboard/collectiblesTabs.tsx index f2789daee..c68db4df1 100644 --- a/src/app/screens/nftDashboard/collectiblesTabs.tsx +++ b/src/app/screens/nftDashboard/collectiblesTabs.tsx @@ -16,7 +16,7 @@ import Notice from './notice'; import RareSatsTabGridItem from './rareSatsTabGridItem'; import type { NftDashboardState } from './useNftDashboard'; -const MAX_SATS_ITEMS_EXTENSION = 6; +const MAX_SATS_ITEMS_EXTENSION = 5; const MAX_SATS_ITEMS_GALLERY = 20; export const GridContainer = styled.div<{ diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx index ac9764835..03182618f 100644 --- a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -2,7 +2,7 @@ import ExoticSatsRow from '@components/exoticSatsRow/exoticSatsRow'; import RareSatIcon from '@components/rareSatIcon/rareSatIcon'; import useSatBundleDataReducer from '@hooks/stores/useSatBundleReducer'; import { DotsThree } from '@phosphor-icons/react'; -import { Bundle } from '@secretkeylabs/xverse-core'; +import { Bundle, RareSatsType } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; import { getFormattedTxIdVoutFromBundle } from '@utils/rareSats'; import { useNavigate } from 'react-router-dom'; @@ -44,40 +44,70 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: Bundle; maxItems: n const renderedIcons = () => { let totalIconsDisplayed = 0; let totalTilesDisplayed = 0; - return bundle.satributes + + const icons: (RareSatsType | 'ellipsis' | '+X')[][] = []; + let overLimitSatsIndex: number | null = null; + let totalSats = 0; + let totalTiles = 0; + bundle.satributes .filter((satributes) => !(satributes.includes('COMMON') && bundle.satributes.length > 1)) - .map((sats, index) => { - if (totalIconsDisplayed > maxItems) { - return null; - } + .forEach((sats, index) => { + totalSats += sats.length; + totalTiles += 1; - if (totalIconsDisplayed >= maxItems - 1) { - totalIconsDisplayed += 1; - return ( - - - +{bundle.satributes.length - totalTilesDisplayed} - - - ); + const isOverLimit = + totalIconsDisplayed + sats.length > maxItems - (sats.length > 1 ? 2 : 1); + // we add ranges till we reach the limit and we store the index of the range that is over the limit + if (isOverLimit || overLimitSatsIndex !== null) { + overLimitSatsIndex = overLimitSatsIndex !== null ? overLimitSatsIndex : index; + return; } totalTilesDisplayed += 1; - return ( - - {sats.map((sattribute, indexSattributes) => { - totalIconsDisplayed += 1; - if (totalIconsDisplayed >= maxItems - 1) { - return null; - } - // eslint-disable-next-line react/no-array-index-key - return ; - })} - {totalIconsDisplayed > maxItems - 2 ? ( - - ) : null} - - ); + totalIconsDisplayed += sats.length; + icons.push(sats); }); + + // if we have more than 1 range and we have reached the limit we add ellipsis and +X + if (overLimitSatsIndex !== null) { + const sats = bundle.satributes[overLimitSatsIndex]; + const satsToDisplay = maxItems - totalIconsDisplayed - 2; + const firstSats = sats.slice(0, satsToDisplay); + // we add ellipsis only if we have more than 1 slot left counting the +X + if (firstSats.length > 0) { + totalTilesDisplayed += 1; + icons.push([...firstSats, 'ellipsis']); + } + + if (totalSats > maxItems) { + icons.push(['+X']); + } + } + + return icons.map((sats, index) => ( + + {sats.map((sattribute, indexSatributes) => { + if (sattribute === 'ellipsis') { + return ( + + ); + } + + if (sattribute === '+X') { + return ( + + +{totalTiles - totalTilesDisplayed} + + ); + } + // eslint-disable-next-line react/no-array-index-key + return ; + })} + + )); }; const bundleId = getFormattedTxIdVoutFromBundle(bundle); @@ -88,6 +118,7 @@ function RareSatsTabGridItem({ bundle, maxItems }: { bundle: Bundle; maxItems: n title={bundleId} satAmount={bundle.value} inscriptions={bundle.inscriptions} + showNumberOfInscriptions icons={renderedIcons()} /> diff --git a/src/app/screens/nftDashboard/supportedRarities/index.tsx b/src/app/screens/nftDashboard/supportedRarities/index.tsx index 9e75db492..ce91f4cda 100644 --- a/src/app/screens/nftDashboard/supportedRarities/index.tsx +++ b/src/app/screens/nftDashboard/supportedRarities/index.tsx @@ -1,6 +1,6 @@ import TopRow from '@components/topRow'; import { ArrowUpRight } from '@phosphor-icons/react'; -import { RoadArmorRareSats, Sattributes } from '@secretkeylabs/xverse-core'; +import { RodarmorRareSats, Satributes } from '@secretkeylabs/xverse-core'; import { StyledP } from '@ui-library/common.styled'; import { BLOG_LINK } from '@utils/constants'; import { useTranslation } from 'react-i18next'; @@ -54,7 +54,7 @@ const MainContainer = styled.div((props) => ({ backgroundColor: Theme.colors.elevation0, })); -const rarityTypes = [...RoadArmorRareSats, ...Sattributes]; +const rarityTypes = [...RodarmorRareSats, ...Satributes]; function SupportedRarities() { const navigate = useNavigate(); diff --git a/src/app/utils/rareSats.ts b/src/app/utils/rareSats.ts index 00bf055f9..1506977ed 100644 --- a/src/app/utils/rareSats.ts +++ b/src/app/utils/rareSats.ts @@ -1,8 +1,8 @@ import { Bundle, RareSatsType, - RoadArmorRareSats, - RoadArmorRareSatsType, + RodarmorRareSats, + RodarmorRareSatsType, } from '@secretkeylabs/xverse-core'; import { t } from 'i18next'; import { getTruncatedAddress } from './helper'; @@ -31,7 +31,7 @@ export const getSatLabel = (satributes: RareSatsType[]): string => { } // we expect to roadarmor sats be in the first position - if (RoadArmorRareSats.includes(satributes[0] as RoadArmorRareSatsType)) { + if (RodarmorRareSats.includes(satributes[0] as RodarmorRareSatsType)) { return `${getRareSatsLabelByType(satributes[0])} ${t( isLengthGrateThanTwo ? 'COMMON.COMBO' : `RARE_SATS.RARITY_LABEL.${satributes[1]}`, )}`; From 49c351db98fef505abc44652e1767b3ac4f1f0de Mon Sep 17 00:00:00 2001 From: Tim Man Date: Thu, 30 Nov 2023 14:06:57 +0800 Subject: [PATCH 22/28] fix: typo --- src/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/en.json b/src/locales/en.json index 345bf39c9..0835bbf82 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1157,7 +1157,7 @@ "VINTAGE": "Sats mined in the first 1000 bitcoin blocks.", "PIZZA": "Sats involved in the famous pizza transaction from 2010.", "JPEG": "Sats involved in the possible first bitcoin trade for an image on February 24, 2010.", - "HITMAN": "Sats involved the transaction made by Ross Ulbricht to hire a hitman.", + "HITMAN": "Sats involved in the transaction made by Ross Ulbricht to hire a hitman.", "SILK_ROAD": "Sats seized from Silk Road and auctioned off on June 27, 2014 by US Marshals." }, "SAT_TYPES": { From 743fa726180c1ad23756f3d892533930d7e08ad5 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Thu, 30 Nov 2023 11:29:04 +0500 Subject: [PATCH 23/28] chore: use colors from theme --- .../components/confirmBtcTransactionComponent/bundleItem.tsx | 4 ++-- src/app/screens/nftDashboard/rareSatsTabGridItem.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx index 18cc33db3..009220d0b 100644 --- a/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx +++ b/src/app/components/confirmBtcTransactionComponent/bundleItem.tsx @@ -13,7 +13,7 @@ const RangeContainer = styled.div``; const Range = styled.div` display: flex; border-radius: 6px; - border: 1px solid var(--white-800, rgba(255, 255, 255, 0.2)); + border: 1px solid ${(props) => props.theme.colors.white_800}; padding: 1px; flex-wrap: wrap; flex-direction: row; @@ -32,7 +32,7 @@ const Container = styled.div` justify-content: space-between; align-items: center; border-bottom: ${(props) => - props.showDivider ? '1px solid rgba(255, 255, 255, 0.10)' : 'transparent'}; + props.showDivider ? `1px solid ${props.theme.colors.white_900}` : 'transparent'}; width: 100%; }`; diff --git a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx index 03182618f..68d2e0601 100644 --- a/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx +++ b/src/app/screens/nftDashboard/rareSatsTabGridItem.tsx @@ -13,7 +13,7 @@ const Range = styled.div` display: flex; flex-direction: row; border-radius: 6px; - border: 1px solid var(--white-800, rgba(255, 255, 255, 0.2)); + border: 1px solid ${(props) => props.theme.colors.white_800}; margin-left: 2px; align-items: center; padding: 1px; From d5409a4dc32db97bf5829d2fa9493ac594531549 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Thu, 30 Nov 2023 12:19:07 +0500 Subject: [PATCH 24/28] fix: padding --- src/app/screens/sendNft/index.tsx | 1 - src/app/screens/sendOrdinal/index.tsx | 1 - src/app/screens/sendRareSat/index.tsx | 1 - 3 files changed, 3 deletions(-) diff --git a/src/app/screens/sendNft/index.tsx b/src/app/screens/sendNft/index.tsx index 82276c7c5..84ff4a26e 100644 --- a/src/app/screens/sendNft/index.tsx +++ b/src/app/screens/sendNft/index.tsx @@ -29,7 +29,6 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; - padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` diff --git a/src/app/screens/sendOrdinal/index.tsx b/src/app/screens/sendOrdinal/index.tsx index c90fe40b0..1fceae6c6 100644 --- a/src/app/screens/sendOrdinal/index.tsx +++ b/src/app/screens/sendOrdinal/index.tsx @@ -30,7 +30,6 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; - padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` diff --git a/src/app/screens/sendRareSat/index.tsx b/src/app/screens/sendRareSat/index.tsx index 33571dd29..c8c20d76d 100644 --- a/src/app/screens/sendRareSat/index.tsx +++ b/src/app/screens/sendRareSat/index.tsx @@ -29,7 +29,6 @@ const Container = styled.div` flex-direction: column; justify-content: space-between; flex-grow: 1; - padding: 0 ${(props) => props.theme.space.m}; `; const StyledSendTo = styled(StyledHeading)` From c6af900470a2f058df88d4c1ef36361816dd4d56 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Thu, 30 Nov 2023 15:36:02 +0800 Subject: [PATCH 25/28] chore: remove mock data and code --- .../ordinals/tempAddressRareSatsMock.ts | 613 ------------------ .../queries/ordinals/useAddressRareSats.ts | 57 +- 2 files changed, 1 insertion(+), 669 deletions(-) delete mode 100644 src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts diff --git a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts b/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts deleted file mode 100644 index 39a3684a6..000000000 --- a/src/app/hooks/queries/ordinals/tempAddressRareSatsMock.ts +++ /dev/null @@ -1,613 +0,0 @@ -import { AddressBundleResponse, UtxoBundleResponse } from '@secretkeylabs/xverse-core'; - -export const inscriptionPartOfBundle: UtxoBundleResponse = { - block_height: 803128, - txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', - value: 100, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 10, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000001', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 11, - offset: 1, - range: { - start: '34234320000003', - end: '34234320000004', - }, - satributes: [], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067474, - }, - ], - }, - ], - xVersion: 1, -}; - -export const exoticInscriptionNotPartOfBundle: UtxoBundleResponse = { - block_height: 803128, - txid: 'b143d94bb084eb429c3d3d4e8ebc9ee7b6a070a3b9b1a92849fe4059f8c2da09', - value: 1, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 10, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000001', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [ - { - content_type: 'text/html', - id: 'b143d94bb084eb429c3d3d4e8ebc9ee7b6a070a3b9b1a92849fe4059f8c2da09i0', - inscription_number: 32218693, - }, - ], - }, - ], - xVersion: 1, -}; - -export const mockData: AddressBundleResponse = { - xVersion: 1, - limit: 30, - offset: 0, - total: 1, - results: [ - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c7', - value: 21000, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320010000', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 10000, - range: { - start: '34234320010001', - end: '34234320010002', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [ - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141212, - }, - ], - }, - { - year_mined: 2009, - block: 9, - offset: 10002, - range: { - start: '34234320010002', - end: '34234320020000', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 20001, - range: { - start: '45000000001', - end: '45000000999', - }, - satributes: ['BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], - inscriptions: [], - }, - ], - }, - ], -}; - -// TestCase 1 - Empty response -export const mockTestCase1: AddressBundleResponse = { - xVersion: 1, - limit: 30, - offset: 0, - total: 0, - results: [], -}; - -// TestCase 3 - 6 bundles -const { xVersion, ...bundle } = inscriptionPartOfBundle; -export const mockTestCase3: AddressBundleResponse = { - xVersion: 1, - limit: 30, - offset: 0, - total: 6, - results: [ - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c7', - value: 20997, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320010000', - }, - satributes: ['RARE', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 10000, - range: { - start: '34234320010001', - end: '34234320010002', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [ - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141212, - }, - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141213, - }, - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141214, - }, - ], - }, - { - year_mined: 2009, - block: 9, - offset: 10002, - range: { - start: '34234320010002', - end: '34234320020000', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 20001, - range: { - start: '45000000001', - end: '45000000999', - }, - satributes: ['BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], - inscriptions: [], - }, - ], - }, - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c8', - value: 21000, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320010000', - }, - satributes: ['MYTHIC'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 10000, - range: { - start: '34234320010001', - end: '34234320010002', - }, - satributes: ['PIZZA', 'BLOCK78', 'BLOCK9', 'NAKAMOTO', 'VINTAGE', 'FIRST_TRANSACTION'], - inscriptions: [ - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141212, - }, - ], - }, - { - year_mined: 2009, - block: 9, - offset: 10002, - range: { - start: '34234320010002', - end: '34234320020000', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 20001, - range: { - start: '45000000001', - end: '45000000999', - }, - satributes: ['BLOCK9', 'NAKAMOTO'], - inscriptions: [], - }, - ], - }, - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314c9', - value: 21000, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 3, - range: { - start: '34234320010001', - end: '34234320010002', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [ - { - content_type: 'text/plain;charset=utf-8', - id: '09c094c3f1ab71c9be7a356a0f1af21b0e552c18d50372fd3799430c890ef135i0', - inscription_number: 123141212, - }, - ], - }, - { - year_mined: 2009, - block: 9, - offset: 4, - range: { - start: '34234320010002', - end: '34234320010003', - }, - satributes: [ - 'HITMAN', - 'NAME_PALINDROME', - 'NAKAMOTO', - 'VINTAGE', - 'FIRST_TRANSACTION', - '2D_PALINDROME', - 'BLOCK78', - 'BLOCK9', - ], - inscriptions: [], - }, - ], - }, - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d1', - value: 100, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME', 'BLOCK9_450', 'VINTAGE', 'SILK_ROAD'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['UNCOMMON', 'PIZZA', 'PALINDROME'], - inscriptions: [], - }, - ], - }, - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d1', - value: 100, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['UNCOMMON'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['NAKAMOTO'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['SILK_ROAD'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['SEQUENCE_PALINDROME'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['PERFECT_PALINCEPTION'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['VINTAGE'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 9, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000003', - }, - satributes: ['MYTHIC'], - inscriptions: [], - }, - ], - }, - bundle, - { - block_height: 803128, - txid: 'f5aa0649f2e5d0c6402c2d6b64ba6ea89e8be836a2ad01cbb0cdcc8721e314d2', - value: 100, - vout: 0, - sat_ranges: [], - }, - ], -}; - -// TestCase 4 - 4 bundles with unsupported types -export const mockTestCase4: AddressBundleResponse = { - xVersion: 1, - limit: 30, - offset: 0, - total: 5, - results: [ - { - block_height: 803128, - txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', - value: 10, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 11, - offset: 1, - range: { - start: '34234320000003', - end: '34234320000004', - }, - satributes: ['1D_PALINDROME', '2D_PALINDROME', 'BLOCK9_450'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 11, - offset: 2, - range: { - start: '34234320000003', - end: '34234320000004', - }, - satributes: ['PIZZA', 'BLOCK9_450'], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067475, - }, - ], - }, - { - year_mined: 2009, - block: 10, - offset: 0, - range: { - start: '34234320000000', - end: '34234320000001', - }, - satributes: ['BLOCK9_450'], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067474, - }, - ], - }, - { - year_mined: 2009, - block: 11, - offset: 3, - range: { - start: '34234320000004', - end: '34234320000005', - }, - satributes: ['BLOCK9_450'], - inscriptions: [], - }, - ], - }, - { - block_height: 803128, - txid: 'b8f8aee03af313ef1fbba7316aadf7390c91dc5dd34928a15f708ea4ed642852', - value: 10, - vout: 0, - sat_ranges: [ - { - year_mined: 2009, - block: 11, - offset: 0, - range: { - start: '34234320000003', - end: '34234320000004', - }, - satributes: ['EPIC', '1D_PALINDROME', '2D_PALINDROME', 'BLOCK9_450', 'VINTAGE'], - inscriptions: [], - }, - { - year_mined: 2009, - block: 11, - offset: 1, - range: { - start: '34234320000003', - end: '34234320000004', - }, - satributes: ['PIZZA', 'BLOCK9_450'], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067475, - }, - ], - }, - { - year_mined: 2009, - block: 10, - offset: 2, - range: { - start: '34234320000000', - end: '34234320000001', - }, - satributes: ['BLOCK9_450', 'BLOCK78', 'FIBONACCI'], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067474, - }, - ], - }, - { - year_mined: 2009, - block: 10, - offset: 3, - range: { - start: '34234320000000', - end: '34234320000001', - }, - satributes: ['BLOCK9_450', 'BLOCK78', 'FIBONACCI', 'BLACK_EPIC'], - inscriptions: [ - { - content_type: 'image/png', - id: '6b186d467d817e4d086a9d1bf93785d736df6431c1cc9c305571161d616d05d0i0', - inscription_number: 11067473, - }, - ], - }, - { - year_mined: 2009, - block: 11, - offset: 4, - range: { - start: '34234320000004', - end: '34234320000005', - }, - satributes: ['BLOCK9_450'], - inscriptions: [], - }, - ], - }, - ], -}; diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 6c588956e..1e4cec5c8 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -6,14 +6,6 @@ import { } from '@secretkeylabs/xverse-core'; import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; import { handleRetries, InvalidParamsError } from '@utils/query'; -import { - exoticInscriptionNotPartOfBundle, - inscriptionPartOfBundle, - mockData, - mockTestCase1, - mockTestCase3, - mockTestCase4, -} from './tempAddressRareSatsMock'; const PAGE_SIZE = 30; @@ -25,41 +17,9 @@ export const useAddressRareSats = () => { throw new InvalidParamsError('ordinalsAddress is required'); } - // custom ordinal address takes precedence over mocks - const customOrdinalAddress = localStorage.getItem('ordinalAddress'); - const useProdApi = localStorage.getItem('useProdApi'); - - if (!(useProdApi || customOrdinalAddress)) { - // EMPTY RESPONSE - const testcase1 = localStorage.getItem('testcase1'); - if (testcase1) { - return mockTestCase1; - } - - // ERROR RESPONSE - const testcase2 = localStorage.getItem('testcase2'); - if (testcase2) { - throw new Error('Error response from API'); - } - - // 6 bundles with different combinations of sats and inscriptions - const testcase3 = localStorage.getItem('testcase3'); - if (testcase3) { - return mockTestCase3; - } - - // 2 bundles with different combinations of sats and inscriptions but with unsupported types - const testcase4 = localStorage.getItem('testcase4'); - if (testcase4) { - return mockTestCase4; - } - - return mockData; - } - const bundleResponse = await getAddressUtxoOrdinalBundles( network.type, - customOrdinalAddress ?? ordinalsAddress, + ordinalsAddress, pageParam, PAGE_SIZE, { @@ -93,21 +53,6 @@ export const useGetUtxoOrdinalBundle = ( throw new InvalidParamsError('output is required'); } - const customOrdinalAddress = localStorage.getItem('ordinalAddress'); - const useProdApi = localStorage.getItem('useProdApi'); - if (!(useProdApi || customOrdinalAddress)) { - if (output === `${inscriptionPartOfBundle.txid}:${inscriptionPartOfBundle.vout}`) { - return inscriptionPartOfBundle; - } - - if ( - output === - `${exoticInscriptionNotPartOfBundle.txid}:${exoticInscriptionNotPartOfBundle.vout}` - ) { - return exoticInscriptionNotPartOfBundle; - } - } - const [txid, vout] = output.split(':'); const bundleResponse = await getUtxoOrdinalBundle(network.type, txid, parseInt(vout, 10)); return bundleResponse; From c57c861b6852ffd3357e7cefd1cd6449d94c9f10 Mon Sep 17 00:00:00 2001 From: fede erbes Date: Thu, 30 Nov 2023 08:55:02 +0100 Subject: [PATCH 26/28] fix: restore cache key --- src/app/hooks/queries/ordinals/useAddressRareSats.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/hooks/queries/ordinals/useAddressRareSats.ts b/src/app/hooks/queries/ordinals/useAddressRareSats.ts index 1e4cec5c8..3e21ff647 100644 --- a/src/app/hooks/queries/ordinals/useAddressRareSats.ts +++ b/src/app/hooks/queries/ordinals/useAddressRareSats.ts @@ -60,7 +60,7 @@ export const useGetUtxoOrdinalBundle = ( const { data, isLoading } = useQuery({ enabled: !!(output && shouldMakeTheCall), - queryKey: ['rare-sats', output], + queryKey: ['rare-sats', output, network.type], queryFn: getUtxoOrdinalBundleByOutput, retry: handleRetries, staleTime: 1 * 60 * 1000, // 1 min From 93d0c6fec9d62613bc819edd607e9925a9137249 Mon Sep 17 00:00:00 2001 From: Abdul Haseeb Date: Thu, 30 Nov 2023 13:00:33 +0500 Subject: [PATCH 27/28] fix: UI --- .../confirmBtcTransactionComponent/index.tsx | 4 ---- src/app/layouts/sendLayout.tsx | 13 ++++++++++--- src/app/screens/confirmBtcTransaction/index.tsx | 11 +++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/app/components/confirmBtcTransactionComponent/index.tsx b/src/app/components/confirmBtcTransactionComponent/index.tsx index 514682181..6cf5e32e4 100644 --- a/src/app/components/confirmBtcTransactionComponent/index.tsx +++ b/src/app/components/confirmBtcTransactionComponent/index.tsx @@ -50,8 +50,6 @@ const Container = styled.div((props) => ({ flexDirection: 'column', flex: 1, marginTop: props.theme.spacing(11), - marginLeft: props.theme.space.m, - marginRight: props.theme.space.m, })); interface ButtonProps { @@ -62,8 +60,6 @@ const ButtonContainer = styled.div((props) => ({ display: 'flex', flexDirection: 'row', position: 'relative', - marginLeft: props.theme.space.m, - marginRight: props.theme.space.m, marginBottom: props.isBtcSendBrowserTx ? props.theme.spacing(20) : props.theme.spacing(5), })); diff --git a/src/app/layouts/sendLayout.tsx b/src/app/layouts/sendLayout.tsx index ca5c1b417..dc5ca3537 100644 --- a/src/app/layouts/sendLayout.tsx +++ b/src/app/layouts/sendLayout.tsx @@ -8,6 +8,10 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { breakpoints, devices } from 'theme'; +interface ContainerProps { + isGallery?: boolean; +} + const ScrollContainer = styled.div((props) => ({ display: 'flex', flex: 1, @@ -15,7 +19,7 @@ const ScrollContainer = styled.div((props) => ({ ...props.theme.scrollbar, })); -const Container = styled.div` +const Container = styled.div` display: flex; flex-direction: column; margin: auto; @@ -31,7 +35,9 @@ const Container = styled.div` max-width: 588px; border: 1px solid ${(props) => props.theme.colors.elevation3}; border-radius: ${(props) => props.theme.space.s}; - padding: ${(props) => props.theme.space.l} 0; + padding-top: ${(props) => props.theme.space.l}; + padding-left: ${(props) => (props.isGallery ? props.theme.space.m : 0)}; + padding-right: ${(props) => (props.isGallery ? props.theme.space.m : 0)}; padding-bottom: ${(props) => props.theme.space.xxl}; margin-top: ${(props) => props.theme.space.xxxxl}; } @@ -67,6 +73,7 @@ function SendLayout({ const { t } = useTranslation('translation', { keyPrefix: 'SEND' }); const isScreenLargerThanXs = document.documentElement.clientWidth > Number(breakpoints.xs); const year = new Date().getFullYear(); + const isGalleryOpen: boolean = document.documentElement.clientWidth > 360; return ( <> @@ -76,7 +83,7 @@ function SendLayout({ )} - + {isScreenLargerThanXs && !hideBackButton && onClickBack && (