diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index a183cdd7..f4408f1a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -23,23 +23,23 @@ jobs: - name: Install packages run: yarn && cd src/frontend-elements && yarn - - name: Build + - name: Build for Mainnet run: yarn build env: SASS_PATH: "node_modules:src/styles" GENERATE_SOURCEMAP: "false" - REACT_APP_RPC_URL: "https://node0.testnet.lum.network/rpc" + REACT_APP_RPC_URL: "https://node0.mainnet.lum.network/rpc" - name: Test run: yarn test - - name: Deploy + - name: Deploy Mainnet Preview uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}' expires: 7d projectId: lum-network - target: lum-network-wallet-testnet + target: lum-network-wallet env: FIREBASE_CLI_PREVIEWS: hostingchannels diff --git a/config-overrides.js b/config-overrides.js index 96e55500..65b8d42d 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -14,6 +14,7 @@ module.exports = { buffer: require.resolve('buffer'), }; config.resolve.modules = [path.resolve(__dirname, 'src'), 'node_modules']; + config.plugins = [ ...config.plugins, new webpack.ProvidePlugin({ @@ -21,6 +22,13 @@ module.exports = { }), ]; + config.module.rules.push({ + test: /\.m?js$/, + resolve: { + fullySpecified: false, + }, + }); + return config; }, jest: function (config) { @@ -29,12 +37,13 @@ module.exports = { '^.+\\.(ts|tsx)$': 'ts-jest', }; - config.transformIgnorePatterns = ['node_modules/(?!(axios))']; + config.transformIgnorePatterns = ['/node_modules/(?!(@ledgerhq))']; config.moduleNameMapper = { ...config.moduleNameMapper, '\\.(css|scss)$': 'identity-obj-proxy', - '@ledgerhq/devices': '@ledgerhq/devices/lib', + '@ledgerhq/devices': '@ledgerhq/devices/lib-es', + axios: 'axios/dist/node/axios.cjs', }; return config; diff --git a/jest.config.js b/jest.config.js index 4025a68e..34bcd853 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { preset: 'ts-jest', - testEnvironment: 'node', + testEnvironment: 'jsdom', moduleDirectories: ['node_modules'], roots: [''], }; diff --git a/package.json b/package.json index 8c1b15d5..a809002c 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,18 @@ "version": "0.1.0", "private": true, "dependencies": { - "@ledgerhq/hw-transport-webusb": "^6.7.0", - "@lum-network/sdk-javascript": "^0.8.7", + "@cosmjs/amino": "0.32.1", + "@cosmjs/crypto": "0.32.1", + "@cosmjs/ledger-amino": "0.32.1", + "@cosmjs/proto-signing": "0.32.1", + "@cosmjs/stargate": "0.32.1", + "@cosmjs/utils": "0.32.1", + "@keplr-wallet/cosmos": "^0.12.59", + "@keplr-wallet/unit": "^0.12.48", + "@ledgerhq/hw-app-cosmos": "6.28.2", + "@ledgerhq/hw-transport": "6.28.5", + "@ledgerhq/hw-transport-webusb": "6.28.1", + "@lum-network/sdk-javascript": "^1.0.0-beta.2", "@popperjs/core": "^2.11.6", "@qognicafinance/react-lightweight-charts": "^1.0.5", "@rematch/core": "^2.2.0", @@ -17,6 +27,7 @@ "buffer": "^6.0.3", "class-transformer": "^0.5.1", "clipboard": "^2.0.11", + "cosmjs-utils": "^0.1.0", "crypto-browserify": "^3.12.0", "crypto-js": "^4.1.1", "dayjs": "^1.11.7", @@ -57,9 +68,10 @@ "@babel/preset-typescript": "^7.21.0", "@keplr-wallet/types": "^0.12.5", "@types/bootstrap": "^5.2.6", + "@types/crypto-js": "^4.2.1", "@types/cryptojs": "^3.1.29", "@types/dompurify": "^3.0.2", - "@types/jest": "^29.4.0", + "@types/jest": "^27.4.0", "@types/marked": "^4", "@types/node": "^16.10.3", "@types/numeral": "^2.0.2", @@ -67,6 +79,7 @@ "@types/react-dom": "^18.0.11", "@types/react-router-dom": "^5.3.3", "@types/react-transition-group": "^4.4.5", + "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^5.53.0", "@typescript-eslint/parser": "^5.53.0", "eslint": "^8.34.0", @@ -77,7 +90,7 @@ "identity-obj-proxy": "^3.0.0", "jest-environment-jsdom": "^29.5.0", "prettier": "^2.2.1", - "ts-jest": "^29.1.0" + "ts-jest": "^27" }, "scripts": { "start": "react-app-rewired start", @@ -86,6 +99,12 @@ "eject": "react-scripts eject", "lint": "eslint src/**/*.tsx src/**/*.ts --fix" }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, "browserslist": { "production": [ ">0.2%", diff --git a/src/@types/modules.d.ts b/src/@types/modules.d.ts index d5cf927a..2bca084e 100644 --- a/src/@types/modules.d.ts +++ b/src/@types/modules.d.ts @@ -1 +1,7 @@ declare module '*.scss'; + +/** + * Add untyped module declaration + * Only used by the KeyStore feature therefore not properly declared as it is a minor, almost deprecated feature. + */ +declare module 'crypto-browserify'; diff --git a/src/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx index d7d91cbe..291ac535 100644 --- a/src/components/Badge/Badge.tsx +++ b/src/components/Badge/Badge.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { ProposalStatus } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; -import { BondStatus } from '@lum-network/sdk-javascript/build/codec/cosmos/staking/v1beta1/staking'; +import { ProposalStatus } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1beta1/gov'; +import { BondStatus } from '@lum-network/sdk-javascript/build/codegen/cosmos/staking/v1beta1/staking'; import { useTranslation } from 'react-i18next'; import assets from 'assets'; diff --git a/src/components/Inputs/HdPathInput.tsx b/src/components/Inputs/HdPathInput.tsx index 140ad41e..7f9c9a8a 100644 --- a/src/components/Inputs/HdPathInput.tsx +++ b/src/components/Inputs/HdPathInput.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import Input from './Input'; @@ -15,6 +15,10 @@ const validateDerivationPath = (values: string[]) => { return false; } + if (val === 'm') { + continue; + } + const valToNumber = Number(val); if (Number.isNaN(valToNumber) || valToNumber < 0) { return false; @@ -50,10 +54,6 @@ const HdPathInput = ({ className, value, onChange, onCheck }: Props): JSX.Elemen }, 100); }; - useEffect(() => { - setInputsValues(value.split('/').map((val) => val.replace(`\'`, ''))); - }, [value]); - return ( <>
diff --git a/src/components/Modals/Modal.tsx b/src/components/Modals/Modal.tsx index 3eae725f..cb078ea2 100644 --- a/src/components/Modals/Modal.tsx +++ b/src/components/Modals/Modal.tsx @@ -1,5 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useImperativeHandle, useRef } from 'react'; import { useTranslation } from 'react-i18next'; +import { Modal as BootstrapModal } from 'bootstrap'; import './Modals.scss'; @@ -9,67 +10,119 @@ interface Props { withCloseButton?: boolean; contentClassName?: string; bodyClassName?: string; - dataBsBackdrop?: 'static' | 'true'; + dataBsBackdrop?: 'static' | boolean; dataBsKeyboard?: boolean; onCloseButtonPress?: () => void; } -const Modal = React.forwardRef( - ( - { - id, - children, - bodyClassName, - contentClassName, - onCloseButtonPress, - withCloseButton = true, - dataBsBackdrop = 'true', - dataBsKeyboard = true, - }, +export interface ModalHandlers { + toggle: () => void; + show: () => void; + hide: () => void; + addEventListener: (event: string, listener: () => void) => void; + removeEventListener: (event: string, listener: () => void) => void; +} + +const Modal: React.ForwardRefRenderFunction = (props, ref) => { + const { + id, + children, + bodyClassName, + contentClassName, + onCloseButtonPress, + withCloseButton = true, + dataBsBackdrop = true, + dataBsKeyboard = true, + } = props; + + const [buttonEnabled, setButtonEnabled] = useState(false); + const modalRef = useRef(null); + const bootstrapModalRef = useRef(); + + useEffect(() => { + if (modalRef.current) { + bootstrapModalRef.current = BootstrapModal.getOrCreateInstance(modalRef.current, { + keyboard: dataBsKeyboard, + backdrop: dataBsBackdrop, + }); + } + }, [modalRef]); + + useImperativeHandle( ref, - ) => { - const [buttonEnabled, setButtonEnabled] = useState(false); + () => ({ + toggle: () => { + if (bootstrapModalRef.current) { + bootstrapModalRef.current.toggle(); + } + }, + show: () => { + if (bootstrapModalRef.current) { + bootstrapModalRef.current.show(); + } + }, + hide: () => { + if (bootstrapModalRef.current) { + bootstrapModalRef.current.hide(); + } + }, + addEventListener: (event: string, listener: () => void) => { + const el = document.getElementById(id); + + if (el) { + el.addEventListener(event, listener); + } + }, + removeEventListener: (event: string, listener: () => void) => { + const el = document.getElementById(id); + + if (el) { + el.removeEventListener(event, listener); + } + }, + }), + [bootstrapModalRef], + ); - const { t } = useTranslation(); + const { t } = useTranslation(); - useEffect(() => { - setTimeout(() => setButtonEnabled(true), 300); - }, []); + useEffect(() => { + setTimeout(() => setButtonEnabled(true), 300); + }, []); - return ( -
@@ -162,12 +161,12 @@ const CreateWallet = (): JSX.Element => {
)} */}
- - +
{t('createWallet.doNotForget')} @@ -182,40 +181,52 @@ const CreateWallet = (): JSX.Element => {

{t('welcome.softwareModal.notRecommended')}

{t('welcome.softwareModal.notRecommendedDescription')}

-
-

{t('createWallet.keystore.title')}

- { - const newValue = event.target.value; - formik.handleChange(event); - setPasswordStrength(WalletUtils.checkPwdStrength(newValue)); - }} - placeholder="•••••••••" - className="mt-4" - /> -

- {t('createWallet.keystore.pwdStrength')} - - {passwordStrength} - -

- {formik.touched.password && formik.errors.password && ( -

{formik.errors.password}

- )} -
- +
+
+

{t('createWallet.keystore.title')}

+ {/* Hidden input for accessibility */} + + { + const newValue = event.target.value; + formik.handleChange(event); + setPasswordStrength(WalletUtils.checkPwdStrength(newValue)); + }} + autoComplete="new-password" + placeholder="•••••••••" + className="mt-4" + /> +

+ {t('createWallet.keystore.pwdStrength')} + + {passwordStrength} + +

+ {formik.touched.password && formik.errors.password && ( +

{formik.errors.password}

+ )} +
+ +
{t('createWallet.doNotForget')} {t('createWallet.keystore.warningDescription1')} diff --git a/src/screens/Auth/Welcome.tsx b/src/screens/Auth/Welcome.tsx index 2ccc6b9f..e8952836 100644 --- a/src/screens/Auth/Welcome.tsx +++ b/src/screens/Auth/Welcome.tsx @@ -2,16 +2,16 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; import { Link, useNavigate } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { Modal as BSModal } from 'bootstrap'; + import { Window as KeplrWindow } from '@keplr-wallet/types'; -import { LumConstants } from '@lum-network/sdk-javascript'; -import { Button as FEButton } from 'frontend-elements'; -import { RootDispatch, RootState } from 'redux/store'; +import { getLumHdPath } from '@lum-network/sdk-javascript'; import Assets from 'assets'; import { COSMOS_LEDGER_APP_INSTALL_LINK, KEPLR_DEFAULT_COIN_TYPE, KEPLR_INSTALL_LINK } from 'constant'; import { Modal, Button, SwitchInput, Input, HdPathInput, HoverTooltip } from 'components'; +import { Button as FEButton } from 'frontend-elements'; import { ExtensionMethod, HardwareMethod, SoftwareMethod } from 'models'; +import { RootDispatch, RootState } from 'redux/store'; import { useRematchDispatch } from 'redux/hooks'; import AuthLayout from './components/AuthLayout'; @@ -32,9 +32,9 @@ const Welcome = (): JSX.Element => { // State const [selectedMethod, setSelectedMethod] = useState(null); const [keystoreFileData, setKeystoreFileData] = useState(null); - const [softwareMethodModal, setSoftwareMethodModal] = useState(null); + const [softwareMethodModal, setSoftwareMethodModal] = useState | null>(null); const [showAdvanced, setShowAdvanced] = useState(false); - const [customHdPath, setCustomHdPath] = useState(LumConstants.getLumHdPath()); + const [customHdPath, setCustomHdPath] = useState(getLumHdPath()); const [isCustomPathValid, setIsCustomPathValid] = useState(true); const [isCustomCoinTypeValid, setIsCustomCoinTypeValid] = useState(true); const [keplrCoinType, setKeplrCoinType] = useState(KEPLR_DEFAULT_COIN_TYPE); @@ -53,8 +53,8 @@ const Welcome = (): JSX.Element => { })); // Refs - const importSoftwareModalRef = useRef(null); - const softwareMethodModalRef = useRef(null); + const importSoftwareModalRef = useRef>(null); + const softwareMethodModalRef = useRef>(null); const keystoreInputRef = useRef(null); // Utils hooks @@ -66,8 +66,7 @@ const Welcome = (): JSX.Element => { const modalElement = importSoftwareModalRef.current; if (modalElement) { - const bsModal = BSModal.getOrCreateInstance(modalElement, { backdrop: 'static', keyboard: false }); - bsModal.show(); + modalElement.show(); setModalShowed(true); } }, [importSoftwareModalRef]); @@ -76,8 +75,7 @@ const Welcome = (): JSX.Element => { const modalElement = importSoftwareModalRef.current; if (modalElement) { - const bsModal = BSModal.getOrCreateInstance(modalElement, { backdrop: 'static', keyboard: false }); - bsModal.hide(); + modalElement.hide(); setModalShowed(false); } }, [importSoftwareModalRef]); @@ -97,7 +95,7 @@ const Welcome = (): JSX.Element => { useEffect(() => { if (softwareMethodModalRef.current) { - setSoftwareMethodModal(BSModal.getOrCreateInstance(softwareMethodModalRef.current)); + setSoftwareMethodModal(softwareMethodModalRef.current); } }, [softwareMethodModalRef]); @@ -157,28 +155,28 @@ const Welcome = (): JSX.Element => { + +
+ {/* Hidden input for accessibility */} + + + {formik.touched.password && formik.errors.password && ( +

{formik.errors.password}

+ )} +
+ +

{t('createWallet.doNotForget')} {t('createWallet.keystore.warningDescription1')} diff --git a/src/screens/Auth/components/modals/ImportMnemonicModal.tsx b/src/screens/Auth/components/modals/ImportMnemonicModal.tsx index 3aff1a92..d82e7ca1 100644 --- a/src/screens/Auth/components/modals/ImportMnemonicModal.tsx +++ b/src/screens/Auth/components/modals/ImportMnemonicModal.tsx @@ -1,14 +1,13 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { LumConstants } from '@lum-network/sdk-javascript'; +import { getLumHdPath } from '@lum-network/sdk-javascript'; +import assets from 'assets'; +import { Input, SwitchInput, Button, HdPathInput, HoverTooltip } from 'components'; +import { Button as FEButton } from 'frontend-elements'; import { useRematchDispatch } from 'redux/hooks'; import { RootDispatch } from 'redux/store'; -import { Button as FEButton } from 'frontend-elements'; -import { Input, SwitchInput, Button, HdPathInput, HoverTooltip } from 'components'; - import { MnemonicLength, WalletUtils } from 'utils'; -import assets from 'assets'; const defaultMnemonicState: { length: MnemonicLength; values: string[] } = { length: 12, @@ -21,7 +20,7 @@ const ImportMnemonicModal = (): JSX.Element => { const [pasteHandled, setPasteHandled] = useState(false); const [showAdvanced, setShowAdvanced] = useState(false); - const [customHdPath, setCustomHdPath] = useState(LumConstants.getLumHdPath()); + const [customHdPath, setCustomHdPath] = useState(getLumHdPath()); const [isCustomPathValid, setIsCustomPathValid] = useState(true); /* CODE RELATED TO EXTRA WORD FOR FUTURE IMPLEMENTATION @@ -144,7 +143,7 @@ const ImportMnemonicModal = (): JSX.Element => {

{t('welcome.hardwareModal.advanced.title')}

{ - setCustomHdPath(LumConstants.getLumHdPath()); + setCustomHdPath(getLumHdPath()); }} className="bg-transparent text-btn p-0 me-2 h-auto" > @@ -153,7 +152,9 @@ const ImportMnemonicModal = (): JSX.Element => {
setCustomHdPath(value)} + onChange={(value) => { + setCustomHdPath(value); + }} onCheck={(valid) => setIsCustomPathValid(valid)} />
@@ -185,7 +186,7 @@ const ImportMnemonicModal = (): JSX.Element => {
)} */} +
+
+ {/* Hidden input for accessibility */} + + +
+ {formik.touched.privateKey && formik.errors.privateKey && ( +

{formik.errors.privateKey}

+ )} + +
); }; diff --git a/src/screens/Dashboard/Dashboard.tsx b/src/screens/Dashboard/Dashboard.tsx index d860a4ce..a617c4f7 100644 --- a/src/screens/Dashboard/Dashboard.tsx +++ b/src/screens/Dashboard/Dashboard.tsx @@ -1,10 +1,9 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; -import { LumConstants, LumUtils } from '@lum-network/sdk-javascript'; -import { Card } from 'frontend-elements'; -import { LUM_TWITTER } from 'constant'; +import { LUM_DENOM, convertUnit } from '@lum-network/sdk-javascript'; + import { TransactionsTable, AddressCard, @@ -14,6 +13,8 @@ import { AirdropCard, OtherAssetsTable, } from 'components'; +import { LUM_TWITTER } from 'constant'; +import { Card } from 'frontend-elements'; import { RootState } from 'redux/store'; import StakedCoinsCard from '../Staking/components/Cards/StakedCoinsCard'; @@ -54,17 +55,16 @@ const Dashboard = (): JSX.Element => { ) : null}
- +
@@ -81,14 +81,7 @@ const Dashboard = (): JSX.Element => {
diff --git a/src/screens/Governance/Governance.tsx b/src/screens/Governance/Governance.tsx index 6dd16dda..4c115d88 100644 --- a/src/screens/Governance/Governance.tsx +++ b/src/screens/Governance/Governance.tsx @@ -3,7 +3,7 @@ import { CSSTransition, SwitchTransition } from 'react-transition-group'; import { useNavigate, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; -import { ProposalStatus, VoteOption } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; +import { ProposalStatus, VoteOption } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1beta1/gov'; import { Proposal } from 'models'; import { RootDispatch, RootState } from 'redux/store'; @@ -27,7 +27,7 @@ const Governance = (): JSX.Element => { const nodeRef1 = useRef(null); const nodeRef2 = useRef(null); - const modalRef = useRef(null); + const modalRef = useRef>(null); const { wallet, proposals } = useSelector((state: RootState) => ({ wallet: state.wallet.currentWallet, @@ -86,7 +86,7 @@ const Governance = (): JSX.Element => { }, [proposalId, proposals]); const onDetails = (proposal: Proposal) => { - navigate(`/governance/proposal/${proposal.id}`); + navigate(`/governance/proposal/${proposal.id.toString()}`); }; const onVote = (proposal: Proposal) => { diff --git a/src/screens/Governance/components/ProposalCard/ProposalCard.tsx b/src/screens/Governance/components/ProposalCard/ProposalCard.tsx index 388533c9..9bd6c138 100644 --- a/src/screens/Governance/components/ProposalCard/ProposalCard.tsx +++ b/src/screens/Governance/components/ProposalCard/ProposalCard.tsx @@ -1,26 +1,28 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { Namespace, TFunction } from 'i18next'; -import { LumConstants } from '@lum-network/sdk-javascript'; -import { ProposalStatus } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; -import numeral from 'numeral'; import dayjs from 'dayjs'; -import { marked } from 'marked'; import DOMPurify from 'dompurify'; +import { Namespace, TFunction } from 'i18next'; +import { marked } from 'marked'; +import numeral from 'numeral'; +import { useSelector } from 'react-redux'; +import { useTranslation } from 'react-i18next'; + +import { LUM_DENOM } from '@lum-network/sdk-javascript'; +import { ProposalStatus } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1beta1/gov'; +import { Validator } from '@lum-network/sdk-javascript/build/codegen/cosmos/staking/v1beta1/staking'; + import { Badge, SmallerDecimal } from 'components'; import { Button, Card } from 'frontend-elements'; import { Proposal, VotesResult } from 'models'; -import { calculateTotalVotingPower, dateFromNow, GovernanceUtils, NumbersUtils } from 'utils'; import { useRematchDispatch } from 'redux/hooks'; import { RootDispatch, RootState } from 'redux/store'; +import { calculateTotalVotingPower, dateFromNow, GovernanceUtils, NumbersUtils } from 'utils'; import VoteBar from '../VoteBar/VoteBar'; +import VoteButton from '../VoteButton/VoteButton'; import './ProposalCard.scss'; -import VoteButton from '../VoteButton/VoteButton'; -import { useSelector } from 'react-redux'; -import { Validator } from '@lum-network/sdk-javascript/build/codec/cosmos/staking/v1beta1/staking'; interface Props { proposal: Proposal; @@ -59,7 +61,7 @@ const LargeProposalCard = ({

{t('common.total')}:

- {LumConstants.LumDenom} + {LUM_DENOM}

{t('governance.proposalCard.turnout')}:

@@ -88,14 +90,14 @@ const LargeProposalCard = ({ - {LumConstants.LumDenom} + {LUM_DENOM}

{t('governance.votes.no')}

{numeral(noPercentage).format('0.00')}%
- {LumConstants.LumDenom} + {LUM_DENOM}

{t('governance.votes.noWithVeto')}

@@ -104,7 +106,7 @@ const LargeProposalCard = ({ - {LumConstants.LumDenom} + {LUM_DENOM}

{t('governance.votes.abstain')}

@@ -113,7 +115,7 @@ const LargeProposalCard = ({ - {LumConstants.LumDenom} + {LUM_DENOM}
@@ -349,7 +351,7 @@ const ProposalCard = ({ proposal, full, onVote, onDetails }: Props): JSX.Element return (
-

{`#${proposal.id}`}

+

{`#${proposal.id.toString()}`}

{proposal.content ? proposal.content.title : ''}

diff --git a/src/screens/Governance/components/VoteButton/VoteButton.tsx b/src/screens/Governance/components/VoteButton/VoteButton.tsx index e5dcb686..9d4f3d06 100644 --- a/src/screens/Governance/components/VoteButton/VoteButton.tsx +++ b/src/screens/Governance/components/VoteButton/VoteButton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { ProposalStatus } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; +import { ProposalStatus } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1beta1/gov'; import { Button } from 'components'; import { Button as FEButton } from 'frontend-elements'; import { Proposal } from 'models'; diff --git a/src/screens/Messages/Message.tsx b/src/screens/Messages/Message.tsx index a9550d06..01ee5617 100644 --- a/src/screens/Messages/Message.tsx +++ b/src/screens/Messages/Message.tsx @@ -1,15 +1,14 @@ import React, { useEffect, useRef, useState } from 'react'; +import ClipboardJS from 'clipboard'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; -import ClipboardJS from 'clipboard'; -import { Modal as BSModal } from 'bootstrap'; -import { LumUtils, LumTypes, LumConstants } from '@lum-network/sdk-javascript'; +import { LUM_DENOM, convertUnit, keyFromHex, keyToHex, toUtf8 } from '@lum-network/sdk-javascript'; -import { AddressCard, AvailableCard, Input, Modal, Tooltip } from 'components'; -import { RootState } from 'redux/store'; +import { Button as CustomButton, AddressCard, AvailableCard, Input, Modal, Tooltip } from 'components'; import { Button, Card } from 'frontend-elements'; -import { Button as CustomButton } from 'components'; -import { showErrorToast, showSuccessToast, WalletClient, WalletUtils } from 'utils'; +import { SignMsg } from 'models'; +import { RootState } from 'redux/store'; +import { showErrorToast, showSuccessToast, WalletUtils } from 'utils'; import './styles/Messages.scss'; @@ -26,7 +25,7 @@ const isMessageToVerify = (msg: { publicKey?: Uint8Array; signer?: string; version?: string; -}): msg is LumTypes.SignMsg => { +}): msg is SignMsg => { return !!(msg.address && msg.msg && msg.publicKey && msg.sig && msg.signer && msg.version); }; @@ -44,7 +43,7 @@ const Message = (): JSX.Element => { const [message, setMessage] = useState(''); const [messageToVerify, setMessageToVerify] = useState(''); const [showTooltip, setShowTooltip] = useState(false); - const [signMessage, setSignMessage] = useState(null); + const [signMessage, setSignMessage] = useState(null); const [verifyMessage, setVerifyMessage] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -59,8 +58,8 @@ const Message = (): JSX.Element => { const { t } = useTranslation(); // Refs - const confirmModalRef = useRef(null); - const signatureModalRef = useRef(null); + const confirmModalRef = useRef>(null); + const signatureModalRef = useRef>(null); // Effects useEffect(() => { @@ -102,13 +101,7 @@ const Message = (): JSX.Element => { const handleSign = async () => { setIsLoading(true); try { - const chainId = WalletClient.getChainId(); - - if (!chainId) { - throw new Error('Chain ID not found'); - } - - const json = await WalletUtils.generateSignedMessage(chainId, wallet, message); + const json = await WalletUtils.generateSignedMessage(wallet, message); setSignMessage(json); showModal('confirmation', false); showModal('signature', true); @@ -121,23 +114,19 @@ const Message = (): JSX.Element => { const handleVerify = async () => { const msg = JSON.parse(messageToVerify, (key, value) => { if (key === 'sig' || key === 'publicKey') { - value = LumUtils.keyFromHex(value); + value = keyFromHex(value); } return value; }); if (isMessageToVerify(msg)) { - const chainId = WalletClient.getChainId(); - - if (!chainId) { - throw new Error('Chain ID not found'); - } - - WalletUtils.validateSignMessage(chainId, msg) + WalletUtils.validateSignMessage(msg) .then((result) => { setVerifyMessage({ result, message: msg.msg, address: msg.address }); }) - .catch((error) => showErrorToast(error.message)); + .catch((error) => { + showErrorToast(error.message); + }); } else { showErrorToast(t('messages.invalidMessage')); } @@ -154,10 +143,10 @@ const Message = (): JSX.Element => { const showModal = (id: 'signature' | 'confirmation', toggle: boolean) => { if (id === 'confirmation' && confirmModalRef.current) { - const modal = BSModal.getOrCreateInstance(confirmModalRef.current); + const modal = confirmModalRef.current; return toggle ? modal.show() : modal.hide(); } else if (id === 'signature' && signatureModalRef.current) { - const modal = BSModal.getOrCreateInstance(signatureModalRef.current); + const modal = signatureModalRef.current; return toggle ? modal.show() : modal.hide(); } }; @@ -168,17 +157,16 @@ const Message = (): JSX.Element => {
- +
@@ -291,14 +279,14 @@ const Message = (): JSX.Element => {

{t('messages.confirmationModal.title')}

@@ -316,8 +304,8 @@ const Message = (): JSX.Element => { value={JSON.stringify( { ...signMessage, - sig: LumUtils.keyToHex(signMessage.sig), - publicKey: LumUtils.keyToHex(signMessage.publicKey), + sig: keyToHex(signMessage.sig), + publicKey: keyToHex(signMessage.publicKey), }, null, 2, @@ -334,8 +322,8 @@ const Message = (): JSX.Element => { 'data-clipboard-text': JSON.stringify( { ...signMessage, - sig: LumUtils.keyToHex(signMessage.sig), - publicKey: LumUtils.keyToHex(signMessage.publicKey), + sig: keyToHex(signMessage.sig), + publicKey: keyToHex(signMessage.publicKey), }, null, 2, diff --git a/src/screens/Operations/Operations.tsx b/src/screens/Operations/Operations.tsx index fbab42f5..82751ad6 100644 --- a/src/screens/Operations/Operations.tsx +++ b/src/screens/Operations/Operations.tsx @@ -2,9 +2,9 @@ import React, { useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { useFormik } from 'formik'; -import { LumConstants, LumMessages, LumUtils } from '@lum-network/sdk-javascript'; -import { VoteOption } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; import * as yup from 'yup'; +import { LUM_DENOM, LumBech32Prefixes, convertUnit, cosmos } from '@lum-network/sdk-javascript'; +import { VoteOption } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1/gov'; import assets from 'assets'; import { AddressCard, AvailableCard, Input, Modal, Button as CustomButton, AirdropCard } from 'components'; @@ -23,6 +23,14 @@ import SetWithdrawAddress from './components/Forms/SetWithdrawAddress'; import './Operations.scss'; +const { MsgUndelegate, MsgBeginRedelegate, MsgDelegate } = cosmos.staking.v1beta1; + +const { MsgVote } = cosmos.gov.v1; + +const { MsgWithdrawDelegatorReward, MsgSetWithdrawAddress } = cosmos.distribution.v1beta1; + +const { MsgSend } = cosmos.bank.v1beta1; + type MsgType = { name: string; icon: string; iconClassName?: string; id: string; description: string }; const Operations = (): JSX.Element => { @@ -62,7 +70,7 @@ const Operations = (): JSX.Element => { loadingSend.loading || loadingDelegate.loading || loadingUndelegate.loading || loadingGetReward.loading; const { t } = useTranslation(); - const modalRef = useRef(null); + const modalRef = useRef>(null); const [modal, setModal] = useState(null); const [txResult, setTxResult] = useState<{ hash: string; error?: string | null } | null>(null); @@ -70,44 +78,44 @@ const Operations = (): JSX.Element => { const buttons: MsgType[] = [ { - id: LumMessages.MsgSendUrl, + id: MsgSend.typeUrl, name: t('operations.types.send.name'), icon: assets.images.messageTypes.send, iconClassName: 'send-icon', description: t('operations.types.send.description'), }, { - id: LumMessages.MsgDelegateUrl, + id: MsgDelegate.typeUrl, name: t('operations.types.delegate.name'), icon: assets.images.messageTypes.delegate, description: t('operations.types.delegate.description'), }, { - id: LumMessages.MsgUndelegateUrl, + id: MsgUndelegate.typeUrl, name: t('operations.types.undelegate.name'), icon: assets.images.messageTypes.undelegate, description: t('operations.types.undelegate.description'), }, { - id: LumMessages.MsgBeginRedelegateUrl, + id: MsgBeginRedelegate.typeUrl, name: t('operations.types.redelegate.name'), icon: assets.images.messageTypes.redelegate, description: t('operations.types.redelegate.description'), }, { - id: LumMessages.MsgWithdrawDelegatorRewardUrl, + id: MsgWithdrawDelegatorReward.typeUrl, name: t('operations.types.getRewards.name'), icon: assets.images.messageTypes.getReward, description: t('operations.types.getRewards.description'), }, { - id: LumMessages.MsgVoteUrl, + id: MsgVote.typeUrl, name: t('operations.types.vote.name'), description: t('operations.types.vote.description'), icon: assets.images.messageTypes.vote, }, { - id: LumMessages.MsgSetWithdrawAddressUrl, + id: MsgSetWithdrawAddress.typeUrl, name: t('operations.types.setWithdrawAddress.name'), description: t('operations.types.setWithdrawAddress.description'), icon: assets.images.messageTypes.setWithdrawAddress, @@ -120,7 +128,7 @@ const Operations = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixAccAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.ACC_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -135,7 +143,7 @@ const Operations = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -150,7 +158,7 @@ const Operations = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -165,13 +173,13 @@ const Operations = (): JSX.Element => { fromAddress: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), toAddress: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -186,7 +194,7 @@ const Operations = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), memo: yup.string(), @@ -282,7 +290,7 @@ const Operations = (): JSX.Element => { if (sendResult) { setConfirming(false); - setTxResult({ hash: LumUtils.toHex(sendResult.hash), error: sendResult.error }); + setTxResult({ hash: sendResult.hash, error: sendResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -294,7 +302,7 @@ const Operations = (): JSX.Element => { const delegateResult = await delegate({ validatorAddress, amount, memo, from: wallet }); if (delegateResult) { - setTxResult({ hash: LumUtils.toHex(delegateResult.hash), error: delegateResult.error }); + setTxResult({ hash: delegateResult.hash, error: delegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -306,7 +314,7 @@ const Operations = (): JSX.Element => { const undelegateResult = await undelegate({ validatorAddress, amount, memo, from: wallet }); if (undelegateResult) { - setTxResult({ hash: LumUtils.toHex(undelegateResult.hash), error: undelegateResult.error }); + setTxResult({ hash: undelegateResult.hash, error: undelegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -319,7 +327,7 @@ const Operations = (): JSX.Element => { if (setWithdrawAddressResult) { setTxResult({ - hash: LumUtils.toHex(setWithdrawAddressResult.hash), + hash: setWithdrawAddressResult.hash, error: setWithdrawAddressResult.error, }); } @@ -344,7 +352,7 @@ const Operations = (): JSX.Element => { }); if (redelegateResult) { - setTxResult({ hash: LumUtils.toHex(redelegateResult.hash), error: redelegateResult.error }); + setTxResult({ hash: redelegateResult.hash, error: redelegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -356,7 +364,7 @@ const Operations = (): JSX.Element => { const getRewardResult = await getReward({ validatorAddress, memo, from: wallet }); if (getRewardResult) { - setTxResult({ hash: LumUtils.toHex(getRewardResult.hash), error: getRewardResult.error }); + setTxResult({ hash: getRewardResult.hash, error: getRewardResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -365,7 +373,7 @@ const Operations = (): JSX.Element => { const onSubmitVote = async (proposalId: string, voteOption: VoteOption) => { try { - const proposal = proposals.find((p) => p.id.equals(proposalId)); + const proposal = proposals.find((p) => p.id === BigInt(proposalId)); if (!proposal) { throw new Error(`Proposal #${proposalId} not found`); @@ -374,7 +382,7 @@ const Operations = (): JSX.Element => { const voteResult = await vote({ voter: wallet, proposal, vote: voteOption }); if (voteResult) { - setTxResult({ hash: LumUtils.toHex(voteResult.hash), error: voteResult.error }); + setTxResult({ hash: voteResult.hash, error: voteResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -391,25 +399,25 @@ const Operations = (): JSX.Element => { } switch (modal.id) { - case LumMessages.MsgSendUrl: + case MsgSend.typeUrl: return ; - case LumMessages.MsgDelegateUrl: + case MsgDelegate.typeUrl: return ; - case LumMessages.MsgUndelegateUrl: + case MsgUndelegate.typeUrl: return ; - case LumMessages.MsgBeginRedelegateUrl: + case MsgBeginRedelegate.typeUrl: return ; - case LumMessages.MsgWithdrawDelegatorRewardUrl: + case MsgWithdrawDelegatorReward.typeUrl: return ; - case LumMessages.MsgVoteUrl: + case MsgVote.typeUrl: return ; - case LumMessages.MsgSetWithdrawAddressUrl: + case MsgSetWithdrawAddress.typeUrl: return ( ); @@ -447,17 +455,16 @@ const Operations = (): JSX.Element => {
) : null}
- +
@@ -500,7 +507,7 @@ const Operations = (): JSX.Element => { className="mt-5" data-bs-target="modalSendTxs" data-bs-dismiss="modal" - onClick={() => getWalletInfos(wallet.getAddress())} + onClick={() => getWalletInfos(wallet.address)} > {t('common.close')} diff --git a/src/screens/Operations/components/Forms/Delegate.tsx b/src/screens/Operations/components/Forms/Delegate.tsx index 80f0ee39..dd05912c 100644 --- a/src/screens/Operations/components/Forms/Delegate.tsx +++ b/src/screens/Operations/components/Forms/Delegate.tsx @@ -1,14 +1,16 @@ import React, { useState } from 'react'; -import { LumUtils, LumConstants } from '@lum-network/sdk-javascript'; -import { Input, Button as CustomButton } from 'components'; import { FormikContextType } from 'formik'; -import { Button } from 'frontend-elements'; +import numeral from 'numeral'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; +import { LUM_DENOM, convertUnit } from '@lum-network/sdk-javascript'; + +import { Input, Button as CustomButton } from 'components'; +import { Button } from 'frontend-elements'; import { RootState } from 'redux/store'; import { calculateTotalVotingPower, NumbersUtils, sortByVotingPower, trunc } from 'utils'; + import CustomSelect from '../CustomSelect/CustomSelect'; -import numeral from 'numeral'; interface Props { isLoading: boolean; @@ -24,20 +26,14 @@ const Delegate = ({ form, isLoading }: Props): JSX.Element => { const { t } = useTranslation(); - const { balance, vestings, bondedValidators, unbondedValidators, unbondingValidators } = useSelector( - (state: RootState) => ({ - balance: state.wallet.currentBalance, - vestings: state.wallet.vestings, - bondedValidators: state.staking.validators.bonded, - unbondedValidators: state.staking.validators.unbonded, - unbondingValidators: state.staking.validators.unbonding, - }), - ); + const { balance, vestings, bondedValidators } = useSelector((state: RootState) => ({ + balance: state.wallet.currentBalance, + vestings: state.wallet.vestings, + bondedValidators: state.staking.validators.bonded, + })); const onMax = () => { - let max = vestings - ? balance.lum - Number(LumUtils.convertUnit(vestings.lockedBankCoins, LumConstants.LumDenom)) - : balance.lum; + let max = vestings ? balance.lum - Number(convertUnit(vestings.lockedBankCoins, LUM_DENOM)) : balance.lum; // Max balance minus avg fees max -= 0.005; @@ -70,13 +66,7 @@ const Delegate = ({ form, isLoading }: Props): JSX.Element => { ({ value: val.operatorAddress, label: val.description?.moniker || val.description?.identity || trunc(val.operatorAddress), diff --git a/src/screens/Operations/components/Forms/Redelegate.tsx b/src/screens/Operations/components/Forms/Redelegate.tsx index bba27628..74db14a4 100644 --- a/src/screens/Operations/components/Forms/Redelegate.tsx +++ b/src/screens/Operations/components/Forms/Redelegate.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { FormikContextType } from 'formik'; import numeral from 'numeral'; -import { Validator } from '@lum-network/sdk-javascript/build/codec/cosmos/staking/v1beta1/staking'; +import { Validator } from '@lum-network/sdk-javascript/build/codegen/cosmos/staking/v1beta1/staking'; import { Input, Button as CustomButton } from 'components'; import { Button } from 'frontend-elements'; @@ -44,9 +44,7 @@ const Redelegate = ({ form, isLoading }: Props): JSX.Element => { const [destValidatorsList, setDestValidatorsList] = useState( sortByVotingPower( bondedValidators, - NumbersUtils.convertUnitNumber( - calculateTotalVotingPower([...bondedValidators, ...unbondedValidators, ...unbondingValidators]), - ), + NumbersUtils.convertUnitNumber(calculateTotalVotingPower([...bondedValidators])), ), ); @@ -69,18 +67,14 @@ const Redelegate = ({ form, isLoading }: Props): JSX.Element => { setDestValidatorsList( sortByVotingPower( bondedValidators, - NumbersUtils.convertUnitNumber( - calculateTotalVotingPower([...bondedValidators, ...unbondedValidators, ...unbondingValidators]), - ), + NumbersUtils.convertUnitNumber(calculateTotalVotingPower([...bondedValidators])), ).filter((val) => val.operatorAddress !== form.values.fromAddress), ); } else { setDestValidatorsList( sortByVotingPower( bondedValidators, - NumbersUtils.convertUnitNumber( - calculateTotalVotingPower([...bondedValidators, ...unbondedValidators, ...unbondingValidators]), - ), + NumbersUtils.convertUnitNumber(calculateTotalVotingPower([...bondedValidators])), ), ); } diff --git a/src/screens/Operations/components/Forms/Send.tsx b/src/screens/Operations/components/Forms/Send.tsx index 0292536c..f5c90975 100644 --- a/src/screens/Operations/components/Forms/Send.tsx +++ b/src/screens/Operations/components/Forms/Send.tsx @@ -1,11 +1,13 @@ -import { LumConstants, LumUtils } from '@lum-network/sdk-javascript'; -import { Input, Button as CustomButton } from 'components'; +import React, { useEffect, useState } from 'react'; + import { FormikContextType } from 'formik'; -import { Button } from 'frontend-elements'; import numeral from 'numeral'; -import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; +import { LUM_DENOM, convertUnit } from '@lum-network/sdk-javascript'; + +import { Input, Button as CustomButton } from 'components'; +import { Button } from 'frontend-elements'; import { RootState } from 'redux/store'; interface Props { @@ -25,9 +27,7 @@ const Send = ({ form, isLoading }: Props): JSX.Element => { const vestings = useSelector((state: RootState) => state.wallet.vestings); const onMax = () => { - let max = vestings - ? balance.lum - Number(LumUtils.convertUnit(vestings.lockedBankCoins, LumConstants.LumDenom)) - : balance.lum; + let max = vestings ? balance.lum - Number(convertUnit(vestings.lockedBankCoins, LUM_DENOM)) : balance.lum; // Max balance minus avg fees max -= 0.005; diff --git a/src/screens/Operations/components/Forms/Vote.tsx b/src/screens/Operations/components/Forms/Vote.tsx index 523ae63a..12b5d53f 100644 --- a/src/screens/Operations/components/Forms/Vote.tsx +++ b/src/screens/Operations/components/Forms/Vote.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; -import { ProposalStatus, VoteOption } from '@lum-network/sdk-javascript/build/codec/cosmos/gov/v1beta1/gov'; +import { ProposalStatus, VoteOption } from '@lum-network/sdk-javascript/build/codegen/cosmos/gov/v1/gov'; import { FormikContextType } from 'formik'; import { Button as CustomButton, Select } from 'components'; diff --git a/src/screens/Staking/Staking.tsx b/src/screens/Staking/Staking.tsx index 8ebbe9fc..148c2b87 100644 --- a/src/screens/Staking/Staking.tsx +++ b/src/screens/Staking/Staking.tsx @@ -1,24 +1,24 @@ import React, { useEffect, useRef, useState } from 'react'; +import { useFormik } from 'formik'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; -import { Validator } from '@lum-network/sdk-javascript/build/codec/cosmos/staking/v1beta1/staking'; -import { LumConstants, LumMessages, LumUtils } from '@lum-network/sdk-javascript'; -import { useFormik } from 'formik'; import * as yup from 'yup'; +import { LUM_DENOM, LumBech32Prefixes, convertUnit, cosmos } from '@lum-network/sdk-javascript'; +import { Validator } from '@lum-network/sdk-javascript/build/codegen/cosmos/staking/v1beta1/staking'; +import { AirdropCard, AvailableCard, Button, Input, Modal } from 'components'; import { Card } from 'frontend-elements'; import { RootDispatch, RootState } from 'redux/store'; import { useRematchDispatch } from 'redux/hooks'; -import { AirdropCard, AvailableCard, Button, Input, Modal } from 'components'; import { calculateTotalVotingPower, getUserValidators, NumbersUtils, showErrorToast, + sortByVotingPower, unbondingsTimeRemaining, } from 'utils'; -import { Modal as BSModal } from 'bootstrap'; import StakedCoinsCard from './components/Cards/StakedCoinsCard'; import UnbondingTokensCard from './components/Cards/UnbondingTokensCard'; @@ -35,6 +35,10 @@ import GetAllRewards from '../Operations/components/Forms/GetAllRewards'; import Redelegate from '../Operations/components/Forms/Redelegate'; import OtherStakingRewards from './components/Lists/OtherStakingRewards'; +const { MsgUndelegate, MsgBeginRedelegate, MsgDelegate } = cosmos.staking.v1beta1; + +const { MsgWithdrawDelegatorReward } = cosmos.distribution.v1beta1; + const noop = () => { //do nothing }; @@ -44,8 +48,10 @@ const Staking = (): JSX.Element => { const [txResult, setTxResult] = useState<{ hash: string; error?: string | null } | null>(null); const [modalType, setModalType] = useState<{ id: string; name: string } | null>(null); const [confirming, setConfirming] = useState(false); - const [operationModal, setOperationModal] = useState(null); - const [topValidatorConfirmationModal, setTopValidatorConfirmationModal] = useState(null); + const [operationModal, setOperationModal] = useState | null>(null); + const [topValidatorConfirmationModal, setTopValidatorConfirmationModal] = useState | null>(null); const [onConfirmOperation, setOnConfirmOperation] = useState<() => void>(noop); const [totalVotingPower, setTotalVotingPower] = useState(0); @@ -112,8 +118,8 @@ const Staking = (): JSX.Element => { const loadingAll = loadingDelegate || loadingUndelegate; // Utils - const modalRef = useRef(null); - const topValidatorConfirmationModalRef = useRef(null); + const modalRef = useRef>(null); + const topValidatorConfirmationModalRef = useRef>(null); const { t } = useTranslation(); @@ -123,7 +129,7 @@ const Staking = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -138,13 +144,13 @@ const Staking = (): JSX.Element => { fromAddress: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), toAddress: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -159,7 +165,7 @@ const Staking = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`), { + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`), { message: t('operations.errors.address'), }), amount: yup.string().required(t('common.required')), @@ -174,7 +180,7 @@ const Staking = (): JSX.Element => { address: yup .string() .required(t('common.required')) - .matches(new RegExp(`^${LumConstants.LumBech32PrefixValAddr}`)), + .matches(new RegExp(`^${LumBech32Prefixes.VAL_ADDR}`)), }), onSubmit: (values) => onSubmitClaim(values.address, values.memo), }); @@ -190,24 +196,20 @@ const Staking = (): JSX.Element => { // Effects useEffect(() => { if (wallet) { - getValidatorsInfos(wallet.getAddress()); + getValidatorsInfos(wallet.address); } }, [getValidatorsInfos, wallet]); useEffect(() => { - setTotalVotingPower( - NumbersUtils.convertUnitNumber( - calculateTotalVotingPower([...bondedValidators, ...unbondedValidators, ...unbondingValidators]), - ), - ); + setTotalVotingPower(NumbersUtils.convertUnitNumber(calculateTotalVotingPower([...bondedValidators]))); }, [bondedValidators, unbondedValidators]); useEffect(() => { if (modalRef && modalRef.current) { - setOperationModal(BSModal.getOrCreateInstance(modalRef.current, { backdrop: 'static', keyboard: false })); + setOperationModal(modalRef.current); } if (topValidatorConfirmationModalRef && topValidatorConfirmationModalRef.current) { - setTopValidatorConfirmationModal(BSModal.getOrCreateInstance(topValidatorConfirmationModalRef.current)); + setTopValidatorConfirmationModal(topValidatorConfirmationModalRef.current); } }, []); @@ -258,7 +260,7 @@ const Staking = (): JSX.Element => { const delegateResult = await delegate({ validatorAddress, amount, memo, from: wallet }); if (delegateResult) { - setTxResult({ hash: LumUtils.toHex(delegateResult.hash), error: delegateResult.error }); + setTxResult({ hash: delegateResult.hash, error: delegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -281,7 +283,7 @@ const Staking = (): JSX.Element => { }); if (redelegateResult) { - setTxResult({ hash: LumUtils.toHex(redelegateResult.hash), error: redelegateResult.error }); + setTxResult({ hash: redelegateResult.hash, error: redelegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -293,7 +295,7 @@ const Staking = (): JSX.Element => { const undelegateResult = await undelegate({ validatorAddress, amount, memo, from: wallet }); if (undelegateResult) { - setTxResult({ hash: LumUtils.toHex(undelegateResult.hash), error: undelegateResult.error }); + setTxResult({ hash: undelegateResult.hash, error: undelegateResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -309,7 +311,7 @@ const Staking = (): JSX.Element => { }); if (claimResult) { - setTxResult({ hash: LumUtils.toHex(claimResult.hash), error: claimResult.error }); + setTxResult({ hash: claimResult.hash, error: claimResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -336,7 +338,7 @@ const Staking = (): JSX.Element => { }); if (getAllRewardsResult) { - setTxResult({ hash: LumUtils.toHex(getAllRewardsResult.hash), error: getAllRewardsResult.error }); + setTxResult({ hash: getAllRewardsResult.hash, error: getAllRewardsResult.error }); } } catch (e) { showErrorToast((e as Error).message); @@ -352,7 +354,7 @@ const Staking = (): JSX.Element => { } } else if (operationModal) { delegateForm.setFieldValue('address', validator.operatorAddress).then(() => { - setModalType({ id: LumMessages.MsgDelegateUrl, name: t('operations.types.delegate.name') }); + setModalType({ id: MsgDelegate.typeUrl, name: t('operations.types.delegate.name') }); operationModal.show(); }); } @@ -361,7 +363,7 @@ const Staking = (): JSX.Element => { const onUndelegate = (validator: Validator) => { if (operationModal) { undelegateForm.setFieldValue('address', validator.operatorAddress).then(() => { - setModalType({ id: LumMessages.MsgUndelegateUrl, name: t('operations.types.undelegate.name') }); + setModalType({ id: MsgUndelegate.typeUrl, name: t('operations.types.undelegate.name') }); operationModal.show(); }); } @@ -370,7 +372,7 @@ const Staking = (): JSX.Element => { const onRedelegate = (validator: Validator) => { if (operationModal) { redelegateForm.setFieldValue('fromAddress', validator.operatorAddress).then(() => { - setModalType({ id: LumMessages.MsgBeginRedelegateUrl, name: t('operations.types.redelegate.name') }); + setModalType({ id: MsgBeginRedelegate.typeUrl, name: t('operations.types.redelegate.name') }); operationModal.show(); }); } @@ -380,7 +382,7 @@ const Staking = (): JSX.Element => { if (operationModal) { claimForm.setFieldValue('address', validator.operatorAddress).then(() => { setModalType({ - id: LumMessages.MsgWithdrawDelegatorRewardUrl, + id: MsgWithdrawDelegatorReward.typeUrl, name: t('operations.types.getRewards.name'), }); operationModal.show(); @@ -391,7 +393,7 @@ const Staking = (): JSX.Element => { const onClaimAll = () => { if (operationModal) { setModalType({ - id: LumMessages.MsgWithdrawDelegatorRewardUrl + '/all', + id: MsgWithdrawDelegatorReward.typeUrl + '/all', name: t('operations.types.getAllRewards.name'), }); operationModal.show(); @@ -405,19 +407,19 @@ const Staking = (): JSX.Element => { } switch (modalType.id) { - case LumMessages.MsgDelegateUrl: + case MsgDelegate.typeUrl: return ; - case LumMessages.MsgBeginRedelegateUrl: + case MsgBeginRedelegate.typeUrl: return ; - case LumMessages.MsgUndelegateUrl: + case MsgUndelegate.typeUrl: return ; - case LumMessages.MsgWithdrawDelegatorRewardUrl: + case MsgWithdrawDelegatorReward.typeUrl: return ; - case LumMessages.MsgWithdrawDelegatorRewardUrl + '/all': + case MsgWithdrawDelegatorReward.typeUrl + '/all': return ; default: @@ -444,14 +446,7 @@ const Staking = (): JSX.Element => {
@@ -459,11 +454,10 @@ const Staking = (): JSX.Element => {
@@ -509,7 +503,7 @@ const Staking = (): JSX.Element => { @@ -552,7 +546,7 @@ const Staking = (): JSX.Element => { diff --git a/src/screens/Staking/components/Lists/AvailableValidators.tsx b/src/screens/Staking/components/Lists/AvailableValidators.tsx index 8d450970..613f37ce 100644 --- a/src/screens/Staking/components/Lists/AvailableValidators.tsx +++ b/src/screens/Staking/components/Lists/AvailableValidators.tsx @@ -1,11 +1,11 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { Validator } from '@lum-network/sdk-javascript/build/codec/cosmos/staking/v1beta1/staking'; +import { Validator } from '@lum-network/sdk-javascript/build/codegen/cosmos/staking/v1beta1/staking'; import numeral from 'numeral'; import { Table, ValidatorLogo } from 'frontend-elements'; import { Button, Input } from 'components'; -import { CLIENT_PRECISION, LUM_ASSETS_GITHUB } from 'constant'; +import { LUM_ASSETS_GITHUB } from 'constant'; import { trunc, NumbersUtils, sortByVotingPower, WalletClient, getExplorerLink } from 'utils'; import searchIcon from 'assets/images/search.svg'; @@ -37,12 +37,14 @@ const AvailableValidators = ({ validators, totalVotingPower, onDelegate }: Props useEffect(() => { if (searchText) { + const lowercaseSearchText = searchText.toLowerCase(); + setVals( validators.filter( (validator) => - validator.operatorAddress.includes(searchText) || - validator.description?.moniker.includes(searchText) || - validator.description?.identity.includes(searchText), + validator.operatorAddress.toLowerCase().includes(lowercaseSearchText) || + validator.description?.moniker.toLowerCase().includes(lowercaseSearchText) || + validator.description?.identity.toLowerCase().includes(lowercaseSearchText), ), ); } else { @@ -55,7 +57,7 @@ const AvailableValidators = ({ validators, totalVotingPower, onDelegate }: Props }; const renderRow = (validator: Validator, index: number) => { - const rank = vals.findIndex((val) => val.operatorAddress === validator.operatorAddress); + const rank = validators.findIndex((val) => val.operatorAddress === validator.operatorAddress); return ( @@ -98,11 +100,7 @@ const AvailableValidators = ({ validators, totalVotingPower, onDelegate }: Props {/* TO RE-ENABLE WHEN UPTIME IS AVAILABLE {validator.} */} -

- {numeral( - parseFloat(validator.commission?.commissionRates?.rate || '0') / CLIENT_PRECISION, - ).format('0.00%')} -

+

{numeral(validator.commission?.commissionRates?.rate || '0').format('0.00%')}