From a7b25f80f5b6f4a0b80d67287fc32b8b03eec36c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:54:16 +0100 Subject: [PATCH 1/5] build(deps): bump react-dom and @types/react-dom (#1053) Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) and [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom). These dependencies needed to be updated together. Updates `react-dom` from 18.2.0 to 18.3.1 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react-dom) Updates `@types/react-dom` from 18.2.18 to 18.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) --- updated-dependencies: - dependency-name: react-dom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: "@types/react-dom" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 68 +++++++++++++++++++++++------------------------ package.json | 4 +-- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index e96dbbaf..b0643166 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "micro-aes-gcm": "0.3.3", "qrcode.react": "^3.1.0", "react": "^18.2.0", - "react-dom": "^18.0.2", + "react-dom": "^18.3.1", "react-hook-form": "7.48.2", "react-i18next": "14.1.0", "react-infinite-scroll-hook": "^4.1.1", @@ -82,7 +82,7 @@ "@types/md5": "^2.3.5", "@types/node": "^20.9.0", "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.18", + "@types/react-dom": "^18.3.0", "@types/react-virtualized": "^9.21.30", "@types/styled-components": "^5.1.26", "@typescript-eslint/parser": "^5.62.0", @@ -7484,9 +7484,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", - "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "devOptional": true, "dependencies": { "@types/react": "*" @@ -24356,23 +24356,15 @@ } }, "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==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "dependencies": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-dom/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" + "react": "^18.3.1" } }, "node_modules/react-fast-compare": { @@ -25501,6 +25493,14 @@ "integrity": "sha512-MgUIvuca+90fBrCWY5LdlU9YUWjlkPFwdpvmomcwQEu3t2id/6YHdG2nhB6o7nhRp4ocfmcXQTh00r/tJtynSg==", "dev": true }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", @@ -35363,9 +35363,9 @@ } }, "@types/react-dom": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", - "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "devOptional": true, "requires": { "@types/react": "*" @@ -48009,22 +48009,12 @@ } }, "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==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "requires": { "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "dependencies": { - "scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "requires": { - "loose-envify": "^1.1.0" - } - } + "scheduler": "^0.23.2" } }, "react-fast-compare": { @@ -48869,6 +48859,14 @@ "integrity": "sha512-MgUIvuca+90fBrCWY5LdlU9YUWjlkPFwdpvmomcwQEu3t2id/6YHdG2nhB6o7nhRp4ocfmcXQTh00r/tJtynSg==", "dev": true }, + "scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "requires": { + "loose-envify": "^1.1.0" + } + }, "schema-utils": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", diff --git a/package.json b/package.json index cdf25862..a65352a2 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "micro-aes-gcm": "0.3.3", "qrcode.react": "^3.1.0", "react": "^18.2.0", - "react-dom": "^18.0.2", + "react-dom": "^18.3.1", "react-hook-form": "7.48.2", "react-i18next": "14.1.0", "react-infinite-scroll-hook": "^4.1.1", @@ -126,7 +126,7 @@ "@types/md5": "^2.3.5", "@types/node": "^20.9.0", "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.18", + "@types/react-dom": "^18.3.0", "@types/react-virtualized": "^9.21.30", "@types/styled-components": "^5.1.26", "@typescript-eslint/parser": "^5.62.0", From 206dc965faf7de2bc47a2d05a847d3defc74520b Mon Sep 17 00:00:00 2001 From: Ostap Piatkovskyi <44294945+ost-ptk@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:00:09 +0200 Subject: [PATCH 2/5] fix: fix account balances fetching (#1068) * update account balances fetching * fix issues with balances and update playwright --- package-lock.json | 62 ++++---- package.json | 4 +- src/apps/onboarding/index.tsx | 10 +- .../select-accounts-to-recover/content.tsx | 36 +---- .../select-accounts-to-recover/index.tsx | 95 +++++-------- src/apps/popup/pages/all-accounts/content.tsx | 14 ++ src/apps/popup/pages/buy-cspr/country.tsx | 12 +- .../components/account-list-item.tsx | 38 +++-- .../pages/download-account-keys/download.tsx | 31 +++- .../components/account-balance/amount-bar.tsx | 29 ++-- .../components/account-balance/amount-row.tsx | 45 ++---- .../home/components/account-balance/index.tsx | 42 +++--- .../connected-ledger.tsx | 69 +++------ .../pages/import-account-from-ledger/types.ts | 4 +- src/apps/popup/pages/receive/content.tsx | 14 +- src/apps/popup/pages/stakes/amount-step.tsx | 32 ++--- src/apps/popup/pages/stakes/confirm-step.tsx | 16 ++- src/apps/popup/pages/stakes/index.tsx | 10 +- src/apps/popup/pages/transfer-nft/index.tsx | 11 +- .../popup/pages/transfer-nft/review-step.tsx | 8 +- src/apps/popup/pages/transfer/amount-step.tsx | 29 ++-- .../popup/pages/transfer/confirm-step.tsx | 25 ++-- src/apps/popup/pages/transfer/index.tsx | 2 +- src/apps/popup/pages/transfer/token-step.tsx | 4 +- src/background/index.ts | 62 -------- .../redux/account-balances/actions.ts | 11 -- .../redux/account-balances/reducer.ts | 13 -- .../redux/account-balances/selectors.ts | 4 - .../redux/account-balances/types.ts | 3 - src/background/redux/account-info/actions.ts | 9 -- src/background/redux/account-info/reducer.ts | 21 --- .../redux/account-info/selectors.ts | 6 - src/background/redux/account-info/types.ts | 3 - src/background/redux/get-main-store.ts | 1 - src/background/redux/redux-action.ts | 2 - src/background/redux/root-reducer.ts | 2 - src/background/redux/sagas/vault-sagas.ts | 2 - src/background/redux/types.d.ts | 2 - src/background/redux/vault/selectors.ts | 64 +++------ src/background/service-message.ts | 20 --- src/background/wallet-repositories.ts | 5 +- src/fixtures/initial-state-for-popup-tests.ts | 9 -- src/hooks/use-casper-token.ts | 42 ++---- src/hooks/use-fetch-account-balances.ts | 60 -------- src/hooks/use-fetch-active-account-balance.ts | 93 ------------ .../layout/header/header-data-updater.tsx | 7 +- .../header/header-submenu-bar-nav-link.tsx | 28 ++-- .../balance-service/balance-service.ts | 132 ------------------ .../services/balance-service/constants.ts | 28 +--- src/libs/services/balance-service/index.ts | 5 +- src/libs/services/balance-service/queries.ts | 68 +++++++++ src/libs/services/balance-service/types.ts | 25 ---- .../use-fetch-accounts-balances.ts | 28 ++++ .../use-fetch-wallet-balance.ts | 123 ++++++++++++++++ src/libs/services/deployer-service/index.ts | 8 +- src/libs/types/account.ts | 8 +- .../account-list/account-list-item.tsx | 19 +-- .../components/account-list/account-list.tsx | 8 ++ src/libs/ui/components/account-list/utils.ts | 4 +- .../active-account-plate.tsx | 8 +- .../dynamic-accounts-list-with-select.tsx | 28 ++-- .../components/my-accounts-list.tsx | 4 +- .../transaction-fee-plate.tsx | 8 +- src/libs/ui/forms/create-account.ts | 4 +- src/libs/ui/forms/form-validation-rules.ts | 25 ++-- src/libs/ui/forms/stakes-form.ts | 2 +- src/libs/ui/forms/transfer-nft.ts | 2 +- src/libs/ui/forms/transfer.ts | 2 +- 68 files changed, 636 insertions(+), 1014 deletions(-) delete mode 100644 src/background/redux/account-balances/actions.ts delete mode 100644 src/background/redux/account-balances/reducer.ts delete mode 100644 src/background/redux/account-balances/selectors.ts delete mode 100644 src/background/redux/account-balances/types.ts delete mode 100644 src/hooks/use-fetch-account-balances.ts delete mode 100644 src/hooks/use-fetch-active-account-balance.ts delete mode 100644 src/libs/services/balance-service/balance-service.ts create mode 100644 src/libs/services/balance-service/queries.ts delete mode 100644 src/libs/services/balance-service/types.ts create mode 100644 src/libs/services/balance-service/use-fetch-accounts-balances.ts create mode 100644 src/libs/services/balance-service/use-fetch-wallet-balance.ts diff --git a/package-lock.json b/package-lock.json index b0643166..e59c9331 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "big.js": "^6.2.1", "casper-cep18-js-client": "1.0.2", "casper-js-sdk": "2.15.4", - "casper-wallet-core": "git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.5", + "casper-wallet-core": "git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.6", "date-fns": "^2.30.0", "i18next": "^23.11.0", "i18next-browser-languagedetector": "^7.2.1", @@ -66,7 +66,7 @@ "@babel/preset-env": "7.23.2", "@babel/preset-react": "7.18.6", "@babel/preset-typescript": "^7.23.3", - "@playwright/test": "^1.39.0", + "@playwright/test": "^1.47.2", "@redux-devtools/cli": "^4.0.0", "@redux-devtools/remote": "^0.9.3", "@testing-library/dom": "9.3.4", @@ -4996,18 +4996,18 @@ "dev": true }, "node_modules/@playwright/test": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", - "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", "dev": true, "dependencies": { - "playwright": "1.39.0" + "playwright": "1.47.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@pnpm/network.ca-file": { @@ -10601,8 +10601,8 @@ }, "node_modules/casper-wallet-core": { "name": "CasperWalletCore", - "version": "0.9.5", - "resolved": "git+ssh://git@github.com/make-software/casper-wallet-core.git#9d91ccbec58b1bd5c94a6d5dd658503a2fa1ce4c", + "version": "0.9.6", + "resolved": "git+ssh://git@github.com/make-software/casper-wallet-core.git#cef8e4ffb029396095993f020d19d472db3c4d02", "dependencies": { "@make-software/ces-js-parser": "^1.3.3", "@react-native/typescript-config": "0.74.83", @@ -23711,33 +23711,33 @@ } }, "node_modules/playwright": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", - "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", "dev": true, "dependencies": { - "playwright-core": "1.39.0" + "playwright-core": "1.47.2" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", - "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", "dev": true, "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/possible-typed-array-names": { @@ -33328,12 +33328,12 @@ } }, "@playwright/test": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", - "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", + "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", "dev": true, "requires": { - "playwright": "1.39.0" + "playwright": "1.47.2" } }, "@pnpm/network.ca-file": { @@ -37770,8 +37770,8 @@ } }, "casper-wallet-core": { - "version": "git+ssh://git@github.com/make-software/casper-wallet-core.git#9d91ccbec58b1bd5c94a6d5dd658503a2fa1ce4c", - "from": "casper-wallet-core@git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.5", + "version": "git+ssh://git@github.com/make-software/casper-wallet-core.git#cef8e4ffb029396095993f020d19d472db3c4d02", + "from": "casper-wallet-core@git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.6", "requires": { "@make-software/ces-js-parser": "^1.3.3", "@react-native/typescript-config": "0.74.83", @@ -47536,19 +47536,19 @@ } }, "playwright": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", - "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.39.0" + "playwright-core": "1.47.2" } }, "playwright-core": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", - "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", "dev": true }, "possible-typed-array-names": { diff --git a/package.json b/package.json index a65352a2..54646437 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "big.js": "^6.2.1", "casper-cep18-js-client": "1.0.2", "casper-js-sdk": "2.15.4", - "casper-wallet-core": "git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.5", + "casper-wallet-core": "git+ssh://git@github.com:make-software/casper-wallet-core.git#v0.9.6", "date-fns": "^2.30.0", "i18next": "^23.11.0", "i18next-browser-languagedetector": "^7.2.1", @@ -110,7 +110,7 @@ "@babel/preset-env": "7.23.2", "@babel/preset-react": "7.18.6", "@babel/preset-typescript": "^7.23.3", - "@playwright/test": "^1.39.0", + "@playwright/test": "^1.47.2", "@redux-devtools/cli": "^4.0.0", "@redux-devtools/remote": "^0.9.3", "@testing-library/dom": "9.3.4", diff --git a/src/apps/onboarding/index.tsx b/src/apps/onboarding/index.tsx index a245e07a..6775baf4 100644 --- a/src/apps/onboarding/index.tsx +++ b/src/apps/onboarding/index.tsx @@ -1,3 +1,4 @@ +import { QueryClientProvider } from '@tanstack/react-query'; import React, { Suspense, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Provider as ReduxProvider } from 'react-redux'; @@ -14,6 +15,7 @@ import { onboardingAppInit } from '@background/redux/windowManagement/actions'; import '@libs/i18n/i18n'; import { ErrorBoundary } from '@libs/layout'; +import { newQueryClient } from '@libs/services/query-client'; import { GlobalStyle, lightTheme } from '@libs/ui'; const Tree = () => { @@ -37,9 +39,11 @@ const Tree = () => { - - - + + + + + diff --git a/src/apps/onboarding/pages/select-accounts-to-recover/content.tsx b/src/apps/onboarding/pages/select-accounts-to-recover/content.tsx index d80b0b79..d0384d4d 100644 --- a/src/apps/onboarding/pages/select-accounts-to-recover/content.tsx +++ b/src/apps/onboarding/pages/select-accounts-to-recover/content.tsx @@ -1,5 +1,5 @@ import { Player } from '@lottiefiles/react-lottie-player'; -import React, { SetStateAction } from 'react'; +import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -13,12 +13,7 @@ import { TabPageContainer, VerticalSpaceContainer } from '@libs/layout'; -import { AccountListRows } from '@libs/types/account'; -import { - DynamicAccountsListWithSelect, - Tile, - Typography -} from '@libs/ui/components'; +import { Tile, Typography } from '@libs/ui/components'; const AnimationContainer = styled(CenteredFlexColumn)` padding: 106px 16px; @@ -26,24 +21,12 @@ const AnimationContainer = styled(CenteredFlexColumn)` interface SelectAccountsToRecoverContentProps { isLoading: boolean; - derivedAccountsWithBalance: AccountListRows[]; - isLoadingMore: boolean; - onLoadMore: () => void; - maxItemsToRender: number; - setSelectedAccounts: React.Dispatch>; - selectedAccounts: AccountListRows[]; - setIsButtonDisabled: React.Dispatch>; + children: React.ReactNode; } export const SelectAccountsToRecoverContent = ({ isLoading, - isLoadingMore, - onLoadMore, - derivedAccountsWithBalance, - maxItemsToRender, - setSelectedAccounts, - selectedAccounts, - setIsButtonDisabled + children }: SelectAccountsToRecoverContentProps) => { const { t } = useTranslation(); const isDarkMode = useIsDarkMode(); @@ -90,16 +73,7 @@ export const SelectAccountsToRecoverContent = ({ ) : ( - + children )} ); diff --git a/src/apps/onboarding/pages/select-accounts-to-recover/index.tsx b/src/apps/onboarding/pages/select-accounts-to-recover/index.tsx index ea1250ca..12f36406 100644 --- a/src/apps/onboarding/pages/select-accounts-to-recover/index.tsx +++ b/src/apps/onboarding/pages/select-accounts-to-recover/index.tsx @@ -1,8 +1,5 @@ import React, { useEffect, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { isEqualCaseInsensitive } from '@src/utils'; import { Stepper } from '@onboarding/components/stepper'; import { SelectAccountsToRecoverContent } from '@onboarding/pages/select-accounts-to-recover/content'; @@ -15,7 +12,6 @@ import { import { closeActiveTab } from '@onboarding/utils/close-active-tab'; import { recoverVault } from '@background/redux/sagas/actions'; -import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; import { dispatchToMainStore } from '@background/redux/utils'; import { getAccountHashFromPublicKey } from '@libs/entities/Account'; @@ -25,9 +21,9 @@ import { TabFooterContainer, TabHeaderContainer } from '@libs/layout'; -import { dispatchFetchAccountBalances } from '@libs/services/balance-service'; +import { useFetchAccountsBalances } from '@libs/services/balance-service'; import { Account, AccountListRows, KeyPair } from '@libs/types/account'; -import { Button } from '@libs/ui/components'; +import { Button, DynamicAccountsListWithSelect } from '@libs/ui/components'; export const SelectAccountsToRecoverPage = () => { const [derivedAccounts, setDerivedAccounts] = useState([]); @@ -47,10 +43,6 @@ export const SelectAccountsToRecoverPage = () => { const { t } = useTranslation(); const location = useTypedLocation(); - const { casperWalletApiUrl } = useSelector( - selectApiConfigBasedOnActiveNetwork - ); - useEffect(() => { if (location.state?.secretPhrase) { const keyPairs = getKeyPairList({ @@ -63,49 +55,31 @@ export const SelectAccountsToRecoverPage = () => { } }, [location.state?.secretPhrase, setDerivedAccounts]); - useEffect(() => { - if (!derivedAccounts.length) return; + const accountHashes = derivedAccounts.map(account => + getAccountHashFromPublicKey(account.publicKey) + ); - const hashes = derivedAccounts.reduce( - (previousValue, currentValue, currentIndex) => { - const hash = getAccountHashFromPublicKey(currentValue.publicKey); + const { accountsBalances, isLoadingBalances } = + useFetchAccountsBalances(accountHashes); - return derivedAccounts.length === currentIndex + 1 - ? previousValue + `${hash}` - : previousValue + `${hash},`; - }, - '' + useEffect(() => { + if (!derivedAccounts.length || isLoadingBalances) return; + + const derivedAccountsWithBalance: AccountListRows[] = derivedAccounts.map( + (account, index) => ({ + ...account, + id: account.publicKey, + hidden: false, + derivationIndex: index, + name: '' + }) ); - dispatchFetchAccountBalances(hashes) - .then(({ payload }) => { - if ('data' in payload) { - const derivedAccountsWithBalance: AccountListRows[] = - derivedAccounts.map((account, index) => { - const accountWithBalance = payload.data.find(ac => - isEqualCaseInsensitive(ac.public_key, account.publicKey) - ); - - return { - ...account, - id: account.publicKey, - hidden: false, - derivationIndex: index, - name: '', - balance: { - liquidMotes: `${accountWithBalance?.balance ?? '0'}` - } - }; - }); - - setDerivedAccountsWithBalance(derivedAccountsWithBalance); - } - }) - .finally(() => { - setIsLoading(false); - setIsLoadingMore(false); - }); - }, [derivedAccounts, casperWalletApiUrl]); + setDerivedAccountsWithBalance(derivedAccountsWithBalance); + + setIsLoading(false); + setIsLoadingMore(false); + }, [accountsBalances, derivedAccounts, isLoadingBalances]); const onLoadMore = () => { try { @@ -156,16 +130,19 @@ export const SelectAccountsToRecoverPage = () => { )} renderContent={() => ( - + + + )} renderFooter={() => ( diff --git a/src/apps/popup/pages/all-accounts/content.tsx b/src/apps/popup/pages/all-accounts/content.tsx index 9898508c..6155aa31 100644 --- a/src/apps/popup/pages/all-accounts/content.tsx +++ b/src/apps/popup/pages/all-accounts/content.tsx @@ -13,6 +13,7 @@ import { import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { ContentContainer, SpacingSize } from '@libs/layout'; import { useFetchAccountsInfo } from '@libs/services/account-info'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { AccountListRowWithAccountHash, AccountListRows @@ -39,6 +40,7 @@ export const AllAccountsContent = () => { const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); + const { accountsBalances, isLoadingBalance } = useFetchWalletBalance(); useEffect(() => { const visibleAccountListRows = sortAccounts( @@ -79,6 +81,10 @@ export const AllAccountsContent = () => { const isConnected = connectedAccountNames.includes(account.name); const isActiveAccount = activeAccountName === account.name; + const accountLiquidBalance = + accountsBalances && + accountsBalances[account.accountHash]?.liquidBalance; + return ( { isConnected={isConnected} showHideAccountItem accountsInfo={accountsInfo} + accountLiquidBalance={accountLiquidBalance} + isLoadingBalance={isLoadingBalance} /> ); }} @@ -100,6 +108,10 @@ export const AllAccountsContent = () => { renderRow={account => { const isConnected = connectedAccountNames.includes(account.name); + const accountLiquidBalance = + accountsBalances && + accountsBalances[account.accountHash]?.liquidBalance; + return ( { isConnected={isConnected} showHideAccountItem accountsInfo={accountsInfo} + accountLiquidBalance={accountLiquidBalance} + isLoadingBalance={isLoadingBalance} /> ); }} diff --git a/src/apps/popup/pages/buy-cspr/country.tsx b/src/apps/popup/pages/buy-cspr/country.tsx index 7bf56450..87cb8c7d 100644 --- a/src/apps/popup/pages/buy-cspr/country.tsx +++ b/src/apps/popup/pages/buy-cspr/country.tsx @@ -1,9 +1,6 @@ import React, { useEffect, useState } from 'react'; import { useForm, useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { selectAccountBalance } from '@background/redux/account-info/selectors'; import { ContentContainer, @@ -11,6 +8,7 @@ import { ParagraphContainer, SpacingSize } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { ResponseCountryPropsWithId } from '@libs/services/buy-cspr-service/types'; import { ActiveAccountPlate, @@ -21,7 +19,6 @@ import { SvgIcon, Typography } from '@libs/ui/components'; -import { motesToCSPR } from '@libs/ui/utils'; import { CountryRow } from './components/country-row'; import { ListRow } from './components/list-row'; @@ -45,10 +42,7 @@ export const Country = ({ >([]); const { t } = useTranslation(); - const csprBalance = useSelector(selectAccountBalance); - - const balance = - csprBalance.liquidMotes && motesToCSPR(csprBalance.liquidMotes); + const { accountBalance } = useFetchWalletBalance(); const { register, control, setValue } = useForm(); @@ -79,7 +73,7 @@ export const Country = ({ diff --git a/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx b/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx index 39ea860d..29300b1e 100644 --- a/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx +++ b/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx @@ -1,3 +1,4 @@ +import { IAccountInfo } from 'casper-wallet-core/src/domain/accountInfo'; import React from 'react'; import styled from 'styled-components'; @@ -6,7 +7,11 @@ import { FlexColumn, SpacingSize } from '@libs/layout'; -import { AccountListRows, HardwareWalletType } from '@libs/types/account'; +import { + AccountListRowWithAccountHash, + AccountListRows, + HardwareWalletType +} from '@libs/types/account'; import { Avatar, Checkbox, @@ -37,11 +42,13 @@ const AccountName = styled(Typography)` `; interface AccountListItemProps { - account: AccountListRows; + account: AccountListRowWithAccountHash; onClick: (event: React.MouseEvent) => void; isConnected: boolean; isActiveAccount: boolean; isSelected?: boolean; + accountsInfo: Record | undefined; + accountLiquidBalance: string | undefined; } export const AccountListItem = ({ @@ -49,14 +56,19 @@ export const AccountListItem = ({ onClick, isActiveAccount, isConnected, - isSelected + isSelected, + accountsInfo, + accountLiquidBalance }: AccountListItemProps) => { - const accountBalance = - account.balance?.liquidMotes != null - ? formatNumber(motesToCSPR(account.balance.liquidMotes), { - precision: { max: 0 } - }) - : '-'; + const accountBalance = accountLiquidBalance + ? formatNumber(motesToCSPR(accountLiquidBalance), { + precision: { max: 0 } + }) + : '0'; + + const csprName = accountsInfo && accountsInfo[account.accountHash]?.csprName; + const brandingLogo = + accountsInfo && accountsInfo[account.accountHash]?.brandingLogo; return ( @@ -68,23 +80,21 @@ export const AccountListItem = ({ isConnected={isConnected} displayContext="accountList" isActiveAccount={isActiveAccount} + brandingLogo={brandingLogo} /> {account.name} - + {accountBalance} { - const [accountsWithId, setAccountsWithId] = useState([]); + const [accountsWithId, setAccountsWithId] = useState< + AccountListRowWithAccountHash[] + >([]); const { t } = useTranslation(); - // TODO: update this when the ledger feature is ready, to not allow the download of the ledger accounts - const accounts = useSelector(selectVaultAccountsWithBalances); + const accounts = useSelector(selectVaultAccountsExceptLedgersAccounts); const connectedAccountNames = useSelector(selectConnectedAccountNamesWithActiveOrigin) || []; const activeAccountName = useSelector(selectVaultActiveAccountName); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); + + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); + const { accountsBalances } = useFetchWalletBalance(); useEffect(() => { const accountsWithId = accounts.map(account => ({ ...account, - id: account.name + id: account.name, + accountHash: getAccountHashFromPublicKey(account.publicKey) })); setAccountsWithId(accountsWithId); @@ -99,6 +112,10 @@ export const Download = ({ const isSelected = selectedAccounts.findIndex(acc => acc.id === account.id) !== -1; + const accountLiquidBalance = + accountsBalances && + accountsBalances[account.accountHash]?.liquidBalance; + return ( toggleAccount(account)} isSelected={isSelected} + accountLiquidBalance={accountLiquidBalance} + accountsInfo={accountsInfo} /> ); }} diff --git a/src/apps/popup/pages/home/components/account-balance/amount-bar.tsx b/src/apps/popup/pages/home/components/account-balance/amount-bar.tsx index 63b85965..a0c55706 100644 --- a/src/apps/popup/pages/home/components/account-balance/amount-bar.tsx +++ b/src/apps/popup/pages/home/components/account-balance/amount-bar.tsx @@ -1,10 +1,8 @@ import React, { useMemo } from 'react'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; -import { selectAccountBalance } from '@background/redux/account-info/selectors'; - import { FlexRow, SpacingSize } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { ContentColor, getColorFromTheme, motesToCSPR } from '@libs/ui/utils'; const Container = styled(FlexRow)` @@ -20,8 +18,8 @@ const Filled = styled.div<{ filledWidth: number; color: ContentColor }>` `; function calculateLiquidPercentage( - amountMotes: string | null, - fullBalanceMotes: string | null + amountMotes: string | undefined, + fullBalanceMotes: string | undefined ) { if (amountMotes != null && fullBalanceMotes != null) { const current = Number(motesToCSPR(amountMotes)); @@ -34,28 +32,31 @@ function calculateLiquidPercentage( } export const AmountBar = () => { - const balance = useSelector(selectAccountBalance); + const { accountBalance } = useFetchWalletBalance(); const liquidPercentage = useMemo( () => - calculateLiquidPercentage(balance.liquidMotes, balance.totalBalanceMotes), - [balance.liquidMotes, balance.totalBalanceMotes] + calculateLiquidPercentage( + accountBalance.liquidBalance, + accountBalance.totalBalance + ), + [accountBalance.liquidBalance, accountBalance.totalBalance] ); const delegatedPercentage = useMemo( () => calculateLiquidPercentage( - balance.delegatedMotes, - balance.totalBalanceMotes + accountBalance.delegatedBalance, + accountBalance.totalBalance ), - [balance.delegatedMotes, balance.totalBalanceMotes] + [accountBalance.delegatedBalance, accountBalance.totalBalance] ); const undelegatingPercentage = useMemo( () => calculateLiquidPercentage( - balance.undelegatingMotes, - balance.totalBalanceMotes + accountBalance.undelegatingBalance, + accountBalance.totalBalance ), - [balance.undelegatingMotes, balance.totalBalanceMotes] + [accountBalance.undelegatingBalance, accountBalance.totalBalance] ); return ( diff --git a/src/apps/popup/pages/home/components/account-balance/amount-row.tsx b/src/apps/popup/pages/home/components/account-balance/amount-row.tsx index 9160dbb5..410c4afe 100644 --- a/src/apps/popup/pages/home/components/account-balance/amount-row.tsx +++ b/src/apps/popup/pages/home/components/account-balance/amount-row.tsx @@ -1,61 +1,42 @@ import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { selectAccountCurrencyRate } from '@background/redux/account-info/selectors'; import { AlignedSpaceBetweenFlexRow, FlexRow, SpacingSize } from '@libs/layout'; import { Typography } from '@libs/ui/components'; -import { - ContentColor, - formatCurrency, - formatNumber, - motesToCSPR, - motesToCurrency -} from '@libs/ui/utils'; +import { ContentColor } from '@libs/ui/utils'; interface AmountRowProps { text: string; - amountMotes: string | null; + fiatAmount: string | undefined; + amountFormattedDecimalBalance: string | undefined; color: ContentColor; showFiatAmounts: boolean; } export const AmountRow = ({ text, - amountMotes, + fiatAmount, + amountFormattedDecimalBalance, color, showFiatAmounts }: AmountRowProps) => { const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); - - const fiatAmount = - currencyRate != null && amountMotes != null - ? formatCurrency( - motesToCurrency(String(amountMotes), currencyRate), - 'USD', - { - precision: 2 - } - ) - : ''; - return ( {text} {showFiatAmounts ? ( - {fiatAmount} + + {fiatAmount} + ) : ( - - {amountMotes == null - ? '-' - : formatNumber(motesToCSPR(amountMotes), { - precision: { max: 5 } - })} + + {amountFormattedDecimalBalance} CSPR diff --git a/src/apps/popup/pages/home/components/account-balance/index.tsx b/src/apps/popup/pages/home/components/account-balance/index.tsx index ddc5dd09..89cdf5a1 100644 --- a/src/apps/popup/pages/home/components/account-balance/index.tsx +++ b/src/apps/popup/pages/home/components/account-balance/index.tsx @@ -1,13 +1,10 @@ import React, { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; -import { selectAccountBalance } from '@background/redux/account-info/selectors'; - import { FlexColumn, FlexRow, SpacingSize } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Typography, getFontSizeBasedOnTextLength } from '@libs/ui/components'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils'; import { AmountBar } from './amount-bar'; import { AmountRow } from './amount-row'; @@ -20,7 +17,7 @@ export const AccountBalance = () => { const [showFiatAmounts, setShowFiatAmounts] = useState(false); const { t } = useTranslation(); - const balance = useSelector(selectAccountBalance); + const { accountBalance } = useFetchWalletBalance(); return ( @@ -28,30 +25,26 @@ export const AccountBalance = () => { Total balance ยท - {balance.totalBalanceFiat} + {accountBalance.totalFormattedFiatBalance} - {balance.totalBalanceMotes == null - ? '-' - : formatNumber(motesToCSPR(balance.totalBalanceMotes), { - precision: { max: 5 } - })} + {accountBalance?.totalFormattedDecimalBalance} CSPR @@ -67,21 +60,30 @@ export const AccountBalance = () => { > - {balance.undelegatingMotes !== '0' && - balance.undelegatingMotes != null && ( + {accountBalance?.undelegatingBalance && + accountBalance?.undelegatingBalance !== '0' && ( diff --git a/src/apps/popup/pages/import-account-from-ledger/connected-ledger.tsx b/src/apps/popup/pages/import-account-from-ledger/connected-ledger.tsx index b08952d8..2b83073b 100644 --- a/src/apps/popup/pages/import-account-from-ledger/connected-ledger.tsx +++ b/src/apps/popup/pages/import-account-from-ledger/connected-ledger.tsx @@ -1,14 +1,10 @@ import { Player } from '@lottiefiles/react-lottie-player'; import React, { useEffect, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; -import { isEqualCaseInsensitive } from '@src/utils'; - import { RouterPath, useTypedNavigate } from '@popup/router'; -import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; import { dispatchToMainStore } from '@background/redux/utils'; import { accountsImported } from '@background/redux/vault/actions'; @@ -28,7 +24,7 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; -import { dispatchFetchAccountBalances } from '@libs/services/balance-service'; +import { useFetchAccountsBalances } from '@libs/services/balance-service'; import { LedgerAccount, LedgerEventStatus, @@ -73,10 +69,6 @@ export const ConnectedLedger: React.FC = ({ const navigate = useTypedNavigate(); const isDarkMode = useIsDarkMode(); - const { casperWalletApiUrl } = useSelector( - selectApiConfigBasedOnActiveNetwork - ); - useEffect(() => { ledger.getAccountList({ size: 5, offset: 0 }); }, []); @@ -93,48 +85,30 @@ export const ConnectedLedger: React.FC = ({ return () => sub.unsubscribe(); }, []); - useEffect(() => { - if (!accountsFromLedger.length) return; + const accountHashes = accountsFromLedger.map(account => + getAccountHashFromPublicKey(account.publicKey) + ); - const hashes = accountsFromLedger.reduce( - (previousValue, currentValue, currentIndex) => { - const hash = getAccountHashFromPublicKey(currentValue.publicKey); + const { accountsBalances, isLoadingBalances } = + useFetchAccountsBalances(accountHashes); - return accountsFromLedger.length === currentIndex + 1 - ? previousValue + `${hash}` - : previousValue + `${hash},`; - }, - '' + useEffect(() => { + if (!accountsFromLedger.length || isLoadingBalances) return; + + const accountsWithBalance = accountsFromLedger.map( + account => ({ + publicKey: account.publicKey, + derivationIndex: account.index, + name: '', + id: account.publicKey + }) ); - dispatchFetchAccountBalances(hashes) - .then(({ payload }) => { - if ('data' in payload) { - const accountsWithBalance = - accountsFromLedger.map(account => { - const accountWithBalance = payload.data.find(ac => - isEqualCaseInsensitive(ac.public_key, account.publicKey) - ); - - return { - publicKey: account.publicKey, - derivationIndex: account.index, - name: '', - id: account.publicKey, - balance: { - liquidMotes: `${accountWithBalance?.balance ?? '0'}` - } - }; - }); - - setLedgerAccountsWithBalance(accountsWithBalance); - } - }) - .finally(() => { - setIsLoading(false); - setIsLoadingMore(false); - }); - }, [casperWalletApiUrl, accountsFromLedger]); + setLedgerAccountsWithBalance(accountsWithBalance); + + setIsLoading(false); + setIsLoadingMore(false); + }, [accountsBalances, accountsFromLedger, isLoadingBalances]); const onSubmit = () => { const accounts: Account[] = selectedAccounts.map(account => ({ @@ -232,6 +206,7 @@ export const ConnectedLedger: React.FC = ({ onLoadMore={onLoadMore} isLoadingMore={isLoadingMore} namePrefix="Ledger account" + accountsBalances={accountsBalances} /> )} diff --git a/src/apps/popup/pages/import-account-from-ledger/types.ts b/src/apps/popup/pages/import-account-from-ledger/types.ts index bae38cb3..9bf6d14d 100644 --- a/src/apps/popup/pages/import-account-from-ledger/types.ts +++ b/src/apps/popup/pages/import-account-from-ledger/types.ts @@ -1,6 +1,6 @@ -import { AccountWithBalance } from '@libs/types/account'; +import { Account } from '@libs/types/account'; export type ILedgerAccountListItem = Omit< - AccountWithBalance, + Account, 'hidden' | 'secretKey' | 'imported' | 'hardware' > & { id: string }; diff --git a/src/apps/popup/pages/receive/content.tsx b/src/apps/popup/pages/receive/content.tsx index 55bd830b..1aa80318 100644 --- a/src/apps/popup/pages/receive/content.tsx +++ b/src/apps/popup/pages/receive/content.tsx @@ -7,10 +7,7 @@ import styled from 'styled-components'; import { formatErc20TokenBalance } from '@popup/pages/home/components/tokens-list/utils'; import { useTypedLocation } from '@popup/router'; -import { - selectAccountBalance, - selectErc20Tokens -} from '@background/redux/account-info/selectors'; +import { selectErc20Tokens } from '@background/redux/account-info/selectors'; import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; import { useCopyToClipboard } from '@hooks/use-copy-to-clipboard'; @@ -22,6 +19,7 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { ActiveAccountPlate, Tile, Typography } from '@libs/ui/components'; import { motesToCSPR } from '@libs/ui/utils'; @@ -57,13 +55,15 @@ export const ReceivePageContent = () => { symbol: location?.state?.tokenData?.symbol ?? '' }); - const csprBalance = useSelector(selectAccountBalance, shallowEqual); const tokens = useSelector(selectErc20Tokens, shallowEqual); + const { accountBalance } = useFetchWalletBalance(); + useEffect(() => { if (tokenData?.symbol === 'CSPR') { const balance = - (csprBalance.liquidMotes && motesToCSPR(csprBalance.liquidMotes)) || + (accountBalance.liquidBalance && + motesToCSPR(accountBalance.liquidBalance)) || '0'; setTokenData(prev => ({ ...prev, balance })); } else { @@ -72,7 +72,7 @@ export const ReceivePageContent = () => { erc20Tokens?.find(t => t?.symbol === tokenData?.symbol)?.amount ?? '0'; setTokenData(prev => ({ ...prev, balance })); } - }, [csprBalance.liquidMotes, tokenData?.symbol, tokens]); + }, [accountBalance.liquidBalance, tokenData?.symbol, tokens]); return ( diff --git a/src/apps/popup/pages/stakes/amount-step.tsx b/src/apps/popup/pages/stakes/amount-step.tsx index 204dbe3e..5ae05f39 100644 --- a/src/apps/popup/pages/stakes/amount-step.tsx +++ b/src/apps/popup/pages/stakes/amount-step.tsx @@ -2,7 +2,6 @@ import Big from 'big.js'; import React, { useEffect, useState } from 'react'; import { UseFormReturn, useWatch } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { @@ -11,17 +10,13 @@ import { STAKE_COST_MOTES } from '@src/constants'; -import { - selectAccountBalance, - selectAccountCurrencyRate -} from '@background/redux/account-info/selectors'; - import { AlignedFlexRow, ParagraphContainer, SpacingSize, VerticalSpaceContainer } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Error, Input, Typography } from '@libs/ui/components'; import { StakeAmountFormValues } from '@libs/ui/forms/stakes-form'; import { @@ -54,22 +49,20 @@ export const AmountStep = ({ const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); - const csprBalance = useSelector(selectAccountBalance); + const { accountBalance, currencyRate } = useFetchWalletBalance(); useEffect(() => { switch (stakeType) { case AuctionManagerEntryPoint.delegate: { - const maxAmountMotes: string = - csprBalance.liquidMotes == null - ? '0' - : Big(csprBalance.liquidMotes).sub(STAKE_COST_MOTES).toFixed(); + const maxAmountMotes: string = !accountBalance.liquidBalance + ? '0' + : Big(accountBalance.liquidBalance).sub(STAKE_COST_MOTES).toFixed(); const minAmount = Big(STAKE_COST_MOTES) .add(DELEGATION_MIN_AMOUNT_MOTES) .toFixed(); const hasEnoughBalance = - csprBalance.liquidMotes != null && - Big(csprBalance.liquidMotes).gte(minAmount); + accountBalance.liquidBalance && + Big(accountBalance.liquidBalance).gte(minAmount); setDisabled(!hasEnoughBalance); @@ -79,14 +72,14 @@ export const AmountStep = ({ case AuctionManagerEntryPoint.undelegate: case AuctionManagerEntryPoint.redelegate: { const hasEnoughBalance = - csprBalance.liquidMotes != null && - Big(csprBalance.liquidMotes).gte(STAKE_COST_MOTES); + accountBalance.liquidBalance && + Big(accountBalance.liquidBalance).gte(STAKE_COST_MOTES); setDisabled(!hasEnoughBalance); setMaxAmountMotes(stakeAmountMotes); } } - }, [csprBalance.liquidMotes, stakeAmountMotes, stakeType]); + }, [accountBalance.liquidBalance, stakeAmountMotes, stakeType]); const { register, @@ -103,7 +96,10 @@ export const AmountStep = ({ const amountLabel = t('Amount'); - const fiatAmount = formatFiatAmount(amount || '0', currencyRate); + const fiatAmount = formatFiatAmount( + amount || '0', + currencyRate?.rate || null + ); return ( <> diff --git a/src/apps/popup/pages/stakes/confirm-step.tsx b/src/apps/popup/pages/stakes/confirm-step.tsx index c2aad3e2..11497a18 100644 --- a/src/apps/popup/pages/stakes/confirm-step.tsx +++ b/src/apps/popup/pages/stakes/confirm-step.tsx @@ -1,13 +1,10 @@ import Big from 'big.js'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { AuctionManagerEntryPoint } from '@src/constants'; -import { selectAccountCurrencyRate } from '@background/redux/account-info/selectors'; - import { AmountContainer, ParagraphContainer, @@ -15,6 +12,7 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { getAuctionManagerDeployCost } from '@libs/services/deployer-service'; import { ValidatorResult } from '@libs/services/validators-service/types'; import { List, Typography, ValidatorPlate } from '@libs/ui/components'; @@ -40,7 +38,7 @@ export const ConfirmStep = ({ }: ConfirmStepProps) => { const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); + const { currencyRate } = useFetchWalletBalance(); const transferFeeMotes = getAuctionManagerDeployCost(stakeType); @@ -58,14 +56,18 @@ export const ConfirmStep = ({ amount: formatNumber(inputAmountCSPR, { precision: { max: 5 } }), - fiatPrice: formatFiatAmount(inputAmountCSPR, currencyRate), + fiatPrice: formatFiatAmount(inputAmountCSPR, currencyRate?.rate || null), symbol: 'CSPR' }, { id: 2, text: t('Transaction fee'), amount: transferCostInCSPR, - fiatPrice: formatFiatAmount(transferCostInCSPR, currencyRate, 3), + fiatPrice: formatFiatAmount( + transferCostInCSPR, + currencyRate?.rate || null, + 3 + ), symbol: 'CSPR' }, { @@ -74,7 +76,7 @@ export const ConfirmStep = ({ amount: formatNumber(totalCSPR, { precision: { max: 5 } }), - fiatPrice: formatFiatAmount(totalCSPR, currencyRate), + fiatPrice: formatFiatAmount(totalCSPR, currencyRate?.rate || null), symbol: 'CSPR', bold: true } diff --git a/src/apps/popup/pages/stakes/index.tsx b/src/apps/popup/pages/stakes/index.tsx index bb1b32d6..3b485048 100644 --- a/src/apps/popup/pages/stakes/index.tsx +++ b/src/apps/popup/pages/stakes/index.tsx @@ -24,7 +24,6 @@ import { ValidatorDropdownInput } from '@popup/pages/stakes/validator-dropdown-i import { RouterPath, useTypedNavigate } from '@popup/router'; import { accountPendingDeployHashesChanged } from '@background/redux/account-info/actions'; -import { selectAccountBalance } from '@background/redux/account-info/selectors'; import { ledgerDeployChanged } from '@background/redux/ledger/actions'; import { selectAskForReviewAfter, @@ -55,6 +54,7 @@ import { VerticalSpaceContainer, createErrorLocationState } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { makeAuctionManagerDeploy, sendSignDeploy, @@ -111,13 +111,14 @@ export const StakesPage = () => { const { networkName, nodeUrl, auctionManagerContractHash } = useSelector( selectApiConfigBasedOnActiveNetwork ); - const csprBalance = useSelector(selectAccountBalance); const ratedInStore = useSelector(selectRatedInStore); const askForReviewAfter = useSelector(selectAskForReviewAfter); const { t } = useTranslation(); const navigate = useTypedNavigate(); + const { accountBalance } = useFetchWalletBalance(); + const { stakeType, validatorList, undelegateValidatorList, loading } = useStakeType(); @@ -130,7 +131,7 @@ export const StakesPage = () => { ); const { amountForm, validatorForm, newValidatorForm } = useStakesForm( - csprBalance.liquidMotes, + accountBalance.liquidBalance, stakeType, stakeAmountMotes, validator?.delegators_number, @@ -538,7 +539,8 @@ export const StakesPage = () => { if ( (stakeType === AuctionManagerEntryPoint.undelegate || stakeType === AuctionManagerEntryPoint.redelegate) && - (csprBalance.delegatedMotes == null || csprBalance.delegatedMotes === '0') + (!accountBalance.delegatedBalance || + accountBalance.delegatedBalance === '0') ) { return ( { const { contractPackageHash, tokenId } = useParams(); const nftTokens = useSelector(selectAccountNftTokens); - const csprBalance = useSelector(selectAccountBalance); const activeAccount = useSelector(selectVaultActiveAccount); const isActiveAccountFromLedger = useSelector( selectIsActiveAccountFromLedger @@ -99,6 +96,8 @@ export const TransferNftPage = () => { const ratedInStore = useSelector(selectRatedInStore); const askForReviewAfter = useSelector(selectAskForReviewAfter); + const { accountBalance } = useFetchWalletBalance(); + const { t } = useTranslation(); const navigate = useTypedNavigate(); const location = useTypedLocation(); @@ -137,7 +136,7 @@ export const TransferNftPage = () => { ); const { recipientForm, amountForm } = useTransferNftForm( - csprBalance.liquidMotes, + accountBalance.liquidBalance, defaultPaymentAmount ); diff --git a/src/apps/popup/pages/transfer-nft/review-step.tsx b/src/apps/popup/pages/transfer-nft/review-step.tsx index aa22224c..3f6e2a6b 100644 --- a/src/apps/popup/pages/transfer-nft/review-step.tsx +++ b/src/apps/popup/pages/transfer-nft/review-step.tsx @@ -1,9 +1,6 @@ import React from 'react'; import { UseFormReturn, useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { selectAccountCurrencyRate } from '@background/redux/account-info/selectors'; import { ContentContainer, @@ -11,6 +8,7 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { NFTTokenResult } from '@libs/services/nft-service'; import { Input, Typography } from '@libs/ui/components'; import { TransferNftAmountFormValues } from '@libs/ui/forms/transfer-nft'; @@ -34,7 +32,7 @@ export const ReviewStep = ({ }: ReviewStepProps) => { const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); + const { currencyRate } = useFetchWalletBalance(); const { register, @@ -49,7 +47,7 @@ export const ReviewStep = ({ const paymentFiatAmount = formatFiatAmount( paymentAmount || '0', - currencyRate + currencyRate?.rate || null ); return ( diff --git a/src/apps/popup/pages/transfer/amount-step.tsx b/src/apps/popup/pages/transfer/amount-step.tsx index f1d38627..1a8c132b 100644 --- a/src/apps/popup/pages/transfer/amount-step.tsx +++ b/src/apps/popup/pages/transfer/amount-step.tsx @@ -6,10 +6,6 @@ import { useSelector } from 'react-redux'; import { TRANSFER_COST_MOTES, TRANSFER_MIN_AMOUNT_MOTES } from '@src/constants'; -import { - selectAccountBalance, - selectAccountCurrencyRate -} from '@background/redux/account-info/selectors'; import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; @@ -21,6 +17,7 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Error, Input, Typography } from '@libs/ui/components'; import { TransactionFeePlate } from '@libs/ui/components/transaction-fee-plate/transaction-fee-plate'; import { calculateSubmitButtonDisabled } from '@libs/ui/forms/get-submit-button-state-from-validation'; @@ -56,11 +53,11 @@ export const AmountStep = ({ const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); - const csprBalance = useSelector(selectAccountBalance); const activeAccount = useSelector(selectVaultActiveAccount); const { networkName } = useSelector(selectApiConfigBasedOnActiveNetwork); + const { accountBalance, currencyRate } = useFetchWalletBalance(); + const erc20Balance = (selectedToken?.balance && divideErc20Balance( @@ -72,22 +69,21 @@ export const AmountStep = ({ const amountForm = useTransferAmountForm( erc20Balance, isErc20Transfer, - csprBalance.liquidMotes, + accountBalance.liquidBalance, paymentAmount, selectedToken?.decimals ); useEffect(() => { - const maxAmountMotes: string = - csprBalance.liquidMotes == null - ? '0' - : Big(csprBalance.liquidMotes).sub(TRANSFER_COST_MOTES).toFixed(); + const maxAmountMotes: string = !accountBalance.liquidBalance + ? '0' + : Big(accountBalance.liquidBalance).sub(TRANSFER_COST_MOTES).toFixed(); const hasEnoughBalance = Big(maxAmountMotes).gte(TRANSFER_MIN_AMOUNT_MOTES); setMaxAmountMotes(maxAmountMotes); setDisabled(!hasEnoughBalance); - }, [csprBalance.liquidMotes]); + }, [accountBalance.liquidBalance]); useEffect(() => { if (!isErc20Transfer) { @@ -109,7 +105,7 @@ export const AmountStep = ({ trigger, formState.touchedFields.amount, selectedToken?.amount, - csprBalance.liquidMotes, + accountBalance.liquidBalance, paymentAmount ]); @@ -131,10 +127,13 @@ export const AmountStep = ({ const transferIdLabel = t('Transfer ID (memo)'); const paymentAmoutLabel = t('Set custom transaction fee'); const fiatAmount = !isErc20Transfer - ? formatFiatAmount(amount || '0', currencyRate) + ? formatFiatAmount(amount || '0', currencyRate?.rate || null) : undefined; const paymentFiatAmount = isErc20Transfer - ? formatFiatAmount(paymentAmountFieldValue || '0', currencyRate) + ? formatFiatAmount( + paymentAmountFieldValue || '0', + currencyRate?.rate || null + ) : undefined; useEffect(() => { diff --git a/src/apps/popup/pages/transfer/confirm-step.tsx b/src/apps/popup/pages/transfer/confirm-step.tsx index 76543f2b..5a2719c2 100644 --- a/src/apps/popup/pages/transfer/confirm-step.tsx +++ b/src/apps/popup/pages/transfer/confirm-step.tsx @@ -1,13 +1,10 @@ import Big from 'big.js'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { TRANSFER_COST_MOTES } from '@src/constants'; -import { selectAccountCurrencyRate } from '@background/redux/account-info/selectors'; - import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { AmountContainer, @@ -18,6 +15,7 @@ import { VerticalSpaceContainer } from '@libs/layout'; import { useFetchAccountsInfo } from '@libs/services/account-info'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { ActiveAccountPlate, List, @@ -33,7 +31,7 @@ const ListItemContainer = styled(SpaceBetweenFlexRow)` interface ConfirmStepProps { recipientPublicKey: string; amount: string; - balance: string | null; + balance: string | undefined; symbol: string | null; isErc20Transfer: boolean; paymentAmount: string; @@ -50,8 +48,7 @@ export const ConfirmStep = ({ }: ConfirmStepProps) => { const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); - + const { currencyRate } = useFetchWalletBalance(); const accountsInfo = useFetchAccountsInfo([recipientPublicKey]); const accountHash = getAccountHashFromPublicKey(recipientPublicKey); @@ -74,14 +71,18 @@ export const ConfirmStep = ({ amount: formatNumber(amount, { precision: { max: 5 } }), - fiatPrice: formatFiatAmount(amount, currencyRate), + fiatPrice: formatFiatAmount(amount, currencyRate?.rate || null), symbol }, { id: 2, text: t('Transaction fee'), amount: transferCostInCSPR, - fiatPrice: formatFiatAmount(transferCostInCSPR, currencyRate, 3), + fiatPrice: formatFiatAmount( + transferCostInCSPR, + currencyRate?.rate || null, + 3 + ), symbol }, { @@ -90,7 +91,7 @@ export const ConfirmStep = ({ amount: formatNumber(totalCSPR, { precision: { max: 5 } }), - fiatPrice: formatFiatAmount(totalCSPR, currencyRate), + fiatPrice: formatFiatAmount(totalCSPR, currencyRate?.rate || null), symbol, bold: true } @@ -112,7 +113,11 @@ export const ConfirmStep = ({ amount: formatNumber(paymentAmount, { precision: { max: 5 } }), - fiatPrice: formatFiatAmount(paymentAmount, currencyRate, 3), + fiatPrice: formatFiatAmount( + paymentAmount, + currencyRate?.rate || null, + 3 + ), symbol: 'CSPR' } ]; diff --git a/src/apps/popup/pages/transfer/index.tsx b/src/apps/popup/pages/transfer/index.tsx index 5ccb09ec..e8ab1827 100644 --- a/src/apps/popup/pages/transfer/index.tsx +++ b/src/apps/popup/pages/transfer/index.tsx @@ -336,7 +336,7 @@ export const TransferPage = () => { @@ -117,7 +117,7 @@ export const TokenStep = ({ diff --git a/src/background/index.ts b/src/background/index.ts index e924f940..efdeb037 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -29,12 +29,6 @@ import { openOnboardingUi } from '@background/open-onboarding-flow'; import { - accountBalancesChanged, - accountBalancesReseted -} from '@background/redux/account-balances/actions'; -import { - accountBalanceChanged, - accountCurrencyRateChanged, accountErc20Changed, accountInfoReset, accountNftTokensAdded, @@ -110,11 +104,6 @@ import { sdkEvent } from '@content/sdk-event'; import { SdkMethod, isSDKMethod, sdkMethod } from '@content/sdk-method'; import { fetchExtendedDeploysInfo } from '@libs/services/account-activity-service'; -import { - fetchAccountBalance, - fetchAccountBalances, - fetchCurrencyRate -} from '@libs/services/balance-service'; import { fetchOnRampOptionGet, fetchOnRampOptionPost, @@ -608,8 +597,6 @@ runtime.onMessage.addListener( case getType(loginRetryLockoutTimeSet): case getType(recipientPublicKeyAdded): case getType(recipientPublicKeyReseted): - case getType(accountBalanceChanged): - case getType(accountCurrencyRateChanged): case getType(accountInfoReset): case getType(accountPendingDeployHashesChanged): case getType(accountPendingDeployHashesRemove): @@ -626,8 +613,6 @@ runtime.onMessage.addListener( case getType(contactsReseted): case getType(ratedInStoreChanged): case getType(askForReviewAfterChanged): - case getType(accountBalancesChanged): - case getType(accountBalancesReseted): case getType(ledgerNewWindowIdChanged): case getType(ledgerStateCleared): case getType(ledgerDeployChanged): @@ -642,53 +627,6 @@ runtime.onMessage.addListener( return; // SERVICE MESSAGE HANDLERS - case getType(serviceMessage.fetchBalanceRequest): { - const { casperWalletApiUrl, casperClarityApiUrl } = - selectApiConfigBasedOnActiveNetwork(store.getState()); - - try { - const [accountData, rate] = await Promise.all([ - fetchAccountBalance({ - accountHash: action.payload.accountHash, - casperWalletApiUrl - }), - fetchCurrencyRate({ casperClarityApiUrl }) - ]); - - return sendResponse( - serviceMessage.fetchBalanceResponse({ - accountData: accountData?.data || null, - currencyRate: rate?.data || null - }) - ); - } catch (error) { - console.error(error); - } - - return; - } - - case getType(serviceMessage.fetchAccountBalancesRequest): { - const { casperWalletApiUrl } = selectApiConfigBasedOnActiveNetwork( - store.getState() - ); - - try { - const data = await fetchAccountBalances({ - accountHashes: action.payload.accountHashes, - casperWalletApiUrl - }); - - return sendResponse( - serviceMessage.fetchAccountBalancesResponse(data) - ); - } catch (error) { - console.error(error); - } - - return; - } - case getType(serviceMessage.fetchExtendedDeploysInfoRequest): { const { casperClarityApiUrl } = selectApiConfigBasedOnActiveNetwork( store.getState() diff --git a/src/background/redux/account-balances/actions.ts b/src/background/redux/account-balances/actions.ts deleted file mode 100644 index e4926b17..00000000 --- a/src/background/redux/account-balances/actions.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createAction } from 'typesafe-actions'; - -import { AccountData } from '@libs/services/balance-service/types'; - -export const accountBalancesChanged = createAction('ACCOUNT_BALANCES_CHANGED')< - AccountData[] ->(); - -export const accountBalancesReseted = createAction( - 'ACCOUNT_BALANCES_RESETED' -)(); diff --git a/src/background/redux/account-balances/reducer.ts b/src/background/redux/account-balances/reducer.ts deleted file mode 100644 index 044e2af7..00000000 --- a/src/background/redux/account-balances/reducer.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createReducer } from 'typesafe-actions'; - -import { accountBalancesChanged, accountBalancesReseted } from './actions'; -import { AccountBalancesState } from './types'; - -const initialState = [] as AccountBalancesState; - -export const reducer = createReducer(initialState) - .handleAction(accountBalancesReseted, () => initialState) - .handleAction( - accountBalancesChanged, - (state, action: ReturnType) => action.payload - ); diff --git a/src/background/redux/account-balances/selectors.ts b/src/background/redux/account-balances/selectors.ts deleted file mode 100644 index fcd06127..00000000 --- a/src/background/redux/account-balances/selectors.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { RootState } from 'typesafe-actions'; - -export const selectAccountBalances = (state: RootState) => - state.accountBalances; diff --git a/src/background/redux/account-balances/types.ts b/src/background/redux/account-balances/types.ts deleted file mode 100644 index f97a24ed..00000000 --- a/src/background/redux/account-balances/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { AccountData } from '@libs/services/balance-service/types'; - -export type AccountBalancesState = AccountData[]; diff --git a/src/background/redux/account-info/actions.ts b/src/background/redux/account-info/actions.ts index 8e7e3f6c..c58b29a4 100644 --- a/src/background/redux/account-info/actions.ts +++ b/src/background/redux/account-info/actions.ts @@ -1,21 +1,12 @@ import { createAction } from 'typesafe-actions'; -import { AccountBalance } from '@libs/services/balance-service/types'; import { ContractPackageWithBalance } from '@libs/services/erc20-service/types'; import { NFTTokenResult } from '@libs/services/nft-service/types'; -export const accountBalanceChanged = createAction( - 'ACCOUNT_BALANCE_CHANGED' -)(); - export const accountErc20Changed = createAction('ACCOUNT_ERC20_CHANGED')< ContractPackageWithBalance[] >(); -export const accountCurrencyRateChanged = createAction( - 'ACCOUNT_CURRENCY_RATE_CHANGED' -)(); - export const accountInfoReset = createAction('ACCOUNT_INFO_RESET')(); export const accountPendingDeployHashesChanged = createAction( diff --git a/src/background/redux/account-info/reducer.ts b/src/background/redux/account-info/reducer.ts index 9eb129de..888a13fb 100644 --- a/src/background/redux/account-info/reducer.ts +++ b/src/background/redux/account-info/reducer.ts @@ -3,8 +3,6 @@ import { createReducer } from 'typesafe-actions'; import { isEqualCaseInsensitive } from '@src/utils'; import { - accountBalanceChanged, - accountCurrencyRateChanged, accountErc20Changed, accountInfoReset, accountNftTokensAdded, @@ -18,14 +16,6 @@ import { import { AccountInfoState } from './types'; const initialState: AccountInfoState = { - balance: { - liquidMotes: null, - delegatedMotes: null, - undelegatingMotes: null, - totalBalanceMotes: null, - totalBalanceFiat: null - }, - currencyRate: null, pendingDeployHashes: [], erc20Tokens: [], accountNftTokens: [], @@ -35,17 +25,6 @@ const initialState: AccountInfoState = { export const reducer = createReducer(initialState) .handleAction(accountInfoReset, () => initialState) - .handleAction(accountBalanceChanged, (state, { payload }) => ({ - ...state, - balance: payload - })) - .handleAction( - accountCurrencyRateChanged, - (state, { payload }): AccountInfoState => ({ - ...state, - currencyRate: payload - }) - ) .handleAction( accountErc20Changed, (state, { payload }): AccountInfoState => ({ diff --git a/src/background/redux/account-info/selectors.ts b/src/background/redux/account-info/selectors.ts index 6008be84..c1680794 100644 --- a/src/background/redux/account-info/selectors.ts +++ b/src/background/redux/account-info/selectors.ts @@ -1,11 +1,5 @@ import { RootState } from 'typesafe-actions'; -export const selectAccountBalance = (state: RootState) => - state.accountInfo.balance; - -export const selectAccountCurrencyRate = (state: RootState) => - state.accountInfo.currencyRate; - export const selectPendingDeployHashes = (state: RootState) => state.accountInfo.pendingDeployHashes; diff --git a/src/background/redux/account-info/types.ts b/src/background/redux/account-info/types.ts index 6d0d3ab1..b9586c51 100644 --- a/src/background/redux/account-info/types.ts +++ b/src/background/redux/account-info/types.ts @@ -1,11 +1,8 @@ -import { AccountBalance } from '@libs/services/balance-service'; import { ContractPackageWithBalance } from '@libs/services/erc20-service'; import { NFTTokenResult } from '@libs/services/nft-service'; export interface AccountInfoState { - balance: AccountBalance; erc20Tokens: ContractPackageWithBalance[]; - currencyRate: number | null; pendingDeployHashes: string[]; accountNftTokens: NFTTokenResult[] | null; nftTokensCount: number; diff --git a/src/background/redux/get-main-store.ts b/src/background/redux/get-main-store.ts index f79f7c56..33e8eb8a 100644 --- a/src/background/redux/get-main-store.ts +++ b/src/background/redux/get-main-store.ts @@ -58,7 +58,6 @@ export const selectPopupState = (state: RootState): PopupState => { accountInfo: state.accountInfo, contacts: state.contacts, rateApp: state.rateApp, - accountBalances: state.accountBalances, ledger: state.ledger, promotion: state.promotion }; diff --git a/src/background/redux/redux-action.ts b/src/background/redux/redux-action.ts index 7ddc20f6..48a26050 100644 --- a/src/background/redux/redux-action.ts +++ b/src/background/redux/redux-action.ts @@ -1,6 +1,5 @@ import { ActionType } from 'typesafe-actions'; -import * as accountBalances from './account-balances/actions'; import * as accountInfo from './account-info/actions'; import * as activeOrigin from './active-origin/actions'; import * as contacts from './contacts/actions'; @@ -35,7 +34,6 @@ const reduxAction = { accountInfo, contacts, rateApp, - accountBalances, ledger, promotion }; diff --git a/src/background/redux/root-reducer.ts b/src/background/redux/root-reducer.ts index d3d6a3aa..aea14de0 100644 --- a/src/background/redux/root-reducer.ts +++ b/src/background/redux/root-reducer.ts @@ -1,6 +1,5 @@ import { combineReducers } from 'redux'; -import { reducer as accountBalances } from './account-balances/reducer'; import { reducer as accountInfo } from './account-info/reducer'; import { reducer as activeOrigin } from './active-origin/reducer'; import { reducer as contacts } from './contacts/reducer'; @@ -33,7 +32,6 @@ const rootReducer = combineReducers({ accountInfo, contacts, rateApp, - accountBalances, ledger, promotion }); diff --git a/src/background/redux/sagas/vault-sagas.ts b/src/background/redux/sagas/vault-sagas.ts index 15d8dcee..56764453 100644 --- a/src/background/redux/sagas/vault-sagas.ts +++ b/src/background/redux/sagas/vault-sagas.ts @@ -8,7 +8,6 @@ import { MapTimeoutDurationSettingToValue } from '@popup/constants'; -import { accountBalancesReseted } from '@background/redux/account-balances/actions'; import { loginRetryLockoutTimeReseted, loginRetryLockoutTimeSet @@ -120,7 +119,6 @@ function* lockVaultSaga() { yield put(vaultReseted()); yield put(deploysReseted()); yield put(accountInfoReset()); - yield put(accountBalancesReseted()); emitSdkEventToActiveTabs(() => { return sdkEvent.lockedEvent({ diff --git a/src/background/redux/types.d.ts b/src/background/redux/types.d.ts index efc28c05..a708694c 100644 --- a/src/background/redux/types.d.ts +++ b/src/background/redux/types.d.ts @@ -1,6 +1,5 @@ import { ActionType, StateType } from 'typesafe-actions'; -import { AccountBalancesState } from '@background/redux/account-balances/types'; import { AccountInfoState } from '@background/redux/account-info/types'; import { ActiveOriginState } from '@background/redux/active-origin/types'; import { ContactsState } from '@background/redux/contacts/types'; @@ -50,7 +49,6 @@ export type PopupState = { accountInfo: AccountInfoState; contacts: ContactsState; rateApp: RateAppState; - accountBalances: AccountBalancesState; ledger: LedgerState; promotion: PromotionState; }; diff --git a/src/background/redux/vault/selectors.ts b/src/background/redux/vault/selectors.ts index 1fb36970..09506ead 100644 --- a/src/background/redux/vault/selectors.ts +++ b/src/background/redux/vault/selectors.ts @@ -1,15 +1,10 @@ import { createSelector } from 'reselect'; import { RootState } from 'typesafe-actions'; -import { selectAccountBalances } from '@background/redux/account-balances/selectors'; import { VaultState } from '@background/redux/vault/types'; import { SecretPhrase } from '@libs/crypto'; -import { - Account, - AccountWithBalance, - HardwareWalletType -} from '@libs/types/account'; +import { Account, HardwareWalletType } from '@libs/types/account'; import { selectActiveOrigin } from '../active-origin/selectors'; @@ -27,35 +22,12 @@ export const selectVaultAccounts = (state: RootState): Account[] => export const selectVaultAccountsPublicKeys = (state: RootState): string[] => state.vault.accounts.map(key => key.publicKey); -export const selectVaultAccountsWithBalances = createSelector( - selectVaultAccounts, - selectAccountBalances, - (accounts, accountBalances): AccountWithBalance[] => - accounts.map(account => { - if (!accountBalances.length) { - return { - ...account, - balance: { - liquidMotes: null - } - }; - } - - const accountBalance = accountBalances.find( - ac => ac.public_key === account.publicKey - ); - - return { - ...account, - balance: { - liquidMotes: String(accountBalance?.balance || '0') - } - }; - }) -); +export const selectVaultAccountsExceptLedgersAccounts = ( + state: RootState +): Account[] => state.vault.accounts.filter(account => !account.hardware); export const selectVaultCountsOfAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.length ); @@ -63,12 +35,12 @@ export const selectVaultHasAccounts = (state: RootState): boolean => state.vault.accounts.length > 0; export const selectVaultAccountsNames = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.map(account => account.name) ); export const selectVaultImportedAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.filter(account => account.imported) ); @@ -78,12 +50,12 @@ export const selectVaultImportedAccountNames = createSelector( ); export const selectVaultVisibleAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.filter(account => !account.hidden) ); export const selectVaultHiddenAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.filter(account => account.hidden) ); @@ -98,12 +70,12 @@ export const selectVaultHasImportedAccount = createSelector( ); export const selectVaultDerivedAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.filter(account => !account.imported && !account.hardware) ); export const selectVaultLedgerAccounts = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.filter(account => account.hardware === HardwareWalletType.Ledger) ); @@ -114,12 +86,12 @@ export const selectVaultLedgerAccountNames = createSelector( ); export const selectVaultAccountsSecretKeysBase64 = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, accounts => accounts.map(account => account.secretKey) ); export const selectVaultAccount = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, (_: RootState, accountName: string) => accountName, (accounts, accountName) => accounts.find(account => account.name === accountName) @@ -129,7 +101,7 @@ export const selectVaultActiveAccountName = (state: RootState) => state.vault.activeAccountName; export const selectVaultActiveAccount = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, selectVaultActiveAccountName, (accounts, activeAccountName) => { return accounts.find(account => account.name === activeAccountName); @@ -222,19 +194,19 @@ export const selectConnectedAccountNamesWithActiveOrigin = createSelector( export const selectConnectedAccountsWithActiveOrigin = createSelector( selectActiveOrigin, - selectVaultAccountsWithBalances, + selectVaultAccounts, selectConnectedAccountNamesWithActiveOrigin, - (origin, accounts, connectedAccountNamesWithOrigin): AccountWithBalance[] => { + (origin, accounts, connectedAccountNamesWithOrigin): Account[] => { return (connectedAccountNamesWithOrigin || []) .map(accountName => accounts.find(account => account.name === accountName) ) - .filter((account): account is AccountWithBalance => !!account); + .filter((account): account is Account => !!account); } ); export const selectUnconnectedAccountsWithActiveOrigin = createSelector( - selectVaultAccountsWithBalances, + selectVaultAccounts, selectConnectedAccountsWithActiveOrigin, (accounts, connectedAccountsToActiveTab) => accounts.filter( diff --git a/src/background/service-message.ts b/src/background/service-message.ts index e91c6615..c09f251a 100644 --- a/src/background/service-message.ts +++ b/src/background/service-message.ts @@ -1,10 +1,6 @@ import { IDeploy } from 'casper-wallet-core'; import { ActionType, createAction } from 'typesafe-actions'; -import { - AccountData, - FetchBalanceResponse -} from '@libs/services/balance-service/types'; import { GetOnRampResponse, OptionsPostRequestData, @@ -23,22 +19,6 @@ import { type Meta = void; export const serviceMessage = { - fetchBalanceRequest: createAction('FETCH_ACCOUNT_BALANCE')< - { accountHash: string }, - Meta - >(), - fetchBalanceResponse: createAction('FETCH_ACCOUNT_BALANCE_RESPONSE')< - FetchBalanceResponse, - Meta - >(), - fetchAccountBalancesRequest: createAction('FETCH_ACCOUNT_BALANCES')< - { accountHashes: string }, - Meta - >(), - fetchAccountBalancesResponse: createAction('FETCH_ACCOUNT_BALANCES_RESPONSE')< - PaginatedResponse | ErrorResponse, - Meta - >(), fetchExtendedDeploysInfoRequest: createAction('FETCH_EXTENDED_DEPLOYS_INFO')< { deployHash: string; publicKey: string }, Meta diff --git a/src/background/wallet-repositories.ts b/src/background/wallet-repositories.ts index ea4e8b05..901479d4 100644 --- a/src/background/wallet-repositories.ts +++ b/src/background/wallet-repositories.ts @@ -1,5 +1,6 @@ import { setupRepositories } from 'casper-wallet-core'; -const { deploysRepository, accountInfoRepository } = setupRepositories(); +const { deploysRepository, accountInfoRepository, tokensRepository } = + setupRepositories(); -export { deploysRepository, accountInfoRepository }; +export { deploysRepository, accountInfoRepository, tokensRepository }; diff --git a/src/fixtures/initial-state-for-popup-tests.ts b/src/fixtures/initial-state-for-popup-tests.ts index 35b1094a..212a7169 100644 --- a/src/fixtures/initial-state-for-popup-tests.ts +++ b/src/fixtures/initial-state-for-popup-tests.ts @@ -91,14 +91,6 @@ export const initialStateForPopupTests: RootState = { }, recentRecipientPublicKeys: [], accountInfo: { - balance: { - liquidMotes: null, - delegatedMotes: null, - undelegatingMotes: null, - totalBalanceMotes: null, - totalBalanceFiat: null - }, - currencyRate: null, pendingDeployHashes: [], erc20Tokens: [], accountNftTokens: [], @@ -113,7 +105,6 @@ export const initialStateForPopupTests: RootState = { ratedInStore: false, askForReviewAfter: null }, - accountBalances: [], promotion: { showCSPRNamePromotion: true } diff --git a/src/hooks/use-casper-token.ts b/src/hooks/use-casper-token.ts index d5f8ad23..b3631370 100644 --- a/src/hooks/use-casper-token.ts +++ b/src/hooks/use-casper-token.ts @@ -1,17 +1,6 @@ import { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; -import { - selectAccountBalance, - selectAccountCurrencyRate -} from '@background/redux/account-info/selectors'; - -import { - formatCurrency, - formatNumber, - motesToCSPR, - motesToCurrency -} from '@libs/ui/utils'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; export type TokenType = { id: string; @@ -28,37 +17,22 @@ export type TokenType = { export const useCasperToken = () => { const [casperToken, setCasperToken] = useState(null); - const balance = useSelector(selectAccountBalance); - const currencyRate = useSelector(selectAccountCurrencyRate); - - const amount = - balance?.liquidMotes == null - ? '-' - : formatNumber(motesToCSPR(balance.liquidMotes), { - precision: { max: 5 } - }); - const amountFiat = - currencyRate != null && balance?.liquidMotes != null - ? formatCurrency( - motesToCurrency(String(balance.liquidMotes), currencyRate), - 'USD', - { - precision: 2 - } - ) - : ''; + const { accountBalance } = useFetchWalletBalance(); useEffect(() => { setCasperToken({ id: 'Casper', contractHash: undefined, name: 'Casper', - amount, - amountFiat: amountFiat, + amount: accountBalance.liquidFormattedDecimalBalance || '-', + amountFiat: accountBalance.liquidFormattedFiatBalance, symbol: 'CSPR', icon: '/assets/icons/casper.svg' }); - }, [amount, amountFiat]); + }, [ + accountBalance.liquidFormattedDecimalBalance, + accountBalance.liquidFormattedFiatBalance + ]); return casperToken; }; diff --git a/src/hooks/use-fetch-account-balances.ts b/src/hooks/use-fetch-account-balances.ts deleted file mode 100644 index 0500c8d2..00000000 --- a/src/hooks/use-fetch-account-balances.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { BALANCE_REFRESH_RATE } from '@src/constants'; - -import { useForceUpdate } from '@popup/hooks/use-force-update'; - -import { accountBalancesChanged } from '@background/redux/account-balances/actions'; -import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; -import { dispatchToMainStore } from '@background/redux/utils'; -import { selectVaultAccounts } from '@background/redux/vault/selectors'; - -import { getAccountHashFromPublicKey } from '@libs/entities/Account'; -import { dispatchFetchAccountBalances } from '@libs/services/balance-service'; - -export const useFetchAccountBalances = () => { - const effectTimeoutRef = useRef(); - const forceUpdate = useForceUpdate(); - const { t } = useTranslation(); - - const { casperClarityApiUrl } = useSelector( - selectApiConfigBasedOnActiveNetwork - ); - const accounts = useSelector(selectVaultAccounts); - - const hashes = accounts.reduce( - (previousValue, currentValue, currentIndex) => { - const hash = getAccountHashFromPublicKey(currentValue.publicKey); - - return accounts.length === currentIndex + 1 - ? previousValue + `${hash}` - : previousValue + `${hash},`; - }, - '' - ); - - useEffect(() => { - dispatchFetchAccountBalances(hashes) - .then(({ payload }) => { - if ('data' in payload) { - dispatchToMainStore(accountBalancesChanged(payload.data)); - } else { - dispatchToMainStore(accountBalancesChanged([])); - } - }) - .catch(error => { - console.error(t('Failed to fetch accounts balance'), error); - }); - - // will cause effect to run again after timeout - effectTimeoutRef.current = setTimeout(() => { - forceUpdate(); - }, BALANCE_REFRESH_RATE + 1); - - return () => { - clearTimeout(effectTimeoutRef.current); - }; - }, [casperClarityApiUrl, forceUpdate, t, hashes]); -}; diff --git a/src/hooks/use-fetch-active-account-balance.ts b/src/hooks/use-fetch-active-account-balance.ts deleted file mode 100644 index 3968d437..00000000 --- a/src/hooks/use-fetch-active-account-balance.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; - -import { BALANCE_REFRESH_RATE } from '@src/constants'; - -import { useForceUpdate } from '@popup/hooks/use-force-update'; - -import { - accountBalanceChanged, - accountCurrencyRateChanged -} from '@background/redux/account-info/actions'; -import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; -import { dispatchToMainStore } from '@background/redux/utils'; -import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; - -import { getAccountHashFromPublicKey } from '@libs/entities/Account'; -import { dispatchFetchActiveAccountBalance } from '@libs/services/balance-service'; -import { formatCurrency, motesToCurrency } from '@libs/ui/utils'; - -export const useFetchActiveAccountBalance = () => { - const effectTimeoutRef = useRef(); - const forceUpdate = useForceUpdate(); - const { t } = useTranslation(); - - const activeAccount = useSelector(selectVaultActiveAccount); - const { casperClarityApiUrl } = useSelector( - selectApiConfigBasedOnActiveNetwork - ); - - useEffect(() => { - if (!activeAccount?.publicKey) return; - - const accountHash = getAccountHashFromPublicKey(activeAccount.publicKey); - - dispatchFetchActiveAccountBalance(accountHash) - .then(({ payload: { accountData, currencyRate } }) => { - if (accountData != null) { - const liquidBalance = accountData?.balance || 0; - const delegatedBalance = accountData?.delegated_balance || 0; - const undelegatingBalance = accountData?.undelegating_balance || 0; - - const totalAmountMotes = - liquidBalance + delegatedBalance + undelegatingBalance; - const totalBalanceFiat = - currencyRate != null - ? formatCurrency( - motesToCurrency(String(totalAmountMotes), currencyRate), - 'USD', - { - precision: 2 - } - ) - : t('Currency service is offline...'); - - dispatchToMainStore(accountCurrencyRateChanged(currencyRate)); - dispatchToMainStore( - accountBalanceChanged({ - liquidMotes: String(liquidBalance), - delegatedMotes: String(delegatedBalance), - undelegatingMotes: String(undelegatingBalance), - totalBalanceMotes: String(totalAmountMotes), - totalBalanceFiat: totalBalanceFiat - }) - ); - } else { - dispatchToMainStore(accountCurrencyRateChanged(currencyRate)); - dispatchToMainStore( - accountBalanceChanged({ - liquidMotes: null, - undelegatingMotes: null, - delegatedMotes: null, - totalBalanceMotes: null, - totalBalanceFiat: null - }) - ); - } - }) - .catch(error => { - console.error('Balance request failed:', error); - }); - - // will cause effect to run again after timeout - effectTimeoutRef.current = setTimeout(() => { - forceUpdate(); - }, BALANCE_REFRESH_RATE + 1); - - return () => { - clearTimeout(effectTimeoutRef.current); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [activeAccount?.publicKey, casperClarityApiUrl, t, forceUpdate]); -}; diff --git a/src/libs/layout/header/header-data-updater.tsx b/src/libs/layout/header/header-data-updater.tsx index 76a57ef3..5c243c72 100644 --- a/src/libs/layout/header/header-data-updater.tsx +++ b/src/libs/layout/header/header-data-updater.tsx @@ -1,13 +1,12 @@ import React from 'react'; -import { useFetchAccountBalances } from '@hooks/use-fetch-account-balances'; -import { useFetchActiveAccountBalance } from '@hooks/use-fetch-active-account-balance'; import { useFetchErc20Tokens } from '@hooks/use-fetch-erc20-tokens'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; + export const HeaderDataUpdater: React.FC = () => { - useFetchActiveAccountBalance(); useFetchErc20Tokens(); - useFetchAccountBalances(); + useFetchWalletBalance(); return null; }; diff --git a/src/libs/layout/header/header-submenu-bar-nav-link.tsx b/src/libs/layout/header/header-submenu-bar-nav-link.tsx index 8108ffee..e5c44e82 100644 --- a/src/libs/layout/header/header-submenu-bar-nav-link.tsx +++ b/src/libs/layout/header/header-submenu-bar-nav-link.tsx @@ -1,17 +1,15 @@ import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { RouterPath } from '@popup/router/paths'; import { useTypedNavigate } from '@popup/router/use-typed-navigate'; import { closeCurrentWindow } from '@background/close-current-window'; -import { selectAccountBalance } from '@background/redux/account-info/selectors'; import { AlignedFlexRow, SpacingSize } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Link, SvgIcon, Typography } from '@libs/ui/components'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils/formatters'; const LinkWithIconContainer = styled.div` display: flex; @@ -40,11 +38,7 @@ export function HeaderSubmenuBarNavLink({ const { t } = useTranslation(); const navigate = useTypedNavigate(); - const balance = useSelector(selectAccountBalance); - - const formattedBalance = formatNumber( - (balance.liquidMotes && motesToCSPR(balance.liquidMotes)) || '' - ); + const { accountBalance } = useFetchWalletBalance(); switch (linkType) { case 'close': @@ -81,14 +75,16 @@ export function HeaderSubmenuBarNavLink({ }} withLeftChevronIcon /> - - - Balance: - - - {`${formattedBalance} CSPR`} - - + {accountBalance.liquidFormattedDecimalBalance && ( + + + Balance: + + + {`${accountBalance.liquidFormattedDecimalBalance} CSPR`} + + + )} ) : ( => - fetch(getCurrencyRateUrl(casperClarityApiUrl), { signal }) - .then(toJson) - .catch(handleError); - -export const accountBalanceRequest = ( - accountHash: string, - casperWalletApiUrl: string, - signal?: AbortSignal -): Promise => { - if (!accountHash) { - throw Error('Missing account hash'); - } - - return fetch(getAccountBalanceUrl({ accountHash, casperWalletApiUrl }), { - signal - }) - .then(res => { - if (res.status === 404) { - return { - data: { - balance: 0 - } as AccountData - }; - } - - return toJson(res); - }) - .catch(handleError); -}; - -export const accountBalancesRequest = ( - accountHashes: string, - casperWalletApiUrl: string, - signal?: AbortSignal -): Promise | ErrorResponse> => - fetch( - getAccountBalancesUrl({ - accountHashes, - casperWalletApiUrl - }), - { - signal - } - ) - .then(toJson) - .catch(handleError); - -export const dispatchFetchActiveAccountBalance = ( - accountHash = '' -): Promise> => - dispatchToMainStore(serviceMessage.fetchBalanceRequest({ accountHash })); - -export const dispatchFetchAccountBalances = ( - accountHashes = '' -): Promise | ErrorResponse>> => - dispatchToMainStore( - serviceMessage.fetchAccountBalancesRequest({ accountHashes }) - ); - -export const fetchAccountBalance = ({ - accountHash, - casperWalletApiUrl -}: { - accountHash: string; - casperWalletApiUrl: string; -}): Promise> => - queryClient.fetchQuery( - ['getAccountBalanceRequest', accountHash, casperWalletApiUrl], - ({ signal }) => - accountBalanceRequest(accountHash, casperWalletApiUrl, signal), - { - staleTime: BALANCE_REFRESH_RATE - } - ); - -export const fetchCurrencyRate = ({ - casperClarityApiUrl -}: { - casperClarityApiUrl: string; -}) => - queryClient.fetchQuery( - 'getCurrencyRateRequest', - ({ signal }) => currencyRateRequest(casperClarityApiUrl, signal), - { - staleTime: CURRENCY_REFRESH_RATE - } - ); - -export const fetchAccountBalances = ({ - accountHashes, - casperWalletApiUrl -}: { - accountHashes: string; - casperWalletApiUrl: string; -}) => - queryClient.fetchQuery( - ['getAccountBalancesRequest', accountHashes, casperWalletApiUrl], - ({ signal }) => - accountBalancesRequest(accountHashes, casperWalletApiUrl, signal), - { - staleTime: BALANCE_REFRESH_RATE - } - ); diff --git a/src/libs/services/balance-service/constants.ts b/src/libs/services/balance-service/constants.ts index 44cc59b0..33bf11a9 100644 --- a/src/libs/services/balance-service/constants.ts +++ b/src/libs/services/balance-service/constants.ts @@ -1,24 +1,8 @@ -interface GetAccountBalanceUrl { - accountHash: string; - casperWalletApiUrl: string; -} - -interface GetAccountBalancesUrl { - accountHashes: string; - casperWalletApiUrl: string; -} +import { ICsprBalance } from 'casper-wallet-core/src/domain/tokens'; -export const getCurrencyRateUrl = (casperClarityApiUrl: string) => - `${casperClarityApiUrl}/rates/1/amount`; +type AccountsBalances = Record | undefined; -export const getAccountBalanceUrl = ({ - accountHash, - casperWalletApiUrl -}: GetAccountBalanceUrl) => - `${casperWalletApiUrl}/accounts/${accountHash}?includes=delegated_balance,undelegating_balance`; - -export const getAccountBalancesUrl = ({ - accountHashes, - casperWalletApiUrl -}: GetAccountBalancesUrl) => - `${casperWalletApiUrl}/accounts?account_hash=${accountHashes}&page=1&page_size=100&includes=delegated_balance,undelegating_balance`; +export interface UseFetchAccountsBalances { + accountsBalances: AccountsBalances; + isLoadingBalances: boolean; +} diff --git a/src/libs/services/balance-service/index.ts b/src/libs/services/balance-service/index.ts index b7d52483..f929e3a8 100644 --- a/src/libs/services/balance-service/index.ts +++ b/src/libs/services/balance-service/index.ts @@ -1,3 +1,2 @@ -export * from './balance-service'; -export * from './types'; -export * from './constants'; +export * from './use-fetch-accounts-balances'; +export * from './use-fetch-wallet-balance'; diff --git a/src/libs/services/balance-service/queries.ts b/src/libs/services/balance-service/queries.ts new file mode 100644 index 00000000..56a00a91 --- /dev/null +++ b/src/libs/services/balance-service/queries.ts @@ -0,0 +1,68 @@ +import { CasperNetwork } from 'casper-wallet-core/src/domain/common/common'; + +import { + BALANCE_REFRESH_RATE, + CURRENCY_REFRESH_RATE, + NetworkSetting +} from '@src/constants'; + +import { + accountInfoRepository, + tokensRepository +} from '@background/wallet-repositories'; + +import { Account } from '@libs/types/account'; + +interface AccountBalanceQueryProps { + network: NetworkSetting; + activeAccount: Account | undefined; +} + +interface CurrencyRateQueryProps { + network: NetworkSetting; +} + +interface AccountBalancesQueryProps { + accountHashesString: string; + network: NetworkSetting; + accountHashes: string[]; +} + +export const accountBalanceQuery = ({ + network, + activeAccount +}: AccountBalanceQueryProps) => ({ + queryKey: ['ACCOUNT_BALANCE', network, activeAccount?.publicKey], + queryFn: () => + tokensRepository.getCsprBalance({ + publicKey: activeAccount?.publicKey || '', + network: network.toLowerCase() as CasperNetwork + }), + refetchInterval: BALANCE_REFRESH_RATE, + staleTime: BALANCE_REFRESH_RATE +}); + +export const currencyRateQuery = ({ network }: CurrencyRateQueryProps) => ({ + queryKey: ['CURRENCY_RATE', network], + queryFn: () => + tokensRepository.getCsprFiatCurrencyRate({ + network: network.toLowerCase() as CasperNetwork + }), + refetchInterval: CURRENCY_REFRESH_RATE, + staleTime: CURRENCY_REFRESH_RATE +}); + +export const accountsBalancesQuery = ({ + accountHashesString, + network, + accountHashes +}: AccountBalancesQueryProps) => ({ + queryKey: ['ACCOUNTS_BALANCES', accountHashesString, network], + queryFn: async () => + accountInfoRepository.getAccountsBalances({ + accountHashes: accountHashes, + network: network.toLowerCase() as CasperNetwork + }), + refetchInterval: BALANCE_REFRESH_RATE, + staleTime: BALANCE_REFRESH_RATE +}); diff --git a/src/libs/services/balance-service/types.ts b/src/libs/services/balance-service/types.ts deleted file mode 100644 index 867c1a87..00000000 --- a/src/libs/services/balance-service/types.ts +++ /dev/null @@ -1,25 +0,0 @@ -export interface GetCurrencyRateRequestResponse { - data: number; -} - -export interface AccountData { - account_hash: string; - balance: number; - delegated_balance?: number; - main_purse_uref: string; - public_key: string; - undelegating_balance?: number; -} - -export interface FetchBalanceResponse { - currencyRate: number | null; - accountData: AccountData | null; -} - -export interface AccountBalance { - liquidMotes: string | null; - delegatedMotes: string | null; - undelegatingMotes: string | null; - totalBalanceMotes: string | null; - totalBalanceFiat: string | null; -} diff --git a/src/libs/services/balance-service/use-fetch-accounts-balances.ts b/src/libs/services/balance-service/use-fetch-accounts-balances.ts new file mode 100644 index 00000000..8270a4e2 --- /dev/null +++ b/src/libs/services/balance-service/use-fetch-accounts-balances.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import { useSelector } from 'react-redux'; + +import { selectActiveNetworkSetting } from '@background/redux/settings/selectors'; + +import { UseFetchAccountsBalances } from '@libs/services/balance-service/constants'; +import { accountsBalancesQuery } from '@libs/services/balance-service/queries'; + +export const useFetchAccountsBalances = ( + accountHashes: string[] +): UseFetchAccountsBalances => { + const network = useSelector(selectActiveNetworkSetting); + + const accountHashesString = accountHashes.toString(); + + const { data: accountsBalances, isFetching: isLoadingBalances } = useQuery( + accountsBalancesQuery({ + network, + accountHashes, + accountHashesString + }) + ); + + return { + accountsBalances, + isLoadingBalances + }; +}; diff --git a/src/libs/services/balance-service/use-fetch-wallet-balance.ts b/src/libs/services/balance-service/use-fetch-wallet-balance.ts new file mode 100644 index 00000000..76da2ee4 --- /dev/null +++ b/src/libs/services/balance-service/use-fetch-wallet-balance.ts @@ -0,0 +1,123 @@ +import { useQueries } from '@tanstack/react-query'; +import { useSelector } from 'react-redux'; + +import { selectActiveNetworkSetting } from '@background/redux/settings/selectors'; +import { + selectVaultAccounts, + selectVaultActiveAccount +} from '@background/redux/vault/selectors'; + +import { getAccountHashFromPublicKey } from '@libs/entities/Account'; +import { + accountBalanceQuery, + accountsBalancesQuery, + currencyRateQuery +} from '@libs/services/balance-service/queries'; +import { formatCurrency, motesToCurrency } from '@libs/ui/utils'; + +export const useFetchWalletBalance = () => { + const activeAccount = useSelector(selectVaultActiveAccount); + const network = useSelector(selectActiveNetworkSetting); + const accounts = useSelector(selectVaultAccounts); + + const accountHashes = accounts.map(account => + getAccountHashFromPublicKey(account.publicKey) + ); + + const accountHashesString = accountHashes.toString(); + + const { + accountBalance, + isLoadingBalance, + currencyRate, + accountsBalances, + isLoadingBalances + } = useQueries({ + queries: [ + accountBalanceQuery({ + network, + activeAccount + }), + currencyRateQuery({ + network + }), + accountsBalancesQuery({ + accountHashesString, + network, + accountHashes + }) + ], + combine: results => { + const accountBalance = results[0].data; + const totalBalance = results[0].data?.totalBalance; + const liquidBalance = results[0].data?.liquidBalance; + const delegatedBalance = results[0].data?.delegatedBalance; + const undelegatingBalance = results[0].data?.undelegatingBalance; + const currencyRate = results[1].data?.rate; + const accountsBalances = results[2].data; + + const totalFormattedFiatBalance = + currencyRate && totalBalance + ? formatCurrency( + motesToCurrency(String(totalBalance), currencyRate), + 'USD', + { + precision: 2 + } + ) + : ''; + const liquidFormattedFiatBalance = + currencyRate && liquidBalance + ? formatCurrency( + motesToCurrency(String(liquidBalance), currencyRate), + 'USD', + { + precision: 2 + } + ) + : ''; + const delegatedFormattedFiatBalance = + currencyRate && delegatedBalance + ? formatCurrency( + motesToCurrency(String(delegatedBalance), currencyRate), + 'USD', + { + precision: 2 + } + ) + : ''; + const undelegatedFormattedFiatBalance = + currencyRate && undelegatingBalance + ? formatCurrency( + motesToCurrency(String(undelegatingBalance), currencyRate), + 'USD', + { + precision: 2 + } + ) + : ''; + + return { + accountBalance: { + ...accountBalance, + totalFormattedFiatBalance, + liquidFormattedFiatBalance, + delegatedFormattedFiatBalance, + undelegatedFormattedFiatBalance + }, + isLoadingBalance: results[0].isLoading, + currencyRate: results[1].data, + accountsBalances, + isLoadingBalances: results[2].isLoading + }; + } + }); + + return { + accountBalance, + isLoadingBalance, + currencyRate, + accountsBalances, + isLoadingBalances + }; +}; diff --git a/src/libs/services/deployer-service/index.ts b/src/libs/services/deployer-service/index.ts index 3f622926..6dbe61b0 100644 --- a/src/libs/services/deployer-service/index.ts +++ b/src/libs/services/deployer-service/index.ts @@ -20,11 +20,7 @@ import { import { getRawPublicKey } from '@libs/entities/Account'; import { toJson } from '@libs/services/utils'; -import { - Account, - AccountWithBalance, - HardwareWalletType -} from '@libs/types/account'; +import { Account, HardwareWalletType } from '@libs/types/account'; import { CSPRtoMotes, multiplyErc20Balance } from '@libs/ui/utils'; import { ledger } from '../ledger'; @@ -119,7 +115,7 @@ export const makeAuctionManagerDeploy = async ( }; export const makeNativeTransferDeploy = async ( - activeAccount: AccountWithBalance, + activeAccount: Account, recipientPublicKeyHex: string, amountMotes: string, networkName: NetworkName, diff --git a/src/libs/types/account.ts b/src/libs/types/account.ts index f5f6a57d..82a5883a 100644 --- a/src/libs/types/account.ts +++ b/src/libs/types/account.ts @@ -14,13 +14,7 @@ export enum HardwareWalletType { Ledger = 'Ledger' } -export interface AccountWithBalance extends Account { - balance: { - liquidMotes: string | null; - }; -} - -export interface AccountListRows extends AccountWithBalance { +export interface AccountListRows extends Account { id: string; } diff --git a/src/libs/ui/components/account-list/account-list-item.tsx b/src/libs/ui/components/account-list/account-list-item.tsx index d90ed69b..d7f7b9e8 100644 --- a/src/libs/ui/components/account-list/account-list-item.tsx +++ b/src/libs/ui/components/account-list/account-list-item.tsx @@ -56,6 +56,8 @@ interface AccountListItemProps { showHideAccountItem?: boolean; closeModal?: (e: React.MouseEvent) => void; accountsInfo: Record | undefined; + accountLiquidBalance: string | undefined; + isLoadingBalance: boolean; } export const AccountListItem = ({ @@ -65,14 +67,15 @@ export const AccountListItem = ({ isConnected, showHideAccountItem, closeModal, - accountsInfo + accountsInfo, + accountLiquidBalance, + isLoadingBalance }: AccountListItemProps) => { - const accountBalance = - account.balance?.liquidMotes != null - ? formatNumber(motesToCSPR(account.balance.liquidMotes), { - precision: { max: 0 } - }) - : '-'; + const accountBalance = accountLiquidBalance + ? formatNumber(motesToCSPR(accountLiquidBalance), { + precision: { max: 0 } + }) + : '0'; const csprName = accountsInfo && accountsInfo[account.accountHash]?.csprName; const brandingLogo = @@ -106,7 +109,7 @@ export const AccountListItem = ({ {accountBalance} diff --git a/src/libs/ui/components/account-list/account-list.tsx b/src/libs/ui/components/account-list/account-list.tsx index d76c669d..89921ff0 100644 --- a/src/libs/ui/components/account-list/account-list.tsx +++ b/src/libs/ui/components/account-list/account-list.tsx @@ -21,6 +21,7 @@ import { useWindowManager } from '@hooks/use-window-manager'; import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { FlexColumn, SpacingSize } from '@libs/layout'; import { useFetchAccountsInfo } from '@libs/services/account-info'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { AccountListRowWithAccountHash, AccountListRows @@ -56,6 +57,7 @@ export const AccountList = ({ closeModal }: AccountListProps) => { const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); + const { accountsBalances, isLoadingBalance } = useFetchWalletBalance(); useEffect(() => { const accountListRows = sortAccounts( @@ -82,6 +84,10 @@ export const AccountList = ({ closeModal }: AccountListProps) => { const isConnected = connectedAccountNames.includes(account.name); const isActiveAccount = activeAccountName === account.name; + const accountLiquidBalance = + accountsBalances && + accountsBalances[account.accountHash]?.liquidBalance; + return ( { changeActiveAccount(account.name); closeModal(event); }} + accountLiquidBalance={accountLiquidBalance} accountsInfo={accountsInfo} + isLoadingBalance={isLoadingBalance} /> ); }} diff --git a/src/libs/ui/components/account-list/utils.ts b/src/libs/ui/components/account-list/utils.ts index d794b763..7b777e8f 100644 --- a/src/libs/ui/components/account-list/utils.ts +++ b/src/libs/ui/components/account-list/utils.ts @@ -1,7 +1,7 @@ -import { Account, AccountWithBalance } from '@libs/types/account'; +import { Account } from '@libs/types/account'; export function sortAccounts( - accounts: AccountWithBalance[], + accounts: Account[], activeAccountName: string | null, connectedAccountNames: string[] ) { diff --git a/src/libs/ui/components/active-account-plate/active-account-plate.tsx b/src/libs/ui/components/active-account-plate/active-account-plate.tsx index aba7d66c..439e6327 100644 --- a/src/libs/ui/components/active-account-plate/active-account-plate.tsx +++ b/src/libs/ui/components/active-account-plate/active-account-plate.tsx @@ -42,7 +42,7 @@ const Container = styled(TileContainer)` interface ActiveAccountPlateProps { label: string; - balance: string | null; + balance: string | undefined; symbol: string | null; top?: SpacingSize; } @@ -107,15 +107,13 @@ export const ActiveAccountPlate = ({ 9 ? balance : undefined - } + title={balance && balance?.length > 9 ? balance : undefined} placement="topLeft" overflowWrap fullWidth > - {balance == null ? '-' : balance} + {balance || '-'} diff --git a/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx b/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx index 7e4dba9b..b15cecf3 100644 --- a/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx +++ b/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx @@ -1,4 +1,5 @@ import { Player } from '@lottiefiles/react-lottie-player'; +import { ICsprBalance } from 'casper-wallet-core/src/domain/tokens'; import React, { useEffect, useState } from 'react'; import { Controller, @@ -23,6 +24,7 @@ import { useIsDarkMode } from '@hooks/use-is-dark-mode'; import dotsDarkModeAnimation from '@libs/animations/dots_dark_mode.json'; import dotsLightModeAnimation from '@libs/animations/dots_light_mode.json'; +import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { CenteredFlexRow, FlexColumn, @@ -68,6 +70,7 @@ interface ListProps { onLoadMore: () => void; isLoadingMore: boolean; namePrefix: string; + accountsBalances: Record | undefined; } type FormFields = FieldValues & { @@ -83,7 +86,8 @@ export const DynamicAccountsListWithSelect = ({ maxItemsToRender, onLoadMore, isLoadingMore, - namePrefix + namePrefix, + accountsBalances }: ListProps) => { const [accountNames, setAccountNames] = useState<{ name: string }[]>([]); const [checkboxes, setCheckboxes] = useState([]); @@ -152,12 +156,16 @@ export const DynamicAccountsListWithSelect = ({ renderRow={(account, index) => { const inputFieldName = `accountNames.${index}.name`; const checkBoxFieldName = `checkbox.${index}`; - const balance = formatNumber( - motesToCSPR(String(account.balance.liquidMotes)), - { - precision: { max: 0 } - } - ); + const accountHash = getAccountHashFromPublicKey(account.publicKey); + + const accountLiquidBalance = + accountsBalances && accountsBalances[accountHash]?.liquidBalance; + + const accountBalance = accountLiquidBalance + ? formatNumber(motesToCSPR(accountLiquidBalance), { + precision: { max: 0 } + }) + : '0'; const isAlreadyConnected = alreadyConnectedLedgerAccounts.some( alreadyConnectedAccount => @@ -232,7 +240,9 @@ export const DynamicAccountsListWithSelect = ({ 9 ? balance : undefined} + title={ + accountBalance.length > 9 ? accountBalance : undefined + } placement="topLeft" overflowWrap fullWidth @@ -242,7 +252,7 @@ export const DynamicAccountsListWithSelect = ({ style={{ textAlign: 'right' }} ellipsis > - {balance} + {accountBalance} { diff --git a/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx b/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx index 111e1afe..da8dd3d7 100644 --- a/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx +++ b/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx @@ -1,16 +1,14 @@ import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { TRANSFER_COST_MOTES } from '@src/constants'; -import { selectAccountCurrencyRate } from '@background/redux/account-info/selectors'; - import { AlignedSpaceBetweenFlexRow, RightAlignedFlexColumn } from '@libs/layout'; +import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Tile, Typography } from '@libs/ui/components'; import { formatFiatAmount, formatNumber, motesToCSPR } from '@libs/ui/utils'; @@ -27,7 +25,7 @@ export const TransactionFeePlate = ({ }: TransactionFeePlateProps) => { const { t } = useTranslation(); - const currencyRate = useSelector(selectAccountCurrencyRate); + const { currencyRate } = useFetchWalletBalance(); return ( @@ -45,7 +43,7 @@ export const TransactionFeePlate = ({ {formatFiatAmount( motesToCSPR(TRANSFER_COST_MOTES) || '0', - currencyRate, + currencyRate?.rate || null, 3 )} diff --git a/src/libs/ui/forms/create-account.ts b/src/libs/ui/forms/create-account.ts index 382166e9..e633ec46 100644 --- a/src/libs/ui/forms/create-account.ts +++ b/src/libs/ui/forms/create-account.ts @@ -3,7 +3,7 @@ import { yupResolver } from '@hookform/resolvers/yup/dist/yup'; import { UseFormProps, useForm } from 'react-hook-form'; import { SecretPhrase, deriveKeyPair } from '@libs/crypto'; -import { AccountWithBalance } from '@libs/types/account'; +import { Account } from '@libs/types/account'; import { useAccountNameRule } from './form-validation-rules'; @@ -34,7 +34,7 @@ export function useCreateAccountForm( export function getDefaultName( existingAccountNames: string[], - derivedAccounts: AccountWithBalance[], + derivedAccounts: Account[], secretPhrase: SecretPhrase | null ) { const accountString = 'Account'; diff --git a/src/libs/ui/forms/form-validation-rules.ts b/src/libs/ui/forms/form-validation-rules.ts index 0a778971..09ca5a2a 100644 --- a/src/libs/ui/forms/form-validation-rules.ts +++ b/src/libs/ui/forms/form-validation-rules.ts @@ -141,13 +141,12 @@ export const useRecipientPublicKeyRule = () => { }); }; -export const useCSPRTransferAmountRule = (amountMotes: string | null) => { +export const useCSPRTransferAmountRule = (amountMotes: string | undefined) => { const { t } = useTranslation(); - const maxAmountMotes: string = - amountMotes == null - ? '0' - : Big(amountMotes).sub(TRANSFER_COST_MOTES).toFixed(); + const maxAmountMotes: string = !amountMotes + ? '0' + : Big(amountMotes).sub(TRANSFER_COST_MOTES).toFixed(); return Yup.string() .required(t('Amount is required')) @@ -269,11 +268,12 @@ export const useErc20AmountRule = ( }); }; -export const usePaymentAmountRule = (csprBalance: string | null) => { +export const usePaymentAmountRule = (csprBalance: string | undefined) => { const { t } = useTranslation(); - const maxAmountMotes: string = - csprBalance == null ? '0' : Big(csprBalance).toFixed(); + const maxAmountMotes: string = !csprBalance + ? '0' + : Big(csprBalance).toFixed(); return Yup.string() .required(t('Payment amount is required')) @@ -315,7 +315,7 @@ export const usePaymentAmountRule = (csprBalance: string | null) => { }; export const useCSPRStakeAmountRule = ( - amountMotes: string | null, + amountMotes: string | undefined, mode: AuctionManagerEntryPoint, stakeAmountMotes: string ) => { @@ -337,10 +337,9 @@ export const useCSPRStakeAmountRule = ( } }; - const maxAmountMotes: string = - amountMotes == null - ? '0' - : Big(amountMotes).sub(STAKE_COST_MOTES).toFixed(); + const maxAmountMotes: string = !amountMotes + ? '0' + : Big(amountMotes).sub(STAKE_COST_MOTES).toFixed(); return Yup.string() .required({ diff --git a/src/libs/ui/forms/stakes-form.ts b/src/libs/ui/forms/stakes-form.ts index 4b40c566..2b57b78c 100644 --- a/src/libs/ui/forms/stakes-form.ts +++ b/src/libs/ui/forms/stakes-form.ts @@ -23,7 +23,7 @@ export type StakeAmountFormValues = { }; export const useStakesForm = ( - amountMotes: string | null, + amountMotes: string | undefined, stakeType: AuctionManagerEntryPoint, stakeAmountMotes: string, delegatorsNumber?: number, diff --git a/src/libs/ui/forms/transfer-nft.ts b/src/libs/ui/forms/transfer-nft.ts index e0fc37bb..b7225cfe 100644 --- a/src/libs/ui/forms/transfer-nft.ts +++ b/src/libs/ui/forms/transfer-nft.ts @@ -16,7 +16,7 @@ export type TransferNftRecipientFormValues = { }; export const useTransferNftForm = ( - amountMotes: string | null, + amountMotes: string | undefined, paymentAmount: string ) => { const recipientFormSchema = Yup.object().shape({ diff --git a/src/libs/ui/forms/transfer.ts b/src/libs/ui/forms/transfer.ts index 6d6fe9aa..1006fddf 100644 --- a/src/libs/ui/forms/transfer.ts +++ b/src/libs/ui/forms/transfer.ts @@ -41,7 +41,7 @@ export const useTransferRecipientForm = () => { export const useTransferAmountForm = ( erc20Balance: string | null, isErc20: boolean, - amountMotes: string | null, + amountMotes: string | undefined, paymentAmount: string, decimals: number | undefined ) => { From 13dfe3af47f9043bfa91b5c062ec02cf5145b9c8 Mon Sep 17 00:00:00 2001 From: Ostap Piatkovskyi <44294945+ost-ptk@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:01:39 +0200 Subject: [PATCH 3/5] added cspr name support to contact details page (#1069) --- .../pages/switch-account/content.tsx | 6 ++--- .../popup/pages/account-settings/content.tsx | 4 ++- .../pages/connect-another-account/index.tsx | 4 +-- .../popup/pages/connected-sites/index.tsx | 4 +-- .../popup/pages/contact-details/details.tsx | 22 ++++++++++++++++ .../contacts/components/contacts-plate.tsx | 17 ++++-------- src/apps/popup/pages/contacts/content.tsx | 26 ++++++++++++++----- .../header/header-connection-status.tsx | 8 ++++-- .../account-info/use-fetch-accounts-info.ts | 2 +- .../active-account-plate.tsx | 9 ++++--- src/libs/ui/forms/form-validation-rules.ts | 4 ++- 11 files changed, 72 insertions(+), 34 deletions(-) diff --git a/src/apps/connect-to-app/pages/switch-account/content.tsx b/src/apps/connect-to-app/pages/switch-account/content.tsx index ce479aef..af4446c1 100644 --- a/src/apps/connect-to-app/pages/switch-account/content.tsx +++ b/src/apps/connect-to-app/pages/switch-account/content.tsx @@ -47,7 +47,7 @@ type SwitchAccountContentProps = { requestId: string }; export function SwitchAccountContent({ requestId }: SwitchAccountContentProps) { const activeOrigin = useSelector(selectActiveOrigin); const activeAccount = useSelector(selectVaultActiveAccount); - const publicKeys = useSelector(selectVaultAccountsPublicKeys); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); const connectedAccountsToActiveTab = useSelector( selectConnectedAccountsWithActiveOrigin ); @@ -77,7 +77,7 @@ export function SwitchAccountContent({ requestId }: SwitchAccountContentProps) { account => account.name !== activeAccount?.name ); - const accountsInfo = useFetchAccountsInfo(publicKeys); + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); return ( @@ -141,7 +141,7 @@ export function SwitchAccountContent({ requestId }: SwitchAccountContentProps) { {account.name} diff --git a/src/apps/popup/pages/account-settings/content.tsx b/src/apps/popup/pages/account-settings/content.tsx index fd964cc6..b43a6fbc 100644 --- a/src/apps/popup/pages/account-settings/content.tsx +++ b/src/apps/popup/pages/account-settings/content.tsx @@ -12,6 +12,7 @@ import { dispatchToMainStore } from '@background/redux/utils'; import { hideAccountFromListChanged } from '@background/redux/vault/actions'; import { selectVaultAccount, + selectVaultAccountsPublicKeys, selectVaultHiddenAccountsNames, selectVaultImportedAccountNames, selectVaultLedgerAccountNames @@ -42,13 +43,14 @@ export function AccountSettingsPageContent() { const account = useSelector((state: RootState) => selectVaultAccount(state, accountName || '') ); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); if (!account) { throw new Error("Account doesn't exist"); } + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); const accountHash = getAccountHashFromPublicKey(account.publicKey); - const accountsInfo = useFetchAccountsInfo([account.publicKey]); const csprName = accountsInfo && accountsInfo[accountHash]?.csprName; diff --git a/src/apps/popup/pages/connect-another-account/index.tsx b/src/apps/popup/pages/connect-another-account/index.tsx index f5dcb115..3c5e3d0b 100644 --- a/src/apps/popup/pages/connect-another-account/index.tsx +++ b/src/apps/popup/pages/connect-another-account/index.tsx @@ -58,7 +58,7 @@ export function ConnectAnotherAccountPageContent() { const { targetAccountName } = useParams(); const activeOrigin = useSelector(selectActiveOrigin); - const publicKeys = useSelector(selectVaultAccountsPublicKeys); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); const { connectAnotherAccountWithEvent: connectAccount, @@ -87,7 +87,7 @@ export function ConnectAnotherAccountPageContent() { targetAccount?.publicKey ); - const accountsInfo = useFetchAccountsInfo(publicKeys); + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); const targetAccountCsprName = accountsInfo && accountsInfo[targetAccountHash]?.csprName; diff --git a/src/apps/popup/pages/connected-sites/index.tsx b/src/apps/popup/pages/connected-sites/index.tsx index c3ec3879..b2560728 100644 --- a/src/apps/popup/pages/connected-sites/index.tsx +++ b/src/apps/popup/pages/connected-sites/index.tsx @@ -32,11 +32,11 @@ export function ConnectedSitesPage() { const accountsByOrigin = useSelector(selectAccountsByOriginDict); const siteNameByOriginDict = useSelector(selectSiteNameByOriginDict); - const publicKeys = useSelector(selectVaultAccountsPublicKeys); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); const isNoSitesConnected = !Object.entries(accountsByOrigin).length; - const accountsInfo = useFetchAccountsInfo(publicKeys); + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); if (isNoSitesConnected) { return ( diff --git a/src/apps/popup/pages/contact-details/details.tsx b/src/apps/popup/pages/contact-details/details.tsx index 3655ce83..5482d06a 100644 --- a/src/apps/popup/pages/contact-details/details.tsx +++ b/src/apps/popup/pages/contact-details/details.tsx @@ -1,14 +1,19 @@ import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; import styled from 'styled-components'; +import { selectAllContactsPublicKeys } from '@background/redux/contacts/selectors'; import { Contact } from '@background/redux/contacts/types'; +import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { ContentContainer, + FlexColumn, LeftAlignedFlexColumn, SpacingSize } from '@libs/layout'; +import { useFetchAccountsInfo } from '@libs/services/account-info'; import { Avatar, Hash, @@ -32,6 +37,13 @@ interface ContactDetailsProps { export const ContactDetails = ({ contact }: ContactDetailsProps) => { const { t } = useTranslation(); + const contactPublicKeys = useSelector(selectAllContactsPublicKeys); + + const accountsInfo = useFetchAccountsInfo(contactPublicKeys); + + const accountHash = getAccountHashFromPublicKey(contact.publicKey); + const csprName = accountsInfo && accountsInfo[accountHash]?.csprName; + return ( @@ -44,6 +56,16 @@ export const ContactDetails = ({ contact }: ContactDetailsProps) => { variant={HashVariant.CaptionHash} color="contentPrimary" /> + {csprName ? ( + + + CSPR.name + + + {csprName} + + + ) : null} Last edited: {formatShortTimestamp(contact.lastModified)} diff --git a/src/apps/popup/pages/contacts/components/contacts-plate.tsx b/src/apps/popup/pages/contacts/components/contacts-plate.tsx index 8e0a3b22..421ca3a8 100644 --- a/src/apps/popup/pages/contacts/components/contacts-plate.tsx +++ b/src/apps/popup/pages/contacts/components/contacts-plate.tsx @@ -1,13 +1,10 @@ +import { Maybe } from 'casper-wallet-core/src/typings/common'; import React from 'react'; -import { useSelector } from 'react-redux'; import styled from 'styled-components'; import { RouterPath, useTypedNavigate } from '@popup/router'; -import { selectAllContactsPublicKeys } from '@background/redux/contacts/selectors'; - import { AlignedFlexRow, FlexColumn, SpacingSize } from '@libs/layout'; -import { useFetchAccountsInfo } from '@libs/services/account-info'; import { Avatar, Hash, HashVariant, Typography } from '@libs/ui/components'; const Container = styled(AlignedFlexRow)` @@ -19,22 +16,18 @@ const Container = styled(AlignedFlexRow)` interface ContactsPlateProps { publicKey: string; name: string; - accountHash: string; + csprName: Maybe | undefined; + brandingLogo: Maybe | undefined; } export const ContactsPlate = ({ publicKey, name, - accountHash + csprName, + brandingLogo }: ContactsPlateProps) => { const navigate = useTypedNavigate(); - const contactPublicKeys = useSelector(selectAllContactsPublicKeys); - const accountsInfo = useFetchAccountsInfo(contactPublicKeys); - - const csprName = accountsInfo && accountsInfo[accountHash]?.csprName; - const brandingLogo = accountsInfo && accountsInfo[accountHash]?.brandingLogo; - return ( { const contacts = useSelector(selectAllContacts); const lastModified = useSelector(selectLastModified); + const contactPublicKeys = useSelector(selectAllContactsPublicKeys); const contactsWithId = contacts.map((contact, index) => ({ ...contact, @@ -31,6 +34,8 @@ export const ContactsBookPageContent = () => { accountHash: getAccountHashFromPublicKey(contact.publicKey) })); + const accountsInfo = useFetchAccountsInfo(contactPublicKeys); + if (contactsWithId.length === 0) { return ; } @@ -53,13 +58,20 @@ export const ContactsBookPageContent = () => { )} ( - - )} + renderRow={({ publicKey, name, accountHash }) => { + const csprName = accountsInfo && accountsInfo[accountHash]?.csprName; + const brandingLogo = + accountsInfo && accountsInfo[accountHash]?.brandingLogo; + + return ( + + ); + }} marginLeftForItemSeparatorLine={54} /> diff --git a/src/libs/layout/header/header-connection-status.tsx b/src/libs/layout/header/header-connection-status.tsx index 1f1ce3af..839c0245 100644 --- a/src/libs/layout/header/header-connection-status.tsx +++ b/src/libs/layout/header/header-connection-status.tsx @@ -1,7 +1,10 @@ import React from 'react'; import { useSelector } from 'react-redux'; -import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; +import { + selectVaultAccountsPublicKeys, + selectVaultActiveAccount +} from '@background/redux/vault/selectors'; import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { @@ -30,8 +33,9 @@ export function HeaderConnectionStatus({ isConnected }: HeaderConnectionStatusProps) { const activeAccount = useSelector(selectVaultActiveAccount); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); - const accountsInfo = useFetchAccountsInfo([activeAccount?.publicKey!]); + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); const accountHash = getAccountHashFromPublicKey(activeAccount?.publicKey); diff --git a/src/libs/services/account-info/use-fetch-accounts-info.ts b/src/libs/services/account-info/use-fetch-accounts-info.ts index c550555f..273eb881 100644 --- a/src/libs/services/account-info/use-fetch-accounts-info.ts +++ b/src/libs/services/account-info/use-fetch-accounts-info.ts @@ -19,7 +19,7 @@ export const useFetchAccountsInfo = (accountPublicKeys: string[]) => { const accountHashesString = accountHashes.toString(); const { data: accountsInfo } = useQuery({ - queryKey: ['ACCOUNT_INFO', accountHashesString], + queryKey: ['ACCOUNT_INFO', accountHashesString, network], queryFn: async () => { return await accountInfoRepository.getAccountsInfo({ accountHashes, diff --git a/src/libs/ui/components/active-account-plate/active-account-plate.tsx b/src/libs/ui/components/active-account-plate/active-account-plate.tsx index 439e6327..0886945e 100644 --- a/src/libs/ui/components/active-account-plate/active-account-plate.tsx +++ b/src/libs/ui/components/active-account-plate/active-account-plate.tsx @@ -3,7 +3,10 @@ import { Trans, useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; -import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; +import { + selectVaultAccountsPublicKeys, + selectVaultActiveAccount +} from '@background/redux/vault/selectors'; import { getAccountHashFromPublicKey } from '@libs/entities/Account'; import { @@ -56,11 +59,11 @@ export const ActiveAccountPlate = ({ const { t } = useTranslation(); const activeAccount = useSelector(selectVaultActiveAccount); + const accountsPublicKeys = useSelector(selectVaultAccountsPublicKeys); - const accountsInfo = useFetchAccountsInfo([activeAccount?.publicKey!]); + const accountsInfo = useFetchAccountsInfo(accountsPublicKeys); const accountHash = getAccountHashFromPublicKey(activeAccount?.publicKey); - const csprName = accountsInfo && accountsInfo[accountHash]?.csprName; const brandingLogo = accountsInfo && accountsInfo[accountHash]?.brandingLogo; diff --git a/src/libs/ui/forms/form-validation-rules.ts b/src/libs/ui/forms/form-validation-rules.ts index 09ca5a2a..1732c8ee 100644 --- a/src/libs/ui/forms/form-validation-rules.ts +++ b/src/libs/ui/forms/form-validation-rules.ts @@ -137,7 +137,9 @@ export const useRecipientPublicKeyRule = () => { return false; }, - message: t('Recipient should be a valid public key or cspr name') + message: t( + 'The recipient should be a valid public key, CSPR.name or contact name' + ) }); }; From 80627026cb1a1e0047ddcf1bdee0c90605089247 Mon Sep 17 00:00:00 2001 From: Ostap Piatkovskyi <44294945+ost-ptk@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:02:19 +0200 Subject: [PATCH 4/5] fix: change condition for enabling the send NFT token button (#1070) * changed condition for enabling the send NFT token button * skip e2e test `should redirect to Ramp provider page` --- e2e-tests/popup/buy-cspr/buy-cspr.spec.ts | 2 +- src/apps/popup/pages/nft-details/content.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/popup/buy-cspr/buy-cspr.spec.ts b/e2e-tests/popup/buy-cspr/buy-cspr.spec.ts index 15ee207d..ea073682 100644 --- a/e2e-tests/popup/buy-cspr/buy-cspr.spec.ts +++ b/e2e-tests/popup/buy-cspr/buy-cspr.spec.ts @@ -39,7 +39,7 @@ popup.describe('Popup UI: buy cspr', () => { } ); - popup( + popup.skip( 'should redirect to Ramp provider page', async ({ popupPage, unlockVault, context }) => { await unlockVault(); diff --git a/src/apps/popup/pages/nft-details/content.tsx b/src/apps/popup/pages/nft-details/content.tsx index f24a017b..3253b1e0 100644 --- a/src/apps/popup/pages/nft-details/content.tsx +++ b/src/apps/popup/pages/nft-details/content.tsx @@ -154,7 +154,7 @@ export const NftDetailsContent = ({ ); if (extendedDeployInfo) { - if (extendedDeployInfo.status === Status.Executed) { + if (extendedDeployInfo.status !== Status.Pending) { dispatchToMainStore( accountTrackingIdOfSentNftTokensRemoved(nftToken?.tracking_id!) ); From 32959a6a4074a3a389a84ebf57d5df33a7c072f0 Mon Sep 17 00:00:00 2001 From: Ostap Piatkovskyi <44294945+ost-ptk@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:03:47 +0200 Subject: [PATCH 5/5] feature: add Terms & Conditions and Privacy Policy link to the navigation menu (#1073) * added Terms & Conditions and Privacy Policy link to the navigation menu * moved urls to constants * removed unused constants --- .../pages/create-vault-password/index.tsx | 6 ++-- .../popup/pages/navigation-menu/index.tsx | 30 +++++++++++++++---- src/constants.ts | 24 +++++++-------- src/libs/services/deployer-service/index.ts | 6 ++-- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/apps/onboarding/pages/create-vault-password/index.tsx b/src/apps/onboarding/pages/create-vault-password/index.tsx index efbd80f1..0c08c95e 100644 --- a/src/apps/onboarding/pages/create-vault-password/index.tsx +++ b/src/apps/onboarding/pages/create-vault-password/index.tsx @@ -3,7 +3,7 @@ import { useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; -import { TermsLink } from '@src/constants'; +import { TERMS_URLS } from '@src/constants'; import { Stepper } from '@onboarding/components/stepper'; import { RouterPath } from '@onboarding/router'; @@ -69,7 +69,7 @@ export function CreateVaultPasswordPage({ onClick={event => { event.stopPropagation(); event.preventDefault(); - window.open(TermsLink.Tos, '_blank'); + window.open(TERMS_URLS.tos, '_blank'); }} color="contentAction" > @@ -80,7 +80,7 @@ export function CreateVaultPasswordPage({ onClick={event => { event.stopPropagation(); event.preventDefault(); - window.open(TermsLink.Privacy, '_blank'); + window.open(TERMS_URLS.privacy, '_blank'); }} color="contentAction" > diff --git a/src/apps/popup/pages/navigation-menu/index.tsx b/src/apps/popup/pages/navigation-menu/index.tsx index ac068c39..fc5377a1 100644 --- a/src/apps/popup/pages/navigation-menu/index.tsx +++ b/src/apps/popup/pages/navigation-menu/index.tsx @@ -3,6 +3,12 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; +import { + ABOUT_US_URL, + SHARE_FEEDBACK_URL, + TERMS_URLS, + USER_GUIDES_URL +} from '@src/constants'; import { isLedgerAvailable, isSafariBuild } from '@src/utils'; import { TimeoutDurationSetting } from '@popup/constants'; @@ -320,23 +326,37 @@ export function NavigationMenuPageContent() { items: [ { id: 1, + title: t('Terms & Conditions'), + iconPath: 'assets/icons/books.svg', + href: TERMS_URLS.tos, + disabled: false + }, + { + id: 2, + title: t('Privacy Policy'), + iconPath: 'assets/icons/books.svg', + href: TERMS_URLS.privacy, + disabled: false + }, + { + id: 3, title: t('Share feedback'), iconPath: 'assets/icons/chat.svg', - href: 'https://casper-wallet.canny.io/feature-requests', + href: SHARE_FEEDBACK_URL, disabled: false }, { - id: 2, + id: 4, title: t('User guides'), iconPath: 'assets/icons/books.svg', - href: 'https://casperwallet.io/user-guide', + href: USER_GUIDES_URL, disabled: false }, { - id: 3, + id: 5, title: t('About us'), iconPath: 'assets/icons/team.svg', - href: 'https://make.services/', + href: ABOUT_US_URL, disabled: false } ] diff --git a/src/constants.ts b/src/constants.ts index 91835661..a52b7fc0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,17 +1,10 @@ const SECOND = 1000; -export const FETCH_QUERY_OPTIONS = { - // cached for 30 sec - apiCacheTime: 30 * SECOND -}; - export const BALANCE_REFRESH_RATE = 15 * SECOND; export const CURRENCY_REFRESH_RATE = 30 * SECOND; export const TOKENS_REFRESH_RATE = 15 * SECOND; export const NFT_TOKENS_REFRESH_RATE = 60 * SECOND; -export const ACCOUNT_DEPLOY_REFRESH_RATE = 30 * SECOND; export const ACCOUNT_CASPER_ACTIVITY_REFRESH_RATE = 30 * SECOND; -export const ERC20_TOKEN_ACTIVITY_REFRESH_RATE = 30 * SECOND; export const VALIDATORS_REFRESH_RATE = 30 * SECOND; export const PENDING_DEPLOY_REFETCH_INTERVAL = 5 * SECOND; export const DEPLOY_DETAILS_REFRESH_RATE = 30 * SECOND; @@ -29,6 +22,16 @@ export const STAKE_COST_MOTES = '2500000000'; // 2.5 CSPR export const DELEGATION_MIN_AMOUNT_MOTES = '500000000000'; // 500 CSPR export const MAX_DELEGATORS = 1200; +export const USER_GUIDES_URL = 'https://casperwallet.io/user-guide'; +export const SHARE_FEEDBACK_URL = + 'https://casper-wallet.canny.io/feature-requests'; +export const ABOUT_US_URL = 'https://make.services'; +export const TERMS_URLS = { + tos: 'https://www.casperwallet.io/tos', + privacy: 'https://www.casperwallet.io/privacy' +}; +export const REFERRER_URL = 'https://casperwallet.io'; + export const getBlockExplorerAccountUrl = ( casperLiveUrl: string, publicKey: string @@ -84,18 +87,11 @@ export enum Browser { Edge = 'edge' } -export enum TermsLink { - Tos = 'https://www.casperwallet.io/tos', - Privacy = 'https://www.casperwallet.io/privacy' -} - export enum CasperNodeUrl { MainnetUrl = 'https://node.cspr.cloud/rpc', TestnetUrl = 'https://node.testnet.cspr.cloud/rpc' } -export const ReferrerUrl = 'https://casperwallet.io'; - export enum NetworkName { Mainnet = 'casper', Testnet = 'casper-test' diff --git a/src/libs/services/deployer-service/index.ts b/src/libs/services/deployer-service/index.ts index 6dbe61b0..c97b4270 100644 --- a/src/libs/services/deployer-service/index.ts +++ b/src/libs/services/deployer-service/index.ts @@ -13,7 +13,7 @@ import { AuctionManagerEntryPoint, CasperNodeUrl, NetworkName, - ReferrerUrl, + REFERRER_URL, STAKE_COST_MOTES, TRANSFER_COST_MOTES } from '@src/constants'; @@ -51,7 +51,7 @@ export const getDateForDeploy = async (nodeUrl: CasperNodeUrl) => { const casperNodeTimestamp: ICasperNodeStatusResponse = await fetch( `${nodeUrl}/info_get_status`, { - referrer: ReferrerUrl + referrer: REFERRER_URL } ).then(toJson); @@ -274,7 +274,7 @@ export const sendSignDeploy = ( return fetch(nodeUrl, { method: 'POST', - referrer: ReferrerUrl, + referrer: REFERRER_URL, body: JSON.stringify({ jsonrpc: '2.0', method: 'account_put_deploy',