diff --git a/jest.config.js b/jest.config.js index 51e0c3218..814361c41 100644 --- a/jest.config.js +++ b/jest.config.js @@ -27,7 +27,6 @@ module.exports = { '!src/i18n/*', '!src/setupTests.js', '!src/setupProxy.js', - '!src/rootReducer.js', '!src/registerServiceWorker.js', '!src/containers/shared/images/*', '!src/containers/test/*', diff --git a/package-lock.json b/package-lock.json index e5fcdbd81..5d8daf0c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "dependencies": { "@google-cloud/bigquery": "^7.9.1", "@paystring/utils": "^2.0.0", - "@redux-devtools/extension": "^3.3.0", "@rollup/plugin-inject": "^5.0.5", "@vitejs/plugin-react": "^4.2.1", "@xrplf/isomorphic": "^1.0.0-beta.1", @@ -43,14 +42,10 @@ "react-helmet-async": "^2.0.4", "react-i18next": "^12.3.1", "react-query": "^3.39.3", - "react-redux": "^8.1.3", "react-router": "^6.12.1", "react-router-dom": "^6.26.1", "react18-json-view": "^0.2.8", "recharts": "^2.12.7", - "redux": "^5.0.1", - "redux-logger": "^3.0.6", - "redux-thunk": "^2.2.0", "ripple-address-codec": "^5.0.0", "topojson-client": "^3.0.0", "usehooks-ts": "^3.1.0", @@ -72,7 +67,6 @@ "@types/node": "^18.19.33", "@types/react": "^17.0.39", "@types/react-dom": "^17.0.9", - "@types/react-redux": "^7.1.22", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^6.21.0", "babel-jest": "^29.7.0", @@ -99,7 +93,6 @@ "prettier": "^3.3.2", "react-error-overlay": "6.0.11", "react-test-renderer": "^17.0.2", - "redux-mock-store": "^1.5.1", "sass": "^1.80.5", "source-map-explorer": "^2.5.3", "stylelint": "^15.11.0", @@ -5784,18 +5777,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@redux-devtools/extension": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", - "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "immutable": "^4.3.4" - }, - "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" - } - }, "node_modules/@remix-run/router": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz", @@ -6579,14 +6560,6 @@ "@types/node": "*" } }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.3", "dev": true, @@ -6670,10 +6643,12 @@ }, "node_modules/@types/prop-types": { "version": "15.7.4", + "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "17.0.39", + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -6683,34 +6658,15 @@ }, "node_modules/@types/react-dom": { "version": "17.0.9", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-redux": { - "version": "7.1.22", "dev": true, "license": "MIT", "dependencies": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" - } - }, - "node_modules/@types/react-redux/node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.9.2" + "@types/react": "*" } }, "node_modules/@types/scheduler": { "version": "0.16.2", + "dev": true, "license": "MIT" }, "node_modules/@types/semver": { @@ -6724,11 +6680,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" - }, "node_modules/@types/yargs": { "version": "13.0.11", "dev": true, @@ -10509,10 +10460,6 @@ "node": ">=8" } }, - "node_modules/deep-diff": { - "version": "0.3.8", - "license": "MIT" - }, "node_modules/deep-equal": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", @@ -13985,13 +13932,6 @@ "he": "bin/he" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" - } - }, "node_modules/hosted-git-info": { "version": "2.8.9", "dev": true, @@ -14201,7 +14141,8 @@ "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "devOptional": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -21851,11 +21792,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.istypedarray": { "version": "3.0.6", "dev": true, @@ -24035,49 +23971,6 @@ } } }, - "node_modules/react-redux": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", - "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", - "dependencies": { - "@babel/runtime": "^7.12.1", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/use-sync-external-store": "^0.0.3", - "hoist-non-react-statics": "^3.3.2", - "react-is": "^18.0.0", - "use-sync-external-store": "^1.0.0" - }, - "peerDependencies": { - "@types/react": "^16.8 || ^17.0 || ^18.0", - "@types/react-dom": "^16.8 || ^17.0 || ^18.0", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0", - "react-native": ">=0.59", - "redux": "^4 || ^5.0.0-beta.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, - "node_modules/react-redux/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, "node_modules/react-router": { "version": "6.26.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz", @@ -24280,30 +24173,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" - }, - "node_modules/redux-logger": { - "version": "3.0.6", - "license": "MIT", - "dependencies": { - "deep-diff": "^0.3.5" - } - }, - "node_modules/redux-mock-store": { - "version": "1.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.isplainobject": "^4.0.6" - } - }, - "node_modules/redux-thunk": { - "version": "2.3.0", - "license": "MIT" - }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -27813,14 +27682,6 @@ "node": ">=0.10.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/usehooks-ts": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.0.tgz", @@ -32710,15 +32571,6 @@ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true }, - "@redux-devtools/extension": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", - "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", - "requires": { - "@babel/runtime": "^7.23.2", - "immutable": "^4.3.4" - } - }, "@remix-run/router": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz", @@ -33220,13 +33072,6 @@ "@types/node": "*" } }, - "@types/hoist-non-react-statics": { - "version": "3.3.1", - "requires": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "dev": true @@ -33303,10 +33148,12 @@ "peer": true }, "@types/prop-types": { - "version": "15.7.4" + "version": "15.7.4", + "dev": true }, "@types/react": { "version": "17.0.39", + "dev": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -33315,34 +33162,14 @@ }, "@types/react-dom": { "version": "17.0.9", - "devOptional": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-redux": { - "version": "7.1.22", "dev": true, "requires": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" - }, - "dependencies": { - "redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dev": true, - "requires": { - "@babel/runtime": "^7.9.2" - } - } + "@types/react": "*" } }, "@types/scheduler": { - "version": "0.16.2" + "version": "0.16.2", + "dev": true }, "@types/semver": { "version": "7.5.0", @@ -33354,11 +33181,6 @@ "version": "1.0.1", "dev": true }, - "@types/use-sync-external-store": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" - }, "@types/yargs": { "version": "13.0.11", "dev": true, @@ -35949,9 +35771,6 @@ "mimic-response": "^2.0.0" } }, - "deep-diff": { - "version": "0.3.8" - }, "deep-equal": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", @@ -38349,12 +38168,6 @@ "he": { "version": "1.2.0" }, - "hoist-non-react-statics": { - "version": "3.3.2", - "requires": { - "react-is": "^16.7.0" - } - }, "hosted-git-info": { "version": "2.8.9", "dev": true @@ -38493,7 +38306,8 @@ "immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "devOptional": true }, "import-fresh": { "version": "3.3.0", @@ -43795,10 +43609,6 @@ "version": "4.5.0", "dev": true }, - "lodash.isplainobject": { - "version": "4.0.6", - "dev": true - }, "lodash.istypedarray": { "version": "3.0.6", "dev": true @@ -45202,26 +45012,6 @@ "match-sorter": "^6.0.2" } }, - "react-redux": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", - "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", - "requires": { - "@babel/runtime": "^7.12.1", - "@types/hoist-non-react-statics": "^3.3.1", - "@types/use-sync-external-store": "^0.0.3", - "hoist-non-react-statics": "^3.3.2", - "react-is": "^18.0.0", - "use-sync-external-store": "^1.0.0" - }, - "dependencies": { - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - } - } - }, "react-router": { "version": "6.26.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz", @@ -45360,27 +45150,6 @@ "strip-indent": "^4.0.0" } }, - "redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" - }, - "redux-logger": { - "version": "3.0.6", - "requires": { - "deep-diff": "^0.3.5" - } - }, - "redux-mock-store": { - "version": "1.5.4", - "dev": true, - "requires": { - "lodash.isplainobject": "^4.0.6" - } - }, - "redux-thunk": { - "version": "2.3.0" - }, "reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -47774,12 +47543,6 @@ "version": "3.1.1", "dev": true }, - "use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "requires": {} - }, "usehooks-ts": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.0.tgz", diff --git a/package.json b/package.json index d44571646..3cd3640ec 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "dependencies": { "@google-cloud/bigquery": "^7.9.1", "@paystring/utils": "^2.0.0", - "@redux-devtools/extension": "^3.3.0", "@rollup/plugin-inject": "^5.0.5", "@vitejs/plugin-react": "^4.2.1", "@xrplf/isomorphic": "^1.0.0-beta.1", @@ -38,14 +37,10 @@ "react-helmet-async": "^2.0.4", "react-i18next": "^12.3.1", "react-query": "^3.39.3", - "react-redux": "^8.1.3", "react-router": "^6.12.1", "react-router-dom": "^6.26.1", "react18-json-view": "^0.2.8", "recharts": "^2.12.7", - "redux": "^5.0.1", - "redux-logger": "^3.0.6", - "redux-thunk": "^2.2.0", "ripple-address-codec": "^5.0.0", "topojson-client": "^3.0.0", "usehooks-ts": "^3.1.0", @@ -67,7 +62,6 @@ "@types/node": "^18.19.33", "@types/react": "^17.0.39", "@types/react-dom": "^17.0.9", - "@types/react-redux": "^7.1.22", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^6.21.0", "babel-jest": "^29.7.0", @@ -94,7 +88,6 @@ "prettier": "^3.3.2", "react-error-overlay": "6.0.11", "react-test-renderer": "^17.0.2", - "redux-mock-store": "^1.5.1", "sass": "^1.80.5", "source-map-explorer": "^2.5.3", "stylelint": "^15.11.0", diff --git a/server/routes/v1/tokenDiscovery.js b/server/routes/v1/tokenDiscovery.js index 7448d4e09..8bf552a93 100644 --- a/server/routes/v1/tokenDiscovery.js +++ b/server/routes/v1/tokenDiscovery.js @@ -36,7 +36,7 @@ async function getAccountInfo(issuer, currencyCode) { const domain = info.Domain ? Buffer.from(info.Domain, 'hex').toString() : undefined - return { domain, gravatar: info.urlgravatar, obligations } + return { domain, obligations } } async function getExchangeRate(issuer, currencyCode) { @@ -101,11 +101,10 @@ async function getTokensList() { // eslint-disable-next-line no-await-in-loop -- okay here, helps run slower so we don't get rate limited const [accountInfo, exchangeRate] = await Promise.all(promises) - const { domain, gravatar, obligations } = accountInfo + const { domain, obligations } = accountInfo const newInfo = { ...rankedTokens[i], domain, - gravatar, obligations, exchangeRate, } diff --git a/src/containers/Accounts/AccountAssetTab/AccountAssetTab.tsx b/src/containers/Accounts/AccountAssetTab/AccountAssetTab.tsx index 2832e2834..c7347fe0d 100644 --- a/src/containers/Accounts/AccountAssetTab/AccountAssetTab.tsx +++ b/src/containers/Accounts/AccountAssetTab/AccountAssetTab.tsx @@ -1,6 +1,5 @@ import { ChangeEvent } from 'react' import { useTranslation } from 'react-i18next' -import { connect } from 'react-redux' import { useNavigate } from 'react-router' import { useRouteParams } from '../../shared/routing' import { AccountIssuedTokenTable } from '../AccountIssuedTokenTable' @@ -15,7 +14,7 @@ interface Props { let assetTypes = ['issued', 'nft'] -const AccountAssetTabDisconnected = ({ account }: Props) => { +export const AccountAssetTab = ({ account }: Props) => { const { id: accountId = '', assetType = assetTypes[0] } = useRouteParams(ACCOUNT_ROUTE) @@ -66,7 +65,3 @@ const AccountAssetTabDisconnected = ({ account }: Props) => { ) } - -export const AccountAssetTab = connect((state: any) => ({ - account: state.accountHeader.data, -}))(AccountAssetTabDisconnected) diff --git a/src/containers/Accounts/AccountHeader/actionTypes.js b/src/containers/Accounts/AccountHeader/actionTypes.js deleted file mode 100644 index c539d0ce4..000000000 --- a/src/containers/Accounts/AccountHeader/actionTypes.js +++ /dev/null @@ -1,4 +0,0 @@ -export const START_LOADING_ACCOUNT_STATE = 'START_LOADING_ACCOUNT_STATE' -export const FINISHED_LOADING_ACCOUNT_STATE = 'FINISHED_LOADING_ACCOUNT_STATE' -export const ACCOUNT_STATE_LOAD_SUCCESS = 'ACCOUNT_STATE_LOAD_SUCCESS' -export const ACCOUNT_STATE_LOAD_FAIL = 'ACCOUNT_STATE_LOAD_FAIL' diff --git a/src/containers/Accounts/AccountHeader/actions.js b/src/containers/Accounts/AccountHeader/actions.js deleted file mode 100644 index 61e0dc53b..000000000 --- a/src/containers/Accounts/AccountHeader/actions.js +++ /dev/null @@ -1,42 +0,0 @@ -import { isValidClassicAddress, isValidXAddress } from 'ripple-address-codec' -import { getAccountState } from '../../../rippled' -import { analytics } from '../../shared/analytics' -import { BAD_REQUEST } from '../../shared/utils' -import * as actionTypes from './actionTypes' - -export const loadAccountState = (accountId, rippledSocket) => (dispatch) => { - if (!isValidClassicAddress(accountId) && !isValidXAddress(accountId)) { - dispatch({ - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - status: BAD_REQUEST, - error: '', - }) - return Promise.resolve() - } - - dispatch({ - type: actionTypes.START_LOADING_ACCOUNT_STATE, - }) - return getAccountState(accountId, rippledSocket) - .then((data) => { - dispatch({ type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }) - dispatch({ - type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, - data, - }) - }) - .catch((error) => { - const status = error.code - analytics.trackException( - `getAccountState ${accountId} --- ${JSON.stringify(error)}`, - ) - dispatch({ type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }) - dispatch({ - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - error: status === 500 ? 'get_account_state_failed' : '', - status, - }) - }) -} - -export default loadAccountState diff --git a/src/containers/Accounts/AccountHeader/index.tsx b/src/containers/Accounts/AccountHeader/index.tsx index 3c04aff64..7d929915c 100644 --- a/src/containers/Accounts/AccountHeader/index.tsx +++ b/src/containers/Accounts/AccountHeader/index.tsx @@ -1,18 +1,20 @@ import { useContext, useEffect } from 'react' import { Trans, useTranslation } from 'react-i18next' -import { connect } from 'react-redux' -import { bindActionCreators } from 'redux' -import { loadAccountState } from './actions' +import { useQuery } from 'react-query' +import { isValidClassicAddress, isValidXAddress } from 'ripple-address-codec' import { Loader } from '../../shared/components/Loader' import './styles.scss' import { BalanceSelector } from './BalanceSelector/BalanceSelector' import { Account } from '../../shared/components/Account' -import { localizeNumber } from '../../shared/utils' +import { BAD_REQUEST, localizeNumber } from '../../shared/utils' import SocketContext from '../../shared/SocketContext' import InfoIcon from '../../shared/images/info.svg' import { useLanguage } from '../../shared/hooks' import Currency from '../../shared/components/Currency' import DomainLink from '../../shared/components/DomainLink' +import { getAccountState } from '../../../rippled' +import { useAnalytics } from '../../shared/analytics' +import { AccountState } from '../../../rippled/accountState' const CURRENCY_OPTIONS = { style: 'currency', @@ -24,70 +26,45 @@ const CURRENCY_OPTIONS = { interface AccountHeaderProps { onSetCurrencySelected: (currency: string) => void currencySelected: string - loading: boolean accountId: string - data: { - balances: { - XRP: number - } - paychannels: { - // eslint-disable-next-line camelcase - total_available: string - channels: any[] - } - escrows: { - totalIn: number - totalOut: number - } - signerList: { - signers: { - account: string - weight: number - }[] - quorum: number - maxSigners: number - } - info: { - reserve: number - sequence: number - ticketCount: number - domain: string - emailHash: string - flags: string[] - nftMinter: string - } - xAddress: { - classicAddress: string - tag: number | boolean - test: boolean - } - deleted: boolean - hasBridge: boolean - } - actions: { - loadAccountState: typeof loadAccountState - } } -const AccountHeader = (props: AccountHeaderProps) => { +export const AccountHeader = ({ + accountId, + onSetCurrencySelected, + currencySelected, +}: AccountHeaderProps) => { const { t } = useTranslation() const rippledSocket = useContext(SocketContext) const language = useLanguage() + const { trackException, trackScreenLoaded } = useAnalytics() + + const { data: accountState, isLoading } = useQuery( + ['accountState', accountId], + () => { + if (!isValidClassicAddress(accountId) && !isValidXAddress(accountId)) { + return Promise.reject(BAD_REQUEST) + } + + return getAccountState(accountId, rippledSocket).catch( + (transactionRequestError) => { + const status = transactionRequestError.code + trackException( + `ledger ${accountId} --- ${JSON.stringify( + transactionRequestError, + )}`, + ) + return Promise.reject(status) + }, + ) + }, + ) - const { - accountId, - actions, - data, - onSetCurrencySelected, - currencySelected, - loading, - } = props - const { deleted } = data useEffect(() => { - actions.loadAccountState(accountId, rippledSocket) - }, [accountId, actions, rippledSocket]) + trackScreenLoaded() + }, [trackScreenLoaded]) - function renderBalancesSelector() { + function renderBalancesSelector(data: AccountState) { const { balances = {} } = data return ( Object.keys(balances).length > 1 && ( @@ -102,7 +79,7 @@ const AccountHeader = (props: AccountHeaderProps) => { ) } - function renderPaymentChannels() { + function renderPaymentChannels(data: AccountState) { const { paychannels } = data return ( paychannels && ( @@ -127,7 +104,7 @@ const AccountHeader = (props: AccountHeaderProps) => { ) } - function renderEscrows() { + function renderEscrows(data: AccountState) { const { escrows } = data return ( escrows && ( @@ -152,7 +129,7 @@ const AccountHeader = (props: AccountHeaderProps) => { ) } - function renderSignerList() { + function renderSignerList(data: AccountState) { const { signerList } = data return ( signerList && ( @@ -183,7 +160,7 @@ const AccountHeader = (props: AccountHeaderProps) => { } // TODO: show X-address on 'classic' account pages - function renderExtendedAddress() { + function renderExtendedAddress(data: AccountState) { const { xAddress } = data // undefined when page has not yet finished loading let messageAboutTag: JSX.Element | string = '' @@ -238,7 +215,7 @@ const AccountHeader = (props: AccountHeaderProps) => { ) } - function renderInfo() { + function renderInfo(data: AccountState) { const { info } = data return ( info && ( @@ -298,8 +275,8 @@ const AccountHeader = (props: AccountHeaderProps) => { ) } - function renderHeaderContent() { - const { balances = {} } = data + function renderHeaderContent(data: AccountState) { + const { balances = {}, deleted } = data const balance = localizeNumber( balances[currencySelected] || 0.0, language, @@ -313,7 +290,7 @@ const AccountHeader = (props: AccountHeaderProps) => { return (
- {renderExtendedAddress()} + {renderExtendedAddress(data)}
{deleted ? (
@@ -333,22 +310,24 @@ const AccountHeader = (props: AccountHeaderProps) => {
{balance}
)} - {renderBalancesSelector()} + {renderBalancesSelector(data)}
- {renderInfo()} - {renderEscrows()} - {renderPaymentChannels()} + {renderInfo(data)} + {renderEscrows(data)} + {renderPaymentChannels(data)}
-
{renderSignerList()}
+
{renderSignerList(data)}
) } - const { xAddress, hasBridge } = data + const xAddress = accountState?.xAddress ?? false + const hasBridge = accountState?.hasBridge ?? false + return (
@@ -359,23 +338,9 @@ const AccountHeader = (props: AccountHeaderProps) => {

{accountId}

- {loading ? : renderHeaderContent()} + {isLoading && } + {accountState != null && renderHeaderContent(accountState)}
) } - -export default connect( - (state: any) => ({ - loading: state.accountHeader.loading, - data: state.accountHeader.data, - }), - (dispatch) => ({ - actions: bindActionCreators( - { - loadAccountState, - }, - dispatch, - ), - }), -)(AccountHeader) diff --git a/src/containers/Accounts/AccountHeader/reducer.js b/src/containers/Accounts/AccountHeader/reducer.js deleted file mode 100644 index 5ed1273fb..000000000 --- a/src/containers/Accounts/AccountHeader/reducer.js +++ /dev/null @@ -1,33 +0,0 @@ -import * as actionTypes from './actionTypes' - -export const initialState = { - loading: false, - data: {}, - error: '', - status: null, -} - -// eslint-disable-next-line default-param-last -const accountReducer = (state = initialState, action) => { - switch (action.type) { - case actionTypes.START_LOADING_ACCOUNT_STATE: - return { ...state, loading: true } - case actionTypes.FINISHED_LOADING_ACCOUNT_STATE: - return { ...state, loading: false } - case actionTypes.ACCOUNT_STATE_LOAD_SUCCESS: - return { ...state, error: '', data: action.data } - case actionTypes.ACCOUNT_STATE_LOAD_FAIL: - return { - ...state, - error: action.error, - status: action.status, - data: state.data.length ? state.data : {}, - } - case 'persist/REHYDRATE': - return { ...initialState } - default: - return state - } -} - -export default accountReducer diff --git a/src/containers/Accounts/AccountHeader/test/AccountHeader.test.tsx b/src/containers/Accounts/AccountHeader/test/AccountHeader.test.tsx new file mode 100644 index 000000000..a5598e5ee --- /dev/null +++ b/src/containers/Accounts/AccountHeader/test/AccountHeader.test.tsx @@ -0,0 +1,282 @@ +import { mount } from 'enzyme' +import { QueryClientProvider } from 'react-query' +import { I18nextProvider } from 'react-i18next' +import { BrowserRouter } from 'react-router-dom' +import { testQueryClient } from '../../../test/QueryClient' +import i18n from '../../../../i18n/testConfig' +import { AccountHeader } from '..' +import { getAccountState } from '../../../../rippled' +import Mock = jest.Mock +import { flushPromises } from '../../../test/utils' + +const TEST_ADDRESS = 'rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv' +const TEST_X_ADDRESS = 'XV3oNHx95sqdCkTDCBCVsVeuBmvh2dz5fTZvfw8UCcMVsfe' + +jest.mock('../../../../rippled', () => ({ + __esModule: true, + getAccountState: jest.fn(), +})) + +const mockedGetAccountState = getAccountState as Mock + +describe('AccountHeader Actions', () => { + const createWrapper = (account = TEST_ADDRESS) => + mount( + + + + + + + , + ) + + beforeEach(() => { + jest.resetModules() + }) + + it('successful account header', async () => { + mockedGetAccountState.mockImplementation(() => + Promise.resolve({ + account: TEST_ADDRESS, + ledger_index: 68990183, + info: { + sequence: 2148991, + ticketCount: undefined, + ownerCount: 0, + reserve: 10, + tick: undefined, + rate: undefined, + domain: undefined, + emailHash: undefined, + flags: [], + balance: '123456000', + nftMinter: undefined, + previousTxn: + '6B6F2CA1633A22247058E988372BA9EFFFC5BF10212230B67341CA32DC9D4A82', + previousLedger: 68990183, + }, + deleted: false, + balances: { XRP: 123.456 }, + signerList: undefined, + tokens: [], + escrows: undefined, + paychannels: null, + xAddress: undefined, + hasBridge: false, + }), + ) + + const wrapper = createWrapper() + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe(TEST_ADDRESS) + + wrapper.unmount() + }) + + it('account with tokens', async () => { + mockedGetAccountState.mockImplementation(() => + Promise.resolve({ + account: 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY', + ledger_index: 72338736, + info: { + sequence: 1227, + ticketCount: undefined, + ownerCount: 28, + reserve: 66, + tick: undefined, + rate: undefined, + domain: undefined, + emailHash: undefined, + flags: [], + balance: '1172875760329', + previousTxn: + '259A84CE4B3B09D5FBCAA133F62FC767CA2B57B3C64CF065F7546AA63D55E070', + previousLedger: 67657581, + }, + balances: { + '0158415500000000C1F76FF6ECB0BAC600000000': 3.692385398244198, + BTC: 1.075524263886059, + CHF: 0.7519685210971255, + CNY: 12.328638002, + DYM: 95.13258522535791, + EUR: 53.426387263174405, + GBP: 79.51188949705619, + JPY: 4986.30908732758, + USD: 936.8290046958887, + XAU: 3.419442510305086, + XRP: 1172875.760329, + }, + signerList: undefined, + tokens: [ + { + amount: 95.13258522535791, + currency: 'DYM', + issuer: 'rGwUWgN5BEg3QGNY3RX2HfYowjUTZdid3E', + }, + { + amount: 20, + currency: 'USD', + issuer: 'rME7HanzUymzFvETpoLgAy5rvxGcKiLrYL', + }, + { + amount: 255.7836054268899, + currency: 'USD', + issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q', + }, + { + amount: 1.075524263886059, + currency: 'BTC', + issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q', + }, + { + amount: 12.328638002, + currency: 'CNY', + issuer: 'rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK', + }, + { + amount: 3.419442510305086, + currency: 'XAU', + issuer: 'rrh7rf1gV2pXAoqA8oYbpHd8TKv5ZQeo67', + }, + { + amount: 3.692385398244198, + currency: '0158415500000000C1F76FF6ECB0BAC600000000', + issuer: 'rrh7rf1gV2pXAoqA8oYbpHd8TKv5ZQeo67', + }, + { + amount: 0.7519685210971255, + currency: 'CHF', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + }, + { + amount: 78.5098894970562, + currency: 'GBP', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + }, + { + amount: 4986.30908732758, + currency: 'JPY', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + }, + { + amount: 28.42638726317441, + currency: 'EUR', + issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', + }, + ], + escrows: undefined, + paychannels: null, + xAddress: undefined, + hasBridge: false, + deleted: false, + }), + ) + + const wrapper = createWrapper() + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe(TEST_ADDRESS) + expect(wrapper.find('.balance-selector-container')).toExist() + expect(wrapper.find('.balance .value').text()).toBe('\uE9001,172,875.76') + + wrapper.unmount() + }) + + it('X-Address', async () => { + mockedGetAccountState.mockImplementation(() => + Promise.resolve({ + account: TEST_ADDRESS, + ledger_index: 68990183, + info: { + sequence: 2148991, + ticketCount: undefined, + ownerCount: 0, + reserve: 10, + tick: undefined, + rate: undefined, + domain: undefined, + emailHash: undefined, + flags: [], + balance: '123456000', + nftMinter: undefined, + previousTxn: + '6B6F2CA1633A22247058E988372BA9EFFFC5BF10212230B67341CA32DC9D4A82', + previousLedger: 68990183, + }, + deleted: false, + balances: { XRP: 123.456 }, + signerList: undefined, + tokens: [], + escrows: undefined, + hasBridge: false, + paychannels: null, + xAddress: { + classicAddress: TEST_ADDRESS, + tag: 0, + test: false, + }, + }), + ) + + const wrapper = createWrapper(TEST_X_ADDRESS) + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe(TEST_X_ADDRESS) + + wrapper.unmount() + }) + + it('server error', async () => { + mockedGetAccountState.mockImplementation(() => Promise.reject()) + + const wrapper = createWrapper() + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe(TEST_ADDRESS) + expect(wrapper.find('.header-container')).not.toExist() + + wrapper.unmount() + }) + + it('invalid address', async () => { + const wrapper = createWrapper('ZZZ') + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe('ZZZ') + expect(wrapper.find('.header-container')).not.toExist() + + wrapper.unmount() + }) + + it('deleted account', async () => { + mockedGetAccountState.mockImplementation(() => + Promise.resolve({ + account: TEST_ADDRESS, + deleted: true, + xAddress: undefined, + }), + ) + + const wrapper = createWrapper() + await flushPromises() + wrapper.update() + + expect(wrapper.find('h1').text()).toBe(TEST_ADDRESS) + expect(wrapper.find('.warning').find('.account-deleted-text').text()).toBe( + 'Account Deleted', + ) + + wrapper.unmount() + }) +}) diff --git a/src/containers/Accounts/AccountHeader/test/actions.test.js b/src/containers/Accounts/AccountHeader/test/actions.test.js deleted file mode 100644 index 797787a05..000000000 --- a/src/containers/Accounts/AccountHeader/test/actions.test.js +++ /dev/null @@ -1,312 +0,0 @@ -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import * as actions from '../actions' -import * as actionTypes from '../actionTypes' -import { initialState } from '../reducer' -import { NOT_FOUND, BAD_REQUEST, SERVER_ERROR } from '../../../shared/utils' -import rippledResponses from './rippledResponses.json' -import accountDeletedTransactions from './accountDeletedTransactions.json' -import actNotFound from '../../../Token/TokenHeader/test/actNotFound.json' -import actWithTokens from './accountWithTokens.json' -import MockWsClient from '../../../test/mockWsClient' - -const TEST_ADDRESS = 'rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv' -const TEST_X_ADDRESS = 'XV3oNHx95sqdCkTDCBCVsVeuBmvh2dz5fTZvfw8UCcMVsfe' - -describe('AccountHeader Actions', () => { - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - let client - beforeEach(() => { - client = new MockWsClient() - }) - - afterEach(() => { - client.close() - }) - - it('should dispatch correct actions on successful loadAccountState', () => { - client.addResponses(rippledResponses) - const expectedData = { - account: 'rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv', - ledger_index: 68990183, - info: { - sequence: 2148991, - ticketCount: undefined, - ownerCount: 0, - reserve: 10, - tick: undefined, - rate: undefined, - domain: undefined, - emailHash: undefined, - flags: [], - balance: '123456000', - nftMinter: undefined, - previousTxn: - '6B6F2CA1633A22247058E988372BA9EFFFC5BF10212230B67341CA32DC9D4A82', - previousLedger: 68990183, - }, - deleted: false, - balances: { XRP: 123.456 }, - signerList: undefined, - tokens: [], - escrows: undefined, - paychannels: null, - xAddress: undefined, - hasBridge: false, - } - const expectedActions = [ - { type: actionTypes.START_LOADING_ACCOUNT_STATE }, - { type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }, - { type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, data: expectedData }, - ] - const store = mockStore({ news: initialState }) - - return store - .dispatch(actions.loadAccountState(TEST_ADDRESS, client)) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on account with tokens', () => { - client.addResponses(actWithTokens) - const expectedData = { - account: 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY', - ledger_index: 72338736, - info: { - sequence: 1227, - ticketCount: undefined, - ownerCount: 28, - reserve: 66, - tick: undefined, - rate: undefined, - domain: undefined, - emailHash: undefined, - flags: [], - balance: '1172875760329', - previousTxn: - '259A84CE4B3B09D5FBCAA133F62FC767CA2B57B3C64CF065F7546AA63D55E070', - previousLedger: 67657581, - }, - balances: { - '0158415500000000C1F76FF6ECB0BAC600000000': 3.692385398244198, - BTC: 1.075524263886059, - CHF: 0.7519685210971255, - CNY: 12.328638002, - DYM: 95.13258522535791, - EUR: 53.426387263174405, - GBP: 79.51188949705619, - JPY: 4986.30908732758, - USD: 936.8290046958887, - XAU: 3.419442510305086, - XRP: 1172875.760329, - }, - signerList: undefined, - tokens: [ - { - amount: 95.13258522535791, - currency: 'DYM', - issuer: 'rGwUWgN5BEg3QGNY3RX2HfYowjUTZdid3E', - }, - { - amount: 20, - currency: 'USD', - issuer: 'rME7HanzUymzFvETpoLgAy5rvxGcKiLrYL', - }, - { - amount: 255.7836054268899, - currency: 'USD', - issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q', - }, - { - amount: 1.075524263886059, - currency: 'BTC', - issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q', - }, - { - amount: 12.328638002, - currency: 'CNY', - issuer: 'rnuF96W4SZoCJmbHYBFoJZpR8eCaxNvekK', - }, - { - amount: 3.419442510305086, - currency: 'XAU', - issuer: 'rrh7rf1gV2pXAoqA8oYbpHd8TKv5ZQeo67', - }, - { - amount: 3.692385398244198, - currency: '0158415500000000C1F76FF6ECB0BAC600000000', - issuer: 'rrh7rf1gV2pXAoqA8oYbpHd8TKv5ZQeo67', - }, - { - amount: 0.7519685210971255, - currency: 'CHF', - issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - }, - { - amount: 78.5098894970562, - currency: 'GBP', - issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - }, - { - amount: 4986.30908732758, - currency: 'JPY', - issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - }, - { - amount: 28.42638726317441, - currency: 'EUR', - issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - }, - ], - escrows: undefined, - paychannels: null, - xAddress: undefined, - hasBridge: false, - deleted: false, - } - const expectedActions = [ - { type: actionTypes.START_LOADING_ACCOUNT_STATE }, - { type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }, - { type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, data: expectedData }, - ] - const store = mockStore({ news: initialState }) - - return store - .dispatch(actions.loadAccountState(TEST_ADDRESS, client)) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on successful loadAccountState for X-Address', () => { - client.addResponses(rippledResponses) - const expectedData = { - account: 'rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv', - ledger_index: 68990183, - info: { - sequence: 2148991, - ticketCount: undefined, - ownerCount: 0, - reserve: 10, - tick: undefined, - rate: undefined, - domain: undefined, - emailHash: undefined, - flags: [], - balance: '123456000', - nftMinter: undefined, - previousTxn: - '6B6F2CA1633A22247058E988372BA9EFFFC5BF10212230B67341CA32DC9D4A82', - previousLedger: 68990183, - }, - deleted: false, - balances: { XRP: 123.456 }, - signerList: undefined, - tokens: [], - escrows: undefined, - hasBridge: false, - paychannels: null, - xAddress: { - classicAddress: 'rDsbeomae4FXwgQTJp9Rs64Qg9vDiTCdBv', - tag: 0, - test: false, - }, - } - const expectedActions = [ - { type: actionTypes.START_LOADING_ACCOUNT_STATE }, - { type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }, - { type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, data: expectedData }, - ] - const store = mockStore({ news: initialState }) - return store - .dispatch(actions.loadAccountState(TEST_X_ADDRESS, client)) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on server error', () => { - client.setReturnError() - const expectedActions = [ - { type: actionTypes.START_LOADING_ACCOUNT_STATE }, - { type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }, - { - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - status: SERVER_ERROR, - error: 'get_account_state_failed', - }, - ] - const store = mockStore({ news: initialState }) - - return store - .dispatch(actions.loadAccountState(TEST_ADDRESS, client)) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on address not found', () => { - const expectedActions = [ - { type: actionTypes.START_LOADING_ACCOUNT_STATE }, - { type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE }, - { - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - status: NOT_FOUND, - error: '', - }, - ] - client.addResponse('account_info', { result: actNotFound }) - client.addResponse('account_tx', { result: actNotFound }) - const store = mockStore({ news: initialState }) - return store - .dispatch(actions.loadAccountState(TEST_ADDRESS, client)) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on invalid address', () => { - const expectedActions = [ - { - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - status: BAD_REQUEST, - error: '', - }, - ] - const store = mockStore({ news: initialState }) - store.dispatch(actions.loadAccountState('ZZZ', client)).then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) - - it('should dispatch correct actions on a deleted account', () => { - client.addResponses(accountDeletedTransactions) - - const expectedActions = [ - { - type: 'START_LOADING_ACCOUNT_STATE', - }, - { - type: 'FINISHED_LOADING_ACCOUNT_STATE', - }, - { - type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, - data: { - account: 'r35jYntLwkrbc3edisgavDbEdNRSKgcQE6', - deleted: true, - xAddress: undefined, - }, - }, - ] - const store = mockStore({ news: initialState }) - store - .dispatch( - actions.loadAccountState('r35jYntLwkrbc3edisgavDbEdNRSKgcQE6', client), - ) - .then(() => { - expect(store.getActions()).toEqual(expectedActions) - }) - }) -}) diff --git a/src/containers/Accounts/AccountHeader/test/reducer.test.js b/src/containers/Accounts/AccountHeader/test/reducer.test.js deleted file mode 100644 index ceecc491f..000000000 --- a/src/containers/Accounts/AccountHeader/test/reducer.test.js +++ /dev/null @@ -1,79 +0,0 @@ -import * as actionTypes from '../actionTypes' -import reducer, { initialState } from '../reducer' - -describe('AccountHeader reducers', () => { - it('should return the initial state', () => { - expect(reducer(undefined, {})).toEqual(initialState) - }) - - it('should handle START_LOADING_ACCOUNT_STATE', () => { - const nextState = { ...initialState, loading: true } - expect( - reducer(initialState, { type: actionTypes.START_LOADING_ACCOUNT_STATE }), - ).toEqual(nextState) - }) - - it('should handle FINISHED_LOADING_ACCOUNT_STATE', () => { - const nextState = { ...initialState, loading: false } - expect( - reducer(initialState, { - type: actionTypes.FINISHED_LOADING_ACCOUNT_STATE, - }), - ).toEqual(nextState) - }) - - it('should handle ACCOUNT_STATE_LOAD_SUCCESS', () => { - const data = [['XRP', 123.456]] - const nextState = { ...initialState, data } - expect( - reducer(initialState, { - data, - type: actionTypes.ACCOUNT_STATE_LOAD_SUCCESS, - }), - ).toEqual(nextState) - }) - - it('should handle ACCOUNT_STATE_LOAD_FAIL', () => { - const status = 500 - const error = 'error' - const nextState = { ...initialState, status, error } - expect( - reducer(initialState, { - status, - error, - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - }), - ).toEqual(nextState) - }) - - it('will not clear previous data on ACCOUNT_STATE_LOAD_FAIL', () => { - const data = [['XRP', 123.456]] - const error = 'error' - const status = 500 - const stateWithData = { ...initialState, data } - const nextState = { ...stateWithData, error, status } - expect( - reducer(stateWithData, { - status, - error, - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - }), - ).toEqual(nextState) - }) - - it('should clear data on rehydration', () => { - const error = 'error' - const status = 500 - const nextState = { ...initialState, error, status } - expect( - reducer(initialState, { - type: actionTypes.ACCOUNT_STATE_LOAD_FAIL, - error, - status, - }), - ).toEqual(nextState) - expect(reducer(nextState, { type: 'persist/REHYDRATE' })).toEqual( - initialState, - ) - }) -}) diff --git a/src/containers/Accounts/AccountNFTTable/test/AccountNFTtable.test.tsx b/src/containers/Accounts/AccountNFTTable/test/AccountNFTtable.test.tsx index 1ba9a9609..6b9ed48e0 100644 --- a/src/containers/Accounts/AccountNFTTable/test/AccountNFTtable.test.tsx +++ b/src/containers/Accounts/AccountNFTTable/test/AccountNFTtable.test.tsx @@ -52,8 +52,6 @@ describe('AccountNFTTable component', () => { }) it('should render a table of nfts', async () => { - mockedGetAccountNFTs.mockReset() - mockedGetAccountNFTs.mockImplementation(() => Promise.resolve(data)) const wrapper = createWrapper() @@ -66,8 +64,6 @@ describe('AccountNFTTable component', () => { }) it('should handle load more', async () => { - mockedGetAccountNFTs.mockReset() - mockedGetAccountNFTs.mockImplementation(() => Promise.resolve({ ...data, @@ -92,8 +88,6 @@ describe('AccountNFTTable component', () => { }) it(`should handle no results`, async () => { - mockedGetAccountNFTs.mockReset() - mockedGetAccountNFTs.mockImplementation(() => Promise.resolve({ account: 'rnuweigWrt8Jp1gBmKJT6VLxrVMSJSuu6G', diff --git a/src/containers/Accounts/index.tsx b/src/containers/Accounts/index.tsx index 8f6361d6b..dfdbd539d 100644 --- a/src/containers/Accounts/index.tsx +++ b/src/containers/Accounts/index.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' import { Helmet } from 'react-helmet-async' -import AccountHeader from './AccountHeader' +import { AccountHeader } from './AccountHeader' import { AccountTransactionTable } from './AccountTransactionTable' import './styles.scss' import { useAnalytics } from '../shared/analytics' @@ -44,7 +44,7 @@ export const Accounts = () => { hasTokensColumn={false} /> )} - {tab === 'assets' && } + {tab === 'assets' && } )}
diff --git a/src/containers/Accounts/test/index.test.tsx b/src/containers/Accounts/test/index.test.tsx index efd512f38..555cff680 100644 --- a/src/containers/Accounts/test/index.test.tsx +++ b/src/containers/Accounts/test/index.test.tsx @@ -1,53 +1,54 @@ import { mount } from 'enzyme' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' import { Route } from 'react-router' -import { initialState } from '../../../rootReducer' import i18n from '../../../i18n/testConfig' import { Accounts } from '../index' -import AccountHeader from '../AccountHeader' +import { AccountHeader } from '../AccountHeader' import { AccountTransactionTable } from '../AccountTransactionTable' import mockAccountState from './mockAccountState.json' -import { QuickHarness } from '../../test/utils' +import { QuickHarness, flushPromises } from '../../test/utils' import { ACCOUNT_ROUTE } from '../../App/routes' +import { getAccountState } from '../../../rippled' +import Mock = jest.Mock + +jest.mock('../../../rippled', () => ({ + __esModule: true, + getAccountState: jest.fn(), + getAccountTransactions: jest.fn(() => []), +})) + +const mockedGetAccountState = getAccountState as Mock describe('Account container', () => { - const TEST_ACCOUNT_ID = 'rTEST_ACCOUNT' - - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const createWrapper = (state = {}) => { - const store = mockStore({ ...initialState, ...state }) - return mount( - - - } /> - - , + const TEST_ACCOUNT_ID = 'rncKvRcdDq9hVJpdLdTcKoxsS3NSkXsvfM' + + const createWrapper = () => + mount( + + } /> + , ) - } + + beforeEach(() => { + jest.resetModules() + }) it('renders without crashing', () => { const wrapper = createWrapper() wrapper.unmount() }) - it('renders static parts', () => { - const state = { - ...initialState, - accountHeader: { - loading: false, - error: null, - data: mockAccountState, - }, - } - - const wrapper = createWrapper(state) + it('renders static parts', async () => { + mockedGetAccountState.mockImplementation(() => + Promise.resolve(mockAccountState), + ) + + const wrapper = createWrapper() + await flushPromises() wrapper.update() + expect(wrapper.find(AccountHeader).length).toBe(1) expect(wrapper.find(AccountTransactionTable).length).toBe(1) wrapper.find('.balance-selector button').simulate('click') diff --git a/src/containers/Amendment/amendment.scss b/src/containers/Amendment/amendment.scss index 2dd439d43..8c5caa035 100644 --- a/src/containers/Amendment/amendment.scss +++ b/src/containers/Amendment/amendment.scss @@ -62,7 +62,7 @@ .value { &.eta { - &.no{ + &.no { color: $yellow-50 !important; } } diff --git a/src/containers/Amendments/amendmentsTable.scss b/src/containers/Amendments/amendmentsTable.scss index 15805be26..1c14d683a 100644 --- a/src/containers/Amendments/amendmentsTable.scss +++ b/src/containers/Amendments/amendmentsTable.scss @@ -1,7 +1,7 @@ @use '../shared/css/variables' as *; @use '../shared/css/table'; -.amendments-page{ +.amendments-page { .summary { padding: 0 16px; margin-top: 100px; @@ -100,7 +100,9 @@ } } - .version, .enabled, .consensus { + .version, + .enabled, + .consensus { max-width: 70px; overflow-wrap: break-word; @include for-size(tablet-portrait-up) { diff --git a/src/containers/App/test/App.test.jsx b/src/containers/App/test/App.test.jsx index 886d08a59..e4275e659 100644 --- a/src/containers/App/test/App.test.jsx +++ b/src/containers/App/test/App.test.jsx @@ -2,11 +2,7 @@ import { mount } from 'enzyme' import moxios from 'moxios' import { MemoryRouter } from 'react-router' import { I18nextProvider } from 'react-i18next' -import configureMockStore from 'redux-mock-store' -import { Provider } from 'react-redux' -import thunk from 'redux-thunk' import { XrplClient } from 'xrpl-client' -import { initialState } from '../../../rootReducer' import i18n from '../../../i18n/testConfig' import { AppWrapper } from '../index' import MockWsClient from '../../test/mockWsClient' @@ -70,7 +66,6 @@ const mockXrplClient = XrplClient const mockGetAccountInfo = getAccountInfo describe('App container', () => { - const mockStore = configureMockStore([thunk]) const createWrapper = ( path = '/', localNetworks = [], @@ -89,15 +84,12 @@ describe('App container', () => { ) } - const store = mockStore(initialState) return mount( - - - - - - - , + + + + + , ) } @@ -304,6 +296,12 @@ describe('App container', () => { event: 'screen_view', network: 'mainnet', }, + { + page_path: '/accounts/rKV8HEL3vLc6q9waTiJcewdRdSFyx67QFb#ssss', + page_title: 'xrpl_explorer | rKV8HEL3vLc6...', + event: 'screen_view', + network: 'mainnet', + }, ]) }) }) @@ -340,6 +338,12 @@ describe('App container', () => { event: 'screen_view', network: 'mainnet', }, + { + page_path: '/accounts/r35jYntLwkrbc3edisgavDbEdNRSKgcQE6#ssss', + page_title: `xrpl_explorer | r35jYntLwkrb...`, + event: 'screen_view', + network: 'mainnet', + }, ]) expect(mockGetAccountInfo).toBeCalledWith( expect.anything(), @@ -361,6 +365,13 @@ describe('App container', () => { event: 'screen_view', network: 'mainnet', }, + { + page_path: + '/accounts/XVVFXHFdehYhofb7XRWeJYV6kjTEwboaHpB9S1ruYMsuXcG#ssss', + page_title: `xrpl_explorer | XVVFXHFdehYh...`, + event: 'screen_view', + network: 'mainnet', + }, ]) expect(mockGetAccountInfo).toBeCalledWith( expect.anything(), @@ -421,6 +432,12 @@ describe('App container', () => { event: 'screen_view', network: 'mainnet', }, + { + page_path: '/accounts/rKV8HEL3vLc6q9waTiJcewdRdSFyx67QFb#ssss', + page_title: 'xrpl_explorer | rKV8HEL3vLc6...', + event: 'screen_view', + network: 'mainnet', + }, ]) }) }) diff --git a/src/containers/CustomNetworkHome/test/CustomNetworkHome.test.js b/src/containers/CustomNetworkHome/test/CustomNetworkHome.test.js index f57ae01c3..3e22b08ca 100644 --- a/src/containers/CustomNetworkHome/test/CustomNetworkHome.test.js +++ b/src/containers/CustomNetworkHome/test/CustomNetworkHome.test.js @@ -1,8 +1,4 @@ import { mount } from 'enzyme' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' -import { initialState } from '../../../rootReducer' import i18n from '../../../i18n/testConfig' import SidechainHome from '../index' import MockWsClient from '../../test/mockWsClient' @@ -13,9 +9,6 @@ describe('SidechainHome page', () => { let client let wrapper - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const createWrapper = (localNetworks = null) => { localStorage.removeItem(CUSTOM_NETWORKS_STORAGE_KEY) if (localNetworks) { @@ -25,13 +18,10 @@ describe('SidechainHome page', () => { ) } - const store = mockStore(initialState) return mount( - - - - - , + + + , ) } diff --git a/src/containers/Header/Banner.tsx b/src/containers/Header/Banner.tsx deleted file mode 100644 index 09334deac..000000000 --- a/src/containers/Header/Banner.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { FC } from 'react' -import { connect } from 'react-redux' -import { useTranslation } from 'react-i18next' -import { Notification } from '../shared/components/Notification' - -const BannerInner: FC<{ messages: [[string, string]] }> = ({ messages }) => { - const { t } = useTranslation() - return ( -
- {messages.map((d) => ( - - ))} -
- ) -} - -export const Banner = connect((state: any) => { - const messages = [['balanceError', state.accountHeader.error]] - - return { - messages: messages.filter((d) => Boolean(d[1])) as [[string, string]], - } -})(BannerInner) diff --git a/src/containers/Header/index.tsx b/src/containers/Header/index.tsx index 5ee021570..ea5dd5a81 100644 --- a/src/containers/Header/index.tsx +++ b/src/containers/Header/index.tsx @@ -1,7 +1,6 @@ import { FC } from 'react' import classnames from 'classnames' -import { Banner } from './Banner' import { navigationConfig } from '../App/navigation' import { NavigationMenu } from './NavigationMenu' @@ -15,7 +14,6 @@ export const Header: FC<{ inNetwork?: boolean }> = ({ inNetwork = true }) => ( - ) diff --git a/src/containers/Header/search.scss b/src/containers/Header/search.scss index b599fd295..00604a57d 100644 --- a/src/containers/Header/search.scss +++ b/src/containers/Header/search.scss @@ -89,7 +89,7 @@ top: 60px; } - @media (max-width: $tablet-portrait-upper-boundary){ + @media (max-width: $tablet-portrait-upper-boundary) { left: 5%; width: 90%; } @@ -102,6 +102,6 @@ border-width: 8px; border-style: solid; border-color: $blue-purple-30 transparent transparent transparent; - content: ""; + content: ''; transform: translateX(-50%); } diff --git a/src/containers/Header/test/Banner.test.tsx b/src/containers/Header/test/Banner.test.tsx deleted file mode 100644 index 95ba1a918..000000000 --- a/src/containers/Header/test/Banner.test.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { mount } from 'enzyme' -import { I18nextProvider } from 'react-i18next' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' -import { initialState } from '../../../rootReducer' -import i18n from '../../../i18n/testConfig' -import { Banner } from '../Banner' - -describe('Banner component', () => { - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const createWrapper = (state = initialState) => { - const store = mockStore(state) - return mount( - - - - - , - ) - } - - it('renders without crashing', () => { - const wrapper = createWrapper() - wrapper.unmount() - }) - - it('renders with messages', () => { - const state = { - ...initialState, - } - - const wrapper = createWrapper(state) - expect(wrapper.find('.notification').length).toEqual(0) - wrapper.unmount() - }) -}) diff --git a/src/containers/Header/test/Header.test.tsx b/src/containers/Header/test/Header.test.tsx index 635ed837d..c911ecc36 100644 --- a/src/containers/Header/test/Header.test.tsx +++ b/src/containers/Header/test/Header.test.tsx @@ -1,11 +1,7 @@ import { mount } from 'enzyme' import { I18nextProvider } from 'react-i18next' import { BrowserRouter as Router } from 'react-router-dom' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' import { QueryClientProvider } from 'react-query' -import { initialState } from '../../../rootReducer' import i18n from '../../../i18n/testConfigEnglish' import SocketContext from '../../shared/SocketContext' import MockWsClient from '../../test/mockWsClient' @@ -14,25 +10,18 @@ import { queryClient } from '../../shared/QueryClient' describe('Header component', () => { let client - // Redux setup required for - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const createWrapper = () => { - const store = mockStore({ ...initialState }) - return mount( + const createWrapper = () => + mount( - - - -
- - - + + +
+ + , ) - } beforeEach(() => { client = new MockWsClient() diff --git a/src/containers/Ledgers/Legend.tsx b/src/containers/Ledgers/Legend.tsx index d4a408fbc..33922b634 100644 --- a/src/containers/Ledgers/Legend.tsx +++ b/src/containers/Ledgers/Legend.tsx @@ -18,7 +18,6 @@ export const Legend = () => { useLocalStorage(LEGEND_STORAGE_KEY, false) const [hidden, setHidden] = useState(previousInteraction) - // TODO: use global variables when we update places using width from redux. // Show legend by default when on desktop sizes useEffect(() => { if (previousInteraction === false) { diff --git a/src/containers/Ledgers/test/LedgersPage.test.js b/src/containers/Ledgers/test/LedgersPage.test.js index 925372e07..adfc2aeca 100644 --- a/src/containers/Ledgers/test/LedgersPage.test.js +++ b/src/containers/Ledgers/test/LedgersPage.test.js @@ -1,12 +1,8 @@ import { mount } from 'enzyme' import moxios from 'moxios' import WS from 'jest-websocket-mock' -import configureMockStore from 'redux-mock-store' -import thunk from 'redux-thunk' -import { Provider } from 'react-redux' import i18n from '../../../i18n/testConfig' import { LedgersPage } from '../index' -import { initialState } from '../../../rootReducer' import SocketContext from '../../shared/SocketContext' import NetworkContext from '../../shared/NetworkContext' import BaseMockWsClient from '../../test/mockWsClient' @@ -80,25 +76,18 @@ const WS_URL = 'ws://localhost:1234' describe('Ledgers Page container', () => { let server let client - const middlewares = [thunk] - const mockStore = configureMockStore(middlewares) - const createWrapper = (props = { network: 'main', path: '/' }) => { - const store = mockStore({ ...initialState }) - - return mount( - - - - - - - - - - - , + const createWrapper = (props = { network: 'main', path: '/' }) => + mount( + + + + + + + + + , ) - } const oldEnvs = process.env diff --git a/src/containers/Token/TokenHeader/index.tsx b/src/containers/Token/TokenHeader/index.tsx index a3b3ddcfc..c22ba9e7c 100644 --- a/src/containers/Token/TokenHeader/index.tsx +++ b/src/containers/Token/TokenHeader/index.tsx @@ -9,6 +9,7 @@ import { useLanguage } from '../../shared/hooks' import { LEDGER_ROUTE, TRANSACTION_ROUTE } from '../../App/routes' import { RouteLink } from '../../shared/routing' import { TokenData } from '../../../rippled/token' +import { XRP_BASE } from '../../shared/transactionUtils' const CURRENCY_OPTIONS = { style: 'currency', @@ -119,7 +120,7 @@ export const TokenHeader = ({ const renderHeaderContent = () => { const { balance, sequence, obligations, reserve } = data const currencyBalance = localizeNumber( - parseInt(balance, 10) / 1000000 || 0.0, + parseInt(balance, 10) / XRP_BASE || 0.0, language, CURRENCY_OPTIONS, ) diff --git a/src/containers/Token/test/index.test.tsx b/src/containers/Token/test/index.test.tsx index 2ff37ad5a..7b8a5ddaa 100644 --- a/src/containers/Token/test/index.test.tsx +++ b/src/containers/Token/test/index.test.tsx @@ -15,6 +15,11 @@ jest.mock('../../../rippled', () => ({ getToken: jest.fn(), })) +jest.mock('../../../rippled', () => ({ + __esModule: true, + getToken: jest.fn(), +})) + describe('Token container', () => { const TEST_ACCOUNT_ID = 'rTEST_ACCOUNT' @@ -30,6 +35,10 @@ describe('Token container', () => { ) } + beforeEach(() => { + jest.resetModules() + }) + it('renders without crashing', () => { const wrapper = createWrapper() wrapper.unmount() diff --git a/src/containers/Transactions/simpleTab.scss b/src/containers/Transactions/simpleTab.scss index 978ef28f3..e29bc8c0a 100644 --- a/src/containers/Transactions/simpleTab.scss +++ b/src/containers/Transactions/simpleTab.scss @@ -68,7 +68,7 @@ $subdued-color: $black-40; &.list { margin-bottom: 12px; - .one-line{ + .one-line { justify-content: flex-end; margin: -1px 0px 0px; } diff --git a/src/containers/Validators/votingTab.scss b/src/containers/Validators/votingTab.scss index eb6c7a489..a39c61ae9 100644 --- a/src/containers/Validators/votingTab.scss +++ b/src/containers/Validators/votingTab.scss @@ -66,7 +66,7 @@ &.nay { background-color: $black-30; } -} + } .no-match { &.no-match-amendments { diff --git a/src/containers/shared/components/TokenSearchResults/styles.scss b/src/containers/shared/components/TokenSearchResults/styles.scss index beec5b9de..db18ff27d 100644 --- a/src/containers/shared/components/TokenSearchResults/styles.scss +++ b/src/containers/shared/components/TokenSearchResults/styles.scss @@ -125,7 +125,6 @@ background: transparent; color: $blue-purple-30; } - } .issuer-address { diff --git a/src/index.tsx b/src/index.tsx index 5eff37e4d..36c5d4778 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,30 +1,19 @@ import { Suspense } from 'react' import ReactDOM from 'react-dom' import { BrowserRouter as Router } from 'react-router-dom' -import { Provider } from 'react-redux' -import { compose, applyMiddleware, createStore } from 'redux' -import thunk from 'redux-thunk' import { I18nextProvider } from 'react-i18next' -import reduxLogger from 'redux-logger' -import { composeWithDevTools } from '@redux-devtools/extension' -import rootReducer from './rootReducer' import { unregister } from './registerServiceWorker' import './containers/shared/css/global.scss' import { AppWrapper } from './containers/App' import i18n from './i18n' -let enhancers -let store - const renderApp = () => { ReactDOM.render( - - - - - + + + , document.getElementById('xrpl-explorer'), @@ -33,19 +22,11 @@ const renderApp = () => { const isDevelopment = process.env.NODE_ENV === 'development' -const middlewarePackages = [thunk] -let middleware = applyMiddleware(...middlewarePackages) if (isDevelopment) { localStorage.setItem('debug', 'xrpl-debug:*') - middlewarePackages.push(reduxLogger) - middleware = applyMiddleware(...middlewarePackages) - enhancers = composeWithDevTools(middleware) - store = createStore(rootReducer, enhancers) renderApp() } else { localStorage.removeItem('debug') - enhancers = compose(middleware) - store = createStore(rootReducer, enhancers) renderApp() } diff --git a/src/rippled/accountState.js b/src/rippled/accountState.ts similarity index 73% rename from src/rippled/accountState.js rename to src/rippled/accountState.ts index 8a03d309d..122cb8fdc 100644 --- a/src/rippled/accountState.js +++ b/src/rippled/accountState.ts @@ -20,13 +20,61 @@ import { } from './lib/rippled' import logger from './lib/logger' import { formatAccountInfo, formatSignerList } from './lib/utils' +import type { ExplorerAmount } from '../containers/shared/types' +import type { ExplorerXrplClient } from '../containers/shared/SocketContext' + +interface XAddress { + classicAddress: string + tag: number | false + test: boolean +} + +export interface AccountState { + account: string + balances: { + XRP: number + } + paychannels?: { + // eslint-disable-next-line camelcase + total_available: number + channels: any[] + } + escrows?: { + totalIn: number + totalOut: number + } + signerList?: { + signers: { + account: string + weight: number + }[] + quorum: number + maxSigners: number + } + info: { + reserve: number + sequence?: number + ticketCount: number + domain?: string + emailHash?: string + flags: string[] + nftMinter?: string + } + xAddress?: { + classicAddress: string + tag: number | boolean + test: boolean + } + deleted: boolean + hasBridge: boolean +} const log = logger({ name: 'account balances' }) const formatBalances = (info, data) => { const balances = { XRP: Number(info.Balance) / 1000000 } const { assets = {}, obligations = {} } = data - const tokens = [] + const tokens: ExplorerAmount[] = [] Object.keys(obligations).forEach((currency) => { if (!balances[currency]) { @@ -56,11 +104,14 @@ const formatBalances = (info, data) => { tokens, } } -const getAccountState = (account, rippledSocket) => { +async function getAccountState( + account: string, + rippledSocket: ExplorerXrplClient, +): Promise { // TODO: Retrieve balances for untagged X-address only? or display notice/warning - let classicAddress - let decomposedAddress = null + let classicAddress: string + let decomposedAddress: XAddress | null = null try { if (!isValidClassicAddress(account) && !isValidXAddress(account)) { @@ -85,7 +136,7 @@ const getAccountState = (account, rippledSocket) => { } else { classicAddress = account } - } catch (error) { + } catch (error: any) { log.error(error.toString()) throw error } @@ -101,8 +152,7 @@ const getAccountState = (account, rippledSocket) => { getServerInfo(rippledSocket), getAccountBridges(rippledSocket, classicAddress), ]).then((data) => ({ - account: info.Account, - ledger_index: info.ledger_index, + account: info.Account as string, info: formatAccountInfo(info, data[3].info.validated_ledger), balances: data[0].balances, tokens: data[0].tokens, @@ -128,6 +178,9 @@ const getAccountState = (account, rippledSocket) => { account: classicAddress, deleted: true, xAddress: decomposedAddress || undefined, + balances: { XRP: 0 }, + hasBridge: false, + info: { reserve: 0, ticketCount: 0, flags: [] }, } } throw error diff --git a/src/rippled/lib/rippled.js b/src/rippled/lib/rippled.js index 89f47ad6e..4f86e6a5a 100644 --- a/src/rippled/lib/rippled.js +++ b/src/rippled/lib/rippled.js @@ -274,7 +274,7 @@ const getAccountPaychannels = async ( return getChannels(resp.marker) } - return null + return undefined }) await getChannels() @@ -287,7 +287,7 @@ const getAccountPaychannels = async ( channels, total_available: remaining / XRP_BASE, } - : null + : undefined } // get account escrows diff --git a/src/rippled/lib/utils.js b/src/rippled/lib/utils.js index a1b19680e..e49603078 100644 --- a/src/rippled/lib/utils.js +++ b/src/rippled/lib/utils.js @@ -82,7 +82,6 @@ const formatAccountInfo = (info, serverInfoValidated) => ({ emailHash: info.EmailHash, flags: buildFlags(info.Flags, ACCOUNT_FLAGS), balance: info.Balance, - gravatar: info.urlgravatar, previousTxn: info.PreviousTxnID, previousLedger: info.PreviousTxnLgrSeq, nftMinter: info.NFTokenMinter, diff --git a/src/rippled/token.ts b/src/rippled/token.ts index 9f6d8736d..ab1adebd9 100644 --- a/src/rippled/token.ts +++ b/src/rippled/token.ts @@ -1,15 +1,14 @@ import logger from './lib/logger' import { formatAccountInfo } from './lib/utils' import { getBalances, getAccountInfo, getServerInfo } from './lib/rippled' +import type { ExplorerXrplClient } from '../containers/shared/SocketContext' const log = logger({ name: 'iou' }) export interface TokenData { - name: string balance: string reserve: number sequence: number - gravatar: string rate?: number obligations?: string domain?: string @@ -19,11 +18,11 @@ export interface TokenData { flags: string[] } -const getToken = async ( - currencyCode, - issuer, - rippledSocket, -): Promise => { +async function getToken( + currencyCode: string, + issuer: string, + rippledSocket: ExplorerXrplClient, +): Promise { try { log.info('fetching account info from rippled') const accountInfo = await getAccountInfo(rippledSocket, issuer) @@ -38,7 +37,6 @@ const getToken = async ( } const { - name, reserve, sequence, rate, @@ -46,13 +44,11 @@ const getToken = async ( emailHash, balance, flags, - gravatar, previousTxn, previousLedger, } = formatAccountInfo(accountInfo, serverInfo.info.validated_ledger) return { - name, reserve, sequence, rate, @@ -60,7 +56,6 @@ const getToken = async ( emailHash, balance, flags, - gravatar, obligations, previousTxn, previousLedger, diff --git a/src/rootReducer.js b/src/rootReducer.js deleted file mode 100644 index 0ad9a2f70..000000000 --- a/src/rootReducer.js +++ /dev/null @@ -1,14 +0,0 @@ -import { combineReducers } from 'redux' -import accountHeaderReducer, { - initialState as accountHeaderState, -} from './containers/Accounts/AccountHeader/reducer' - -export const initialState = { - accountHeader: accountHeaderState, -} - -const rootReducer = combineReducers({ - accountHeader: accountHeaderReducer, -}) - -export default rootReducer