From 41be0491ac23a6670c7af926d7f5ae81e2c90118 Mon Sep 17 00:00:00 2001 From: ost-ptk Date: Tue, 15 Oct 2024 15:02:55 +0300 Subject: [PATCH 1/2] migrate validators fetching to the casper wallet core --- package-lock.json | 16 +-- src/apps/popup/pages/buy-cspr/amount.tsx | 3 +- .../components/account-list-item.tsx | 3 +- .../stakes/components/validator-list.tsx | 23 ++-- src/apps/popup/pages/stakes/confirm-step.tsx | 35 ++--- src/apps/popup/pages/stakes/index.tsx | 21 ++- .../redelegate-validator-dropdown-input.tsx | 38 +++--- src/apps/popup/pages/stakes/utils.ts | 101 ++++---------- .../pages/stakes/validator-dropdown-input.tsx | 44 +++---- .../popup/pages/transfer/confirm-step.tsx | 3 +- .../pages/sign-deploy/deploy-value.tsx | 3 +- src/background/index.ts | 46 ------- src/background/redux/settings/selectors.ts | 6 - src/background/service-message.ts | 17 --- src/background/wallet-repositories.ts | 6 +- src/constants.ts | 10 -- src/libs/services/types.ts | 11 -- .../services/validators-service/constants.ts | 9 -- src/libs/services/validators-service/index.ts | 4 +- src/libs/services/validators-service/types.ts | 124 ------------------ .../use-fetch-validators.ts | 61 +++++++++ .../validators-service/validators-service.ts | 77 ----------- .../account-list/account-list-item.tsx | 3 +- .../dynamic-accounts-list-with-select.tsx | 3 +- .../transaction-fee-plate.tsx | 3 +- .../validator-plate/validator-plate.tsx | 27 ++-- src/libs/ui/utils/formatters.ts | 29 ---- src/utils.ts | 1 + 28 files changed, 187 insertions(+), 540 deletions(-) delete mode 100644 src/libs/services/validators-service/constants.ts delete mode 100644 src/libs/services/validators-service/types.ts create mode 100644 src/libs/services/validators-service/use-fetch-validators.ts delete mode 100644 src/libs/services/validators-service/validators-service.ts diff --git a/package-lock.json b/package-lock.json index 40b28dbc3..89be6b1b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9057,11 +9057,11 @@ } }, "node_modules/apisauce": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-3.0.1.tgz", - "integrity": "sha512-4HEmETv0skPW+bFS4TzB5nQ5y2TdafbUpnAjp83MW8Re9lHwngao2hpnk7aIaxExJqSTxkpWl+ThgZbqjx2bpQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-3.1.0.tgz", + "integrity": "sha512-uE2c8SibGG1oCfN5uVgipnKAbZCBSp7c773aRjRIX4dsi+4Jyoj8HAENbJSV4B6ILltfvQRQFX5Sv4Jw/eeEiA==", "dependencies": { - "axios": "^1.4.0" + "axios": "^1.7.7" } }, "node_modules/append-buffer": { @@ -36588,11 +36588,11 @@ } }, "apisauce": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-3.0.1.tgz", - "integrity": "sha512-4HEmETv0skPW+bFS4TzB5nQ5y2TdafbUpnAjp83MW8Re9lHwngao2hpnk7aIaxExJqSTxkpWl+ThgZbqjx2bpQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-3.1.0.tgz", + "integrity": "sha512-uE2c8SibGG1oCfN5uVgipnKAbZCBSp7c773aRjRIX4dsi+4Jyoj8HAENbJSV4B6ILltfvQRQFX5Sv4Jw/eeEiA==", "requires": { - "axios": "^1.4.0" + "axios": "^1.7.7" } }, "append-buffer": { diff --git a/src/apps/popup/pages/buy-cspr/amount.tsx b/src/apps/popup/pages/buy-cspr/amount.tsx index a6faccce4..2b5e65987 100644 --- a/src/apps/popup/pages/buy-cspr/amount.tsx +++ b/src/apps/popup/pages/buy-cspr/amount.tsx @@ -1,3 +1,4 @@ +import { formatNumber } from 'casper-wallet-core'; import React, { useEffect, useState } from 'react'; import { useForm, useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; @@ -24,7 +25,7 @@ import { Typography } from '@libs/ui/components'; import { useBuyCSPR } from '@libs/ui/forms/buy-cspr'; -import { formatNumber, handleNumericInput } from '@libs/ui/utils'; +import { handleNumericInput } from '@libs/ui/utils'; import { CurrencyRow } from './components/currency-row'; import { ListRow } from './components/list-row'; diff --git a/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx b/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx index 29300b1e3..6b4b9e393 100644 --- a/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx +++ b/src/apps/popup/pages/download-account-keys/components/account-list-item.tsx @@ -1,3 +1,4 @@ +import { formatNumber } from 'casper-wallet-core'; import { IAccountInfo } from 'casper-wallet-core/src/domain/accountInfo'; import React from 'react'; import styled from 'styled-components'; @@ -19,7 +20,7 @@ import { HashVariant, Typography } from '@libs/ui/components'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { motesToCSPR } from '@libs/ui/utils'; const ListItemContainer = styled(FlexColumn)` min-height: 68px; diff --git a/src/apps/popup/pages/stakes/components/validator-list.tsx b/src/apps/popup/pages/stakes/components/validator-list.tsx index a6741425b..6402c6cd5 100644 --- a/src/apps/popup/pages/stakes/components/validator-list.tsx +++ b/src/apps/popup/pages/stakes/components/validator-list.tsx @@ -1,3 +1,4 @@ +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer'; @@ -9,13 +10,12 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; -import { ValidatorResultWithId } from '@libs/services/validators-service'; import { Tile, Typography, ValidatorPlate } from '@libs/ui/components'; interface ValidatorListProps { - filteredValidatorsList: ValidatorResultWithId[]; - handleValidatorClick: (validator: ValidatorResultWithId) => void; - totalStake: 'total_stake' | 'user_stake'; + filteredValidatorsList: ValidatorDto[]; + handleValidatorClick: (validator: ValidatorDto) => void; + totalStake: 'formattedTotalStake' | 'formattedDecimalStake'; } const Container = styled.div``; @@ -48,24 +48,19 @@ export const ValidatorList = ({ rowCount={filteredValidatorsList.length} rowRenderer={({ index, key, style }) => { const validator = filteredValidatorsList[index]; - const logo = - validator?.account_info?.info?.owner?.branding?.logo?.svg || - validator?.account_info?.info?.owner?.branding?.logo - ?.png_256 || - validator?.account_info?.info?.owner?.branding?.logo - ?.png_1024; + const logo = validator?.svgLogo || validator?.imgLogo; return ( { handleValidatorClick(validator); }} diff --git a/src/apps/popup/pages/stakes/confirm-step.tsx b/src/apps/popup/pages/stakes/confirm-step.tsx index 11497a18f..01b4baf0f 100644 --- a/src/apps/popup/pages/stakes/confirm-step.tsx +++ b/src/apps/popup/pages/stakes/confirm-step.tsx @@ -1,4 +1,6 @@ import Big from 'big.js'; +import { formatNumber } from 'casper-wallet-core'; +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import React from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -14,9 +16,8 @@ import { } from '@libs/layout'; import { useFetchWalletBalance } from '@libs/services/balance-service'; import { getAuctionManagerDeployCost } from '@libs/services/deployer-service'; -import { ValidatorResult } from '@libs/services/validators-service/types'; import { List, Typography, ValidatorPlate } from '@libs/ui/components'; -import { formatFiatAmount, formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { formatFiatAmount, motesToCSPR } from '@libs/ui/utils'; const ListItemContainer = styled(SpaceBetweenFlexRow)` padding: 12px 16px; @@ -24,8 +25,8 @@ const ListItemContainer = styled(SpaceBetweenFlexRow)` interface ConfirmStepProps { inputAmountCSPR: string; - validator: ValidatorResult | null; - newValidator: ValidatorResult | null; + validator: ValidatorDto | null; + newValidator: ValidatorDto | null; stakeType: AuctionManagerEntryPoint; confirmStepText: string; } @@ -90,15 +91,11 @@ export const ConfirmStep = ({ <> diff --git a/src/apps/popup/pages/stakes/index.tsx b/src/apps/popup/pages/stakes/index.tsx index 3b485048f..c3a0f9e56 100644 --- a/src/apps/popup/pages/stakes/index.tsx +++ b/src/apps/popup/pages/stakes/index.tsx @@ -1,4 +1,6 @@ import { DeployUtil } from 'casper-js-sdk'; +import { formatNumber } from 'casper-wallet-core'; +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import React, { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; @@ -60,7 +62,6 @@ import { sendSignDeploy, signDeploy } from '@libs/services/deployer-service'; -import { ValidatorResultWithId } from '@libs/services/validators-service/types'; import { Button, HomePageTabsId, @@ -72,7 +73,7 @@ import { } from '@libs/ui/components'; import { calculateSubmitButtonDisabled } from '@libs/ui/forms/get-submit-button-state-from-validation'; import { useStakesForm } from '@libs/ui/forms/stakes-form'; -import { CSPRtoMotes, formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { CSPRtoMotes, motesToCSPR } from '@libs/ui/utils'; const ScrollContainer = styled(VerticalSpaceContainer)<{ isHidden: boolean; @@ -97,11 +98,8 @@ export const StakesPage = () => { const [validatorPublicKey, setValidatorPublicKey] = useState(''); const [newValidatorPublicKey, setNewValidatorPublicKey] = useState(''); const [inputAmountCSPR, setInputAmountCSPR] = useState(''); - const [validator, setValidator] = useState( - null - ); - const [newValidator, setNewValidator] = - useState(null); + const [validator, setValidator] = useState(null); + const [newValidator, setNewValidator] = useState(null); const [stakeAmountMotes, setStakeAmountMotes] = useState(''); const activeAccount = useSelector(selectVaultActiveAccount); @@ -123,19 +121,18 @@ export const StakesPage = () => { useStakeType(); const hasDelegationToSelectedValidator = undelegateValidatorList?.some( - accountDelegation => accountDelegation.public_key === validator?.public_key + accountDelegation => accountDelegation.publicKey === validator?.publicKey ); const hasDelegationToSelectedNewValidator = undelegateValidatorList?.some( - accountDelegation => - accountDelegation.public_key === newValidator?.public_key + accountDelegation => accountDelegation.publicKey === newValidator?.publicKey ); const { amountForm, validatorForm, newValidatorForm } = useStakesForm( accountBalance.liquidBalance, stakeType, stakeAmountMotes, - validator?.delegators_number, - newValidator?.delegators_number, + validator?.delegatorsNumber, + newValidator?.delegatorsNumber, hasDelegationToSelectedValidator, hasDelegationToSelectedNewValidator ); diff --git a/src/apps/popup/pages/stakes/redelegate-validator-dropdown-input.tsx b/src/apps/popup/pages/stakes/redelegate-validator-dropdown-input.tsx index 03648693f..acef10448 100644 --- a/src/apps/popup/pages/stakes/redelegate-validator-dropdown-input.tsx +++ b/src/apps/popup/pages/stakes/redelegate-validator-dropdown-input.tsx @@ -1,3 +1,4 @@ +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import React, { useEffect, useState } from 'react'; import { UseFormReturn, useWatch } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -12,17 +13,14 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; -import { ValidatorResultWithId } from '@libs/services/validators-service/types'; import { Input, SvgIcon, ValidatorPlate } from '@libs/ui/components'; import { StakeNewValidatorFormValues } from '@libs/ui/forms/stakes-form'; interface ValidatorDropdownInputProps { newValidatorForm: UseFormReturn; - validatorList: ValidatorResultWithId[] | null; - validator: ValidatorResultWithId | null; - setValidator: React.Dispatch< - React.SetStateAction - >; + validatorList: ValidatorDto[] | null; + validator: ValidatorDto | null; + setValidator: React.Dispatch>; setStakeAmount: React.Dispatch>; } @@ -59,9 +57,9 @@ export const RedelegateValidatorDropdownInput = ({ if (validator) { if (inputValue !== '') { setShowValidatorPlate(true); - setValue('newValidatorPublicKey', validator.public_key); - setStakeAmount(validator.user_stake!); - await resetAndTriggerPublicKey(validator.public_key); + setValue('newValidatorPublicKey', validator.publicKey); + setStakeAmount(validator.stake!); + await resetAndTriggerPublicKey(validator.publicKey); } else { setShowValidatorPlate(false); setValidator(null); @@ -90,9 +88,9 @@ export const RedelegateValidatorDropdownInput = ({ validatorList ); - const handleValidatorClick = (validator: ValidatorResultWithId) => { - setValue('newValidatorPublicKey', validator.public_key); - setStakeAmount(validator.user_stake!); + const handleValidatorClick = (validator: ValidatorDto) => { + setValue('newValidatorPublicKey', validator.publicKey); + setStakeAmount(validator.stake!); setValidator(validator); @@ -103,16 +101,12 @@ export const RedelegateValidatorDropdownInput = ({ return showValidatorPlate && validator ? ( { @@ -156,7 +150,7 @@ export const RedelegateValidatorDropdownInput = ({ {isOpenValidatorPublicKeysList && ( )} diff --git a/src/apps/popup/pages/stakes/utils.ts b/src/apps/popup/pages/stakes/utils.ts index cb011e327..c0ccad851 100644 --- a/src/apps/popup/pages/stakes/utils.ts +++ b/src/apps/popup/pages/stakes/utils.ts @@ -1,20 +1,14 @@ +import { formatNumber } from 'casper-wallet-core'; +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useSelector } from 'react-redux'; import { AuctionManagerEntryPoint } from '@src/constants'; import { useTypedLocation } from '@popup/router'; -import { selectApiConfigBasedOnActiveNetwork } from '@background/redux/settings/selectors'; -import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; - -import { - ValidatorResultWithId, - dispatchFetchAuctionValidatorsRequest, - dispatchFetchValidatorsDetailsDataRequest -} from '@libs/services/validators-service'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { useFetchValidators } from '@libs/services/validators-service'; +import { motesToCSPR } from '@libs/ui/utils'; type StakeTexts = { validatorStepHeaderText: string; @@ -62,7 +56,7 @@ const stakeActionsTextMap: StakeActionTextMap = { export const useFilteredValidators = ( inputValue: string | undefined, - validatorList: ValidatorResultWithId[] | null + validatorList: ValidatorDto[] | null ) => { return useMemo(() => { if (!validatorList) return []; @@ -74,10 +68,10 @@ export const useFilteredValidators = ( stringToCheck?.toLowerCase().includes(lowerCaseInput); return validatorList.filter(validator => { - const { public_key } = validator; - const ownerName = validator?.account_info?.info?.owner?.name; + const { publicKey } = validator; + const ownerName = validator?.name; - return isIncluded(ownerName) || isIncluded(public_key); + return isIncluded(ownerName) || isIncluded(publicKey); }); }, [inputValue, validatorList]); }; @@ -127,20 +121,21 @@ export const useStakeType = () => { const [stakeType, setStakeType] = useState( AuctionManagerEntryPoint.delegate ); - const [validatorList, setValidatorList] = useState< - ValidatorResultWithId[] | null - >(null); + const [validatorList, setValidatorList] = useState( + null + ); const [undelegateValidatorList, setUndelegateValidatorList] = useState< - ValidatorResultWithId[] | null + ValidatorDto[] | null >(null); - const [loading, setLoading] = useState(true); const { pathname } = useTypedLocation(); - const activeAccount = useSelector(selectVaultActiveAccount); - const { casperClarityApiUrl } = useSelector( - selectApiConfigBasedOnActiveNetwork - ); + const { + validators, + validatorsWithStakes, + isLoadingValidatorsWithStakes, + isLoadingValidators + } = useFetchValidators(); useEffect(() => { const name = pathname.split('/')[1]; @@ -150,68 +145,18 @@ export const useStakeType = () => { name === AuctionManagerEntryPoint.redelegate ) { setStakeType(name); - - if (activeAccount) { - Promise.all([ - dispatchFetchAuctionValidatorsRequest(), - dispatchFetchValidatorsDetailsDataRequest(activeAccount.publicKey) - ]) - .then(([allValidatorsResp, undelegateValidatorResp]) => { - if ('data' in allValidatorsResp.payload) { - const { data } = allValidatorsResp.payload; - - const validatorListWithId = data.map(validator => ({ - ...validator, - id: validator.public_key - })); - - setValidatorList(validatorListWithId); - } - if ('data' in undelegateValidatorResp.payload) { - const { data } = undelegateValidatorResp.payload; - - const validatorListWithId = data.map(delegator => ({ - ...delegator.validator, - id: delegator.validator_public_key, - user_stake: delegator.stake - })); - - setUndelegateValidatorList(validatorListWithId); - } - }) - .finally(() => { - setLoading(false); - }); - } + setValidatorList(validators); + setUndelegateValidatorList(validatorsWithStakes); } else if (name === AuctionManagerEntryPoint.undelegate) { setStakeType(name); - - if (activeAccount) { - dispatchFetchValidatorsDetailsDataRequest(activeAccount.publicKey) - .then(({ payload }) => { - if ('data' in payload) { - const { data } = payload; - - const validatorListWithId = data.map(delegator => ({ - ...delegator.validator, - id: delegator.validator_public_key, - user_stake: delegator.stake - })); - - setUndelegateValidatorList(validatorListWithId); - } - }) - .finally(() => { - setLoading(false); - }); - } + setUndelegateValidatorList(validatorsWithStakes); } - }, [activeAccount, pathname, casperClarityApiUrl]); + }, [pathname, validators, validatorsWithStakes]); return { stakeType, validatorList, undelegateValidatorList, - loading + loading: !(!isLoadingValidators && !isLoadingValidatorsWithStakes) }; }; diff --git a/src/apps/popup/pages/stakes/validator-dropdown-input.tsx b/src/apps/popup/pages/stakes/validator-dropdown-input.tsx index f7b043706..f5aed62e5 100644 --- a/src/apps/popup/pages/stakes/validator-dropdown-input.tsx +++ b/src/apps/popup/pages/stakes/validator-dropdown-input.tsx @@ -1,3 +1,4 @@ +import { ValidatorDto } from 'casper-wallet-core/src/data/dto/validators'; import React, { useEffect, useState } from 'react'; import { UseFormReturn, useWatch } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -14,17 +15,14 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; -import { ValidatorResultWithId } from '@libs/services/validators-service/types'; import { Input, Spinner, SvgIcon, ValidatorPlate } from '@libs/ui/components'; import { StakeValidatorFormValues } from '@libs/ui/forms/stakes-form'; interface ValidatorDropdownInputProps { validatorForm: UseFormReturn; - validatorList: ValidatorResultWithId[] | null; - validator: ValidatorResultWithId | null; - setValidator: React.Dispatch< - React.SetStateAction - >; + validatorList: ValidatorDto[] | null; + validator: ValidatorDto | null; + setValidator: React.Dispatch>; setStakeAmount: React.Dispatch>; stakeType: AuctionManagerEntryPoint; loading: boolean; @@ -66,9 +64,9 @@ export const ValidatorDropdownInput = ({ if (validator) { if (inputValue !== '') { setShowValidatorPlate(true); - setValue('validatorPublicKey', validator.public_key); - setStakeAmount(validator.user_stake!); - await resetAndTriggerPublicKey(validator.public_key); + setValue('validatorPublicKey', validator.publicKey); + setStakeAmount(validator.stake!); + await resetAndTriggerPublicKey(validator.publicKey); } else { setShowValidatorPlate(false); setValidator(null); @@ -111,9 +109,9 @@ export const ValidatorDropdownInput = ({ } }, [stakeType]); - const handleValidatorClick = (validator: ValidatorResultWithId) => { - setValue('validatorPublicKey', validator.public_key); - setStakeAmount(validator.user_stake!); + const handleValidatorClick = (validator: ValidatorDto) => { + setValue('validatorPublicKey', validator.publicKey); + setStakeAmount(validator.stake!); setValidator(validator); @@ -124,21 +122,17 @@ export const ValidatorDropdownInput = ({ return showValidatorPlate && validator ? ( { @@ -185,8 +179,8 @@ export const ValidatorDropdownInput = ({ filteredValidatorsList={filteredValidatorsList} totalStake={ stakeType === AuctionManagerEntryPoint.delegate - ? 'total_stake' - : 'user_stake' + ? 'formattedTotalStake' + : 'formattedDecimalStake' } handleValidatorClick={handleValidatorClick} /> diff --git a/src/apps/popup/pages/transfer/confirm-step.tsx b/src/apps/popup/pages/transfer/confirm-step.tsx index 5a2719c2c..4970b2f63 100644 --- a/src/apps/popup/pages/transfer/confirm-step.tsx +++ b/src/apps/popup/pages/transfer/confirm-step.tsx @@ -1,4 +1,5 @@ import Big from 'big.js'; +import { formatNumber } from 'casper-wallet-core'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -22,7 +23,7 @@ import { RecipientPlate, Typography } from '@libs/ui/components'; -import { formatFiatAmount, formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { formatFiatAmount, motesToCSPR } from '@libs/ui/utils'; const ListItemContainer = styled(SpaceBetweenFlexRow)` padding: 12px 16px; diff --git a/src/apps/signature-request/pages/sign-deploy/deploy-value.tsx b/src/apps/signature-request/pages/sign-deploy/deploy-value.tsx index 44c65d31b..2a3c51b73 100644 --- a/src/apps/signature-request/pages/sign-deploy/deploy-value.tsx +++ b/src/apps/signature-request/pages/sign-deploy/deploy-value.tsx @@ -1,8 +1,9 @@ import { CLValue } from 'casper-js-sdk'; +import { formatNumber } from 'casper-wallet-core'; import React from 'react'; import { Hash, HashVariant, Typography } from '@libs/ui/components'; -import { formatDate, formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { formatDate, motesToCSPR } from '@libs/ui/utils'; import { getDeployParsedValue, diff --git a/src/background/index.ts b/src/background/index.ts index 4a516893a..a37652f29 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -103,10 +103,6 @@ import { fetchOnRampOptionPost, fetchOnRampSelectionPost } from '@libs/services/buy-cspr-service'; -import { - fetchAuctionValidators, - fetchValidatorsDetailsData -} from '@libs/services/validators-service'; import { CannotGetActiveAccountError, @@ -148,7 +144,6 @@ import { themeModeSettingChanged, vaultSettingsReseted } from './redux/settings/actions'; -import { selectApiConfigBasedOnActiveNetwork } from './redux/settings/selectors'; import { vaultCipherCreated, vaultCipherReseted @@ -612,47 +607,6 @@ runtime.onMessage.addListener( return; // SERVICE MESSAGE HANDLERS - case getType(serviceMessage.fetchAuctionValidatorsRequest): { - const { casperClarityApiUrl } = selectApiConfigBasedOnActiveNetwork( - store.getState() - ); - - try { - const data = await fetchAuctionValidators({ - casperClarityApiUrl - }); - - return sendResponse( - serviceMessage.fetchAuctionValidatorsResponse(data) - ); - } catch (error) { - console.error(error); - } - - return; - } - - case getType(serviceMessage.fetchValidatorsDetailsDataRequest): { - const { casperClarityApiUrl } = selectApiConfigBasedOnActiveNetwork( - store.getState() - ); - - try { - const data = await fetchValidatorsDetailsData({ - casperClarityApiUrl, - publicKey: action.payload.publicKey - }); - - return sendResponse( - serviceMessage.fetchValidatorsDetailsDataResponse(data) - ); - } catch (error) { - console.error(error); - } - - return; - } - case getType(serviceMessage.fetchOnRampGetOptionRequest): { try { const data = await fetchOnRampOptionGet(); diff --git a/src/background/redux/settings/selectors.ts b/src/background/redux/settings/selectors.ts index 05e10e3f8..56e33d5a9 100644 --- a/src/background/redux/settings/selectors.ts +++ b/src/background/redux/settings/selectors.ts @@ -7,10 +7,8 @@ import { AuctionPoolContractHash, CSPRMarketContractHash, CSPRStudioCep47ContractHash, - CasperClarityApiUrl, CasperLiveUrl, CasperNodeUrl, - CasperWalletApiUrl, NetworkName, NetworkSetting } from '@src/constants'; @@ -28,8 +26,6 @@ export const selectApiConfigBasedOnActiveNetwork = createSelector( case NetworkSetting.Mainnet: return { casperLiveUrl: CasperLiveUrl.MainnetUrl, - casperClarityApiUrl: CasperClarityApiUrl.MainnetUrl, - casperWalletApiUrl: CasperWalletApiUrl.MainnetUrl, networkName: NetworkName.Mainnet, nodeUrl: CasperNodeUrl.MainnetUrl, auctionManagerContractHash: AuctionManagerContractHash.Mainnet, @@ -41,8 +37,6 @@ export const selectApiConfigBasedOnActiveNetwork = createSelector( case NetworkSetting.Testnet: return { casperLiveUrl: CasperLiveUrl.TestnetUrl, - casperClarityApiUrl: CasperClarityApiUrl.TestnetUrl, - casperWalletApiUrl: CasperWalletApiUrl.TestnetUrl, networkName: NetworkName.Testnet, nodeUrl: CasperNodeUrl.TestnetUrl, auctionManagerContractHash: AuctionManagerContractHash.Testnet, diff --git a/src/background/service-message.ts b/src/background/service-message.ts index dcaa48b06..8a3ee6a8b 100644 --- a/src/background/service-message.ts +++ b/src/background/service-message.ts @@ -7,27 +7,10 @@ import { ResponseSelectionProps, SelectionPostRequestData } from '@libs/services/buy-cspr-service/types'; -import { ErrorResponse, PaginatedResponse } from '@libs/services/types'; -import { - DelegatorResult, - ValidatorResult -} from '@libs/services/validators-service/types'; type Meta = void; export const serviceMessage = { - fetchAuctionValidatorsRequest: createAction( - 'FETCH_AUCTION_VALIDATORS' - )(), - fetchAuctionValidatorsResponse: createAction( - 'FETCH_AUCTION_VALIDATORS_RESPONSE' - ) | ErrorResponse, Meta>(), - fetchValidatorsDetailsDataRequest: createAction( - 'FETCH_VALIDATORS_DETAILS_DATA' - )<{ publicKey: string }, Meta>(), - fetchValidatorsDetailsDataResponse: createAction( - 'FETCH_VALIDATORS_DETAILS_DATA_RESPONSE' - ) | ErrorResponse, Meta>(), fetchOnRampGetOptionRequest: createAction( 'FETCH_ON_RAMP_GET_OPTION_REQUEST' )(), diff --git a/src/background/wallet-repositories.ts b/src/background/wallet-repositories.ts index f7f89598e..d1a400366 100644 --- a/src/background/wallet-repositories.ts +++ b/src/background/wallet-repositories.ts @@ -4,12 +4,14 @@ const { deploysRepository, accountInfoRepository, tokensRepository, - nftsRepository + nftsRepository, + validatorsRepository } = setupRepositories(); export { deploysRepository, accountInfoRepository, tokensRepository, - nftsRepository + nftsRepository, + validatorsRepository }; diff --git a/src/constants.ts b/src/constants.ts index 16fe7d3c3..91127d39c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -54,16 +54,6 @@ export enum CasperLiveUrl { TestnetUrl = 'https://testnet.cspr.live' } -export enum CasperClarityApiUrl { - MainnetUrl = 'https://event-store-api-clarity-mainnet.make.services', - TestnetUrl = 'https://event-store-api-clarity-testnet.make.services' -} - -export enum CasperWalletApiUrl { - MainnetUrl = 'https://api.mainnet.casperwallet.io', - TestnetUrl = 'https://api.testnet.casperwallet.io' -} - export enum NetworkSetting { Mainnet = 'Mainnet', Testnet = 'Testnet' diff --git a/src/libs/services/types.ts b/src/libs/services/types.ts index 61206325d..d00d6fd00 100644 --- a/src/libs/services/types.ts +++ b/src/libs/services/types.ts @@ -2,17 +2,6 @@ export interface Payload { payload: T; } -export interface PaginatedResponse { - data: T[]; - itemCount: number; - pageCount: number; - pages: any[]; -} - -export interface DataResponse { - data: T; -} - export interface ErrorResponse { error: { message: string; diff --git a/src/libs/services/validators-service/constants.ts b/src/libs/services/validators-service/constants.ts deleted file mode 100644 index 614a0d2bd..000000000 --- a/src/libs/services/validators-service/constants.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const getAuctionValidatorsUrl = (casperClarityApiUrl: string) => - `${casperClarityApiUrl}/auction-validators?page=1&limit=-1&fields=account_info,average_performance&is_active=true`; - -export const getValidatorsDetailsDataUrl = ( - casperClarityApiUrl: string, - publicKey: string -) => ` - ${casperClarityApiUrl}/accounts/${publicKey}/delegations?page=1&limit=100&fields=validator,validator_account_info -`; diff --git a/src/libs/services/validators-service/index.ts b/src/libs/services/validators-service/index.ts index 963aa288f..b3666016f 100644 --- a/src/libs/services/validators-service/index.ts +++ b/src/libs/services/validators-service/index.ts @@ -1,3 +1 @@ -export * from './types'; -export * from './validators-service'; -export * from './constants'; +export * from './use-fetch-validators'; diff --git a/src/libs/services/validators-service/types.ts b/src/libs/services/validators-service/types.ts deleted file mode 100644 index 486a4c5b0..000000000 --- a/src/libs/services/validators-service/types.ts +++ /dev/null @@ -1,124 +0,0 @@ -export interface ValidatorResult { - fee: number; - is_active: boolean; - self_stake: string; - bid_amount: string; - total_stake: string; - self_share: string; - public_key: string; - network_share: string; - era_id: number; - delegators_number: number; - delegator_stake: string; - rank: number; - account_info?: AccountInfoResult; - average_performance?: ValidatorAveragePerformanceResult; -} - -export interface ValidatorResultWithId extends ValidatorResult { - id: string; - user_stake?: string; -} - -export interface ValidatorAveragePerformanceResult { - era_id: number; - public_key: string; - average_score: number; // between 0 and 100, treat it as percentage -} - -export interface AccountInfoResult { - account_hash: string; - url: string; - is_active: boolean; - deploy_hash: string; - verified_account_hashes: string[]; - info?: { - owner?: AccountInfoOwner; - nodes?: Array; - }; -} - -export interface AccountInfoOwner { - name?: string; - description?: string; - type?: Array; - email?: string; - identity?: { - ownership_disclosure_url?: string; - casper_association_kyc_url?: string; - casper_association_kyc_onchain?: string; - }; - resources?: { - code_of_conduct_url?: string; - terms_of_service_url?: string; - privacy_policy_url?: string; - other?: Array<{ - name?: string; - url?: string; - }>; - }; - affiliated_accounts?: Array; - website?: string; - branding?: { - logo?: { - svg?: string; - png_256?: string; - png_1024?: string; - }; - }; - location?: { - name?: string; - country?: string; - latitude?: number; - longitude?: number; - }; - social?: { - github?: string; - medium?: string; - reddit?: string; - wechat?: string; - keybase?: string; - twitter?: string; - youtube?: string; - facebook?: string; - telegram?: string; - }; -} - -export interface AccountInfoAffiliatedAccount { - public_key?: string; -} - -export interface AccountInfoNode { - public_key?: string; - description?: string; - functionality?: string[]; - location?: { - name?: string; - country?: string; - latitude?: number; - longitude?: number; - }; -} - -export interface DelegatorResult { - validator_public_key: string; - public_key: string; - stake: string; - bonding_purse: string; - account_info?: AccountInfoResult; - validator_account_info?: ValidatorAccountInfoResult; - validator: ValidatorResult; -} - -export interface ValidatorAccountInfoResult { - account_hash: string; - deploy_hash: string; - info: { - owner?: AccountInfoOwner; - nodes?: Array; - }; - is_active: boolean; - url: string; - verified_account_hashes: string[]; -} diff --git a/src/libs/services/validators-service/use-fetch-validators.ts b/src/libs/services/validators-service/use-fetch-validators.ts new file mode 100644 index 000000000..5ad5829e6 --- /dev/null +++ b/src/libs/services/validators-service/use-fetch-validators.ts @@ -0,0 +1,61 @@ +import { useQueries } from '@tanstack/react-query'; +import { CasperNetwork } from 'casper-wallet-core/src/domain/common/common'; +import { useSelector } from 'react-redux'; + +import { VALIDATORS_REFRESH_RATE } from '@src/constants'; + +import { selectActiveNetworkSetting } from '@background/redux/settings/selectors'; +import { selectVaultActiveAccount } from '@background/redux/vault/selectors'; +import { validatorsRepository } from '@background/wallet-repositories'; + +export const useFetchValidators = () => { + const activeAccount = useSelector(selectVaultActiveAccount); + const network = useSelector(selectActiveNetworkSetting); + + const { + validators, + validatorsWithStakes, + isLoadingValidators, + isLoadingValidatorsWithStakes + } = useQueries({ + queries: [ + { + queryKey: ['VALIDATORS', network], + queryFn: () => + validatorsRepository.getValidators({ + network: network.toLowerCase() as CasperNetwork + }), + staleTime: VALIDATORS_REFRESH_RATE + }, + { + queryKey: ['VALIDATORS_WITH_STAKE', network, activeAccount?.publicKey], + queryFn: () => + validatorsRepository.getValidatorsWithStakes({ + network: network.toLowerCase() as CasperNetwork, + publicKey: activeAccount?.publicKey || '' + }), + staleTime: VALIDATORS_REFRESH_RATE + } + ], + combine: results => { + const validators = results[0].data || null; + const isLoadingValidators = results[0].isLoading; + const validatorsWithStakes = results[1].data || null; + const isLoadingValidatorsWithStakes = results[1].isLoading; + + return { + validators, + validatorsWithStakes, + isLoadingValidators, + isLoadingValidatorsWithStakes + }; + } + }); + + return { + validators, + validatorsWithStakes, + isLoadingValidators, + isLoadingValidatorsWithStakes + }; +}; diff --git a/src/libs/services/validators-service/validators-service.ts b/src/libs/services/validators-service/validators-service.ts deleted file mode 100644 index 3de2d9fb0..000000000 --- a/src/libs/services/validators-service/validators-service.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { VALIDATORS_REFRESH_RATE } from '@src/constants'; - -import { dispatchToMainStore } from '@background/redux/utils'; -import { serviceMessage } from '@background/service-message'; - -import { queryClient } from '@libs/services/query-client'; -import { - ErrorResponse, - PaginatedResponse, - Payload -} from '@libs/services/types'; -import { handleError, toJson } from '@libs/services/utils'; -import { - getAuctionValidatorsUrl, - getValidatorsDetailsDataUrl -} from '@libs/services/validators-service/constants'; -import { - DelegatorResult, - ValidatorResult -} from '@libs/services/validators-service/types'; - -export const auctionValidatorsRequest = ( - casperClarityApiUrl: string, - signal?: AbortSignal -) => - fetch(getAuctionValidatorsUrl(casperClarityApiUrl), { signal }) - .then(toJson) - .catch(handleError); - -export const validatorsDetailsDataRequest = ( - casperClarityApiUrl: string, - publicKey: string, - signal?: AbortSignal -) => - fetch(getValidatorsDetailsDataUrl(casperClarityApiUrl, publicKey), { signal }) - .then(toJson) - .catch(handleError); - -export const fetchAuctionValidators = ({ - casperClarityApiUrl -}: { - casperClarityApiUrl: string; -}): Promise | ErrorResponse> => - queryClient.fetchQuery( - ['getAuctionValidators', casperClarityApiUrl], - ({ signal }) => auctionValidatorsRequest(casperClarityApiUrl, signal), - { - staleTime: VALIDATORS_REFRESH_RATE - } - ); - -export const fetchValidatorsDetailsData = ({ - casperClarityApiUrl, - publicKey -}: { - casperClarityApiUrl: string; - publicKey: string; -}): Promise | ErrorResponse> => - queryClient.fetchQuery( - ['getDelegations', casperClarityApiUrl, publicKey], - ({ signal }) => - validatorsDetailsDataRequest(casperClarityApiUrl, publicKey, signal), - { - staleTime: VALIDATORS_REFRESH_RATE - } - ); - -export const dispatchFetchAuctionValidatorsRequest = (): Promise< - Payload | ErrorResponse> -> => dispatchToMainStore(serviceMessage.fetchAuctionValidatorsRequest()); - -export const dispatchFetchValidatorsDetailsDataRequest = ( - publicKey: string -): Promise | ErrorResponse>> => - dispatchToMainStore( - serviceMessage.fetchValidatorsDetailsDataRequest({ publicKey }) - ); diff --git a/src/libs/ui/components/account-list/account-list-item.tsx b/src/libs/ui/components/account-list/account-list-item.tsx index d7f7b9e80..c0024fec4 100644 --- a/src/libs/ui/components/account-list/account-list-item.tsx +++ b/src/libs/ui/components/account-list/account-list-item.tsx @@ -1,3 +1,4 @@ +import { formatNumber } from 'casper-wallet-core'; import { IAccountInfo } from 'casper-wallet-core/src/domain/accountInfo'; import React from 'react'; import styled from 'styled-components'; @@ -19,7 +20,7 @@ import { HashVariant, Typography } from '@libs/ui/components'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { motesToCSPR } from '@libs/ui/utils'; const ListItemContainer = styled(FlexColumn)` min-height: 68px; diff --git a/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx b/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx index b15cecf37..ca502d535 100644 --- a/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx +++ b/src/libs/ui/components/dynamic-accounts-list-with-select/dynamic-accounts-list-with-select.tsx @@ -1,4 +1,5 @@ import { Player } from '@lottiefiles/react-lottie-player'; +import { formatNumber } from 'casper-wallet-core'; import { ICsprBalance } from 'casper-wallet-core/src/domain/tokens'; import React, { useEffect, useState } from 'react'; import { @@ -44,7 +45,7 @@ import { Typography } from '@libs/ui/components'; import { calculateSubmitButtonDisabled } from '@libs/ui/forms/get-submit-button-state-from-validation'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { motesToCSPR } from '@libs/ui/utils'; const ListItemContainer = styled(FlexColumn)<{ disabled?: boolean }>` padding: 12px 16px; diff --git a/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx b/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx index da8dd3d73..75ddfe2e2 100644 --- a/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx +++ b/src/libs/ui/components/transaction-fee-plate/transaction-fee-plate.tsx @@ -1,3 +1,4 @@ +import { formatNumber } from 'casper-wallet-core'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -10,7 +11,7 @@ import { } from '@libs/layout'; import { useFetchWalletBalance } from '@libs/services/balance-service'; import { Tile, Typography } from '@libs/ui/components'; -import { formatFiatAmount, formatNumber, motesToCSPR } from '@libs/ui/utils'; +import { formatFiatAmount, motesToCSPR } from '@libs/ui/utils'; const TransactionFeeContainer = styled(AlignedSpaceBetweenFlexRow)` padding: 10px 16px; diff --git a/src/libs/ui/components/validator-plate/validator-plate.tsx b/src/libs/ui/components/validator-plate/validator-plate.tsx index 96b7c0a2f..d44844ade 100644 --- a/src/libs/ui/components/validator-plate/validator-plate.tsx +++ b/src/libs/ui/components/validator-plate/validator-plate.tsx @@ -1,4 +1,6 @@ -import React, { useEffect, useState } from 'react'; +import { formatNumber } from 'casper-wallet-core'; +import { Maybe } from 'casper-wallet-core/src/typings/common'; +import React from 'react'; import { FieldError } from 'react-hook-form'; import styled from 'styled-components'; @@ -21,7 +23,6 @@ import { HashVariant, Typography } from '@libs/ui/components'; -import { formatNumber, motesToCSPR } from '@libs/ui/utils/formatters'; const ValidatorPlateContainer = styled(AlignedFlexRow)<{ onClick?: () => void; @@ -62,11 +63,11 @@ interface ValidatorPlateProps { name?: string; logo?: string; showFullPublicKey?: boolean; - fee: number; + fee: string; delegatorsNumber?: number; validatorLabel?: string; error?: FieldError; - totalStake?: string; + formattedTotalStake?: Maybe; withBorder?: boolean; } @@ -80,26 +81,16 @@ export const ValidatorPlate = ({ delegatorsNumber, validatorLabel, error, - totalStake, + formattedTotalStake, withBorder }: ValidatorPlateProps) => { - const [formattedTotalStake, setFormattedTotalStake] = useState(''); - - useEffect(() => { - if (totalStake) { - setFormattedTotalStake(formatNumber(motesToCSPR(totalStake))); - } - }, [totalStake]); - const logoUrl = getImageProxyUrl(logo); - const formattedFee = formatNumber(fee, { - precision: { min: 2 } - }); + const getFormattedDelegatorsNumber = () => { if (delegatorsNumber && delegatorsNumber >= 1000) { return ( formatNumber(delegatorsNumber / 1000, { - precision: { max: 2 } + precision: { max: 3 } }) + 'k' ); } @@ -168,7 +159,7 @@ export const ValidatorPlate = ({ - {`${formattedFee}% fee`} + {`${fee}% fee`} {getFormattedDelegatorsNumber()} delegators diff --git a/src/libs/ui/utils/formatters.ts b/src/libs/ui/utils/formatters.ts index ce3919771..36c81b3bf 100644 --- a/src/libs/ui/utils/formatters.ts +++ b/src/libs/ui/utils/formatters.ts @@ -106,35 +106,6 @@ export const formatTimestampAge = (value: string): string => { })}`; }; -export const formatNumber = ( - value: number | string, - { - precision, - notation, - compactDisplay - }: { - precision?: { min?: number; max?: number }; - notation?: 'compact' | 'standard'; - compactDisplay?: 'short' | 'long'; - } = {} -): string => - intl.formatNumber(value as number, { - minimumFractionDigits: precision?.min || 0, - maximumFractionDigits: precision?.max || precision?.min || 0, - notation, - compactDisplay - }); - -export function formatMotes(motes: string) { - const int = Number.parseInt(motes); - - if (Number.isNaN(int)) { - throw new Error('Parsing motes failed'); - } - - return int.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' '); -} - export const motesToCSPR = (motes: string): string => { return Big(motes).div(MOTES_PER_CSPR_RATE).toFixed(); }; diff --git a/src/utils.ts b/src/utils.ts index 04fe6f68e..5da81f424 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -143,6 +143,7 @@ export const RETINA_SCALE = 2; export const IMAGE_WIDTH = 376; export const CACHE_TTL = '2592000'; +// TODO: use isKeysEqual form casper wallet core export const isEqualCaseInsensitive = (key1: string, key2: string) => { if (!(key1 && key2)) { return false; From d274a9ca0289fe0fa8d650a1ac0daa6a2231a045 Mon Sep 17 00:00:00 2001 From: Ostap Piatkovskyi <44294945+ost-ptk@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:31:25 +0200 Subject: [PATCH 2/2] feature: migrate on Ramp fetching to the casper wallet core (#1077) * migrate on Ramp fetching to the casper wallet core * removed the old version of the react-query (#1078) --- package-lock.json | 168 +---------- package.json | 1 - src/apps/popup/pages/buy-cspr/amount.tsx | 30 +- .../pages/buy-cspr/components/country-row.tsx | 75 ++--- .../buy-cspr/components/currency-row.tsx | 6 +- .../pages/buy-cspr/components/list-row.tsx | 18 +- src/apps/popup/pages/buy-cspr/country.tsx | 38 ++- src/apps/popup/pages/buy-cspr/index.tsx | 285 ++++++++---------- src/apps/popup/pages/buy-cspr/provider.tsx | 8 +- src/apps/popup/pages/buy-cspr/utils.ts | 12 +- src/background/index.ts | 55 +--- src/background/redux/utils.ts | 4 +- src/background/service-message.ts | 34 --- src/background/wallet-repositories.ts | 6 +- .../services/buy-cspr-service/constants.ts | 2 - src/libs/services/buy-cspr-service/index.ts | 81 +---- src/libs/services/buy-cspr-service/types.ts | 73 ----- ...-fetch-on-ramp-countries-and-currencies.ts | 65 ++++ .../use-get-on-ramp-providers.ts | 24 ++ src/libs/services/query-client.ts | 3 - src/libs/services/types.ts | 11 - src/libs/ui/components/spinner/spinner.tsx | 8 +- 22 files changed, 330 insertions(+), 677 deletions(-) delete mode 100644 src/background/service-message.ts delete mode 100644 src/libs/services/buy-cspr-service/constants.ts delete mode 100644 src/libs/services/buy-cspr-service/types.ts create mode 100644 src/libs/services/buy-cspr-service/use-fetch-on-ramp-countries-and-currencies.ts create mode 100644 src/libs/services/buy-cspr-service/use-get-on-ramp-providers.ts delete mode 100644 src/libs/services/types.ts diff --git a/package-lock.json b/package-lock.json index 89be6b1b5..c5376a666 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,6 @@ "react-inlinesvg": "3.0.3", "react-loading-skeleton": "^3.3.1", "react-player": "^2.13.0", - "react-query": "^3.39.3", "react-redux": "8.0.5", "react-router-dom": "6.16.0", "react-virtualized": "^9.22.5", @@ -9778,6 +9777,7 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, "engines": { "node": ">=0.6" } @@ -10064,21 +10064,6 @@ "node": ">=8" } }, - "node_modules/broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - } - }, "node_modules/broccoli-node-api": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz", @@ -13143,7 +13128,8 @@ "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true }, "node_modules/diff": { "version": "4.0.2", @@ -20099,11 +20085,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -21721,15 +21702,6 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "dev": true }, - "node_modules/match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -21872,11 +21844,6 @@ "node": ">=8.6" } }, - "node_modules/microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -22257,14 +22224,6 @@ "dev": true, "optional": true }, - "node_modules/nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "dependencies": { - "big-integer": "^1.6.16" - } - }, "node_modules/nanoclone": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", @@ -22820,11 +22779,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -24530,31 +24484,6 @@ "react": ">=16.6.0" } }, - "node_modules/react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, "node_modules/react-redux": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", @@ -24947,11 +24876,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, "node_modules/remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -28110,15 +28034,6 @@ "node": ">= 10.0.0" } }, - "node_modules/unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "dependencies": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -37143,7 +37058,8 @@ "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true }, "big.js": { "version": "6.2.1", @@ -37367,21 +37283,6 @@ "fill-range": "^7.1.1" } }, - "broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "requires": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - } - }, "broccoli-node-api": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz", @@ -39644,7 +39545,8 @@ "detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true }, "diff": { "version": "4.0.2", @@ -44805,11 +44707,6 @@ "integrity": "sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ==", "dev": true }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -46045,15 +45942,6 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "dev": true }, - "match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "requires": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, "matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -46168,11 +46056,6 @@ "picomatch": "^2.3.1" } }, - "microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -46464,14 +46347,6 @@ "dev": true, "optional": true }, - "nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "requires": { - "big-integer": "^1.6.16" - } - }, "nanoclone": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", @@ -46883,11 +46758,6 @@ "es-abstract": "^1.22.1" } }, - "oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -48136,16 +48006,6 @@ "react-fast-compare": "^3.0.1" } }, - "react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "requires": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - } - }, "react-redux": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", @@ -48433,11 +48293,6 @@ } } }, - "remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -50883,15 +50738,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, - "unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "requires": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 389ba938a..ec6022556 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,6 @@ "react-inlinesvg": "3.0.3", "react-loading-skeleton": "^3.3.1", "react-player": "^2.13.0", - "react-query": "^3.39.3", "react-redux": "8.0.5", "react-router-dom": "6.16.0", "react-virtualized": "^9.22.5", diff --git a/src/apps/popup/pages/buy-cspr/amount.tsx b/src/apps/popup/pages/buy-cspr/amount.tsx index 2b5e65987..c797d94ad 100644 --- a/src/apps/popup/pages/buy-cspr/amount.tsx +++ b/src/apps/popup/pages/buy-cspr/amount.tsx @@ -1,4 +1,5 @@ import { formatNumber } from 'casper-wallet-core'; +import { IOnRampCurrencyItem } from 'casper-wallet-core/src/domain'; import React, { useEffect, useState } from 'react'; import { useForm, useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; @@ -15,7 +16,6 @@ import { SpacingSize, VerticalSpaceContainer } from '@libs/layout'; -import { ResponseCurrencyProps } from '@libs/services/buy-cspr-service/types'; import { Input, List, @@ -31,23 +31,23 @@ import { CurrencyRow } from './components/currency-row'; import { ListRow } from './components/list-row'; interface AmountProps { - currencies: ResponseCurrencyProps[]; - selectedCurrency: ResponseCurrencyProps; + availableCurrencies: IOnRampCurrencyItem[]; + selectedCurrency: IOnRampCurrencyItem; setPaymentAmount: React.Dispatch>; setSelectedCurrency: React.Dispatch< - React.SetStateAction + React.SetStateAction >; defaultAmount: string; } export const Amount = ({ - currencies, + availableCurrencies, selectedCurrency, setPaymentAmount, setSelectedCurrency, defaultAmount }: AmountProps) => { - const [sortedCurrency, setSortedCurrency] = useState( + const [sortedCurrency, setSortedCurrency] = useState( [] ); const { t } = useTranslation(); @@ -91,16 +91,17 @@ export const Amount = ({ useEffect(() => { const sortedCurrencies = sortCurrencies( - currencies, - selectedCurrency.code - ).filter(currency => - currency.code - .toLowerCase() - .includes(searchInputValue?.toLowerCase() || '') + availableCurrencies, + selectedCurrency?.code + ).filter( + currency => + currency?.code + .toLowerCase() + .includes(searchInputValue?.toLowerCase() || '') ); setSortedCurrency(sortedCurrencies); - }, [currencies, searchInputValue, selectedCurrency.code]); + }, [availableCurrencies, searchInputValue, selectedCurrency?.code]); return ( @@ -143,7 +144,8 @@ export const Amount = ({ rows={sortedCurrency} height={280} renderRow={currency => { - const isSelected = selectedCurrency.code === currency.code; + const isSelected = + selectedCurrency?.code === currency?.code; return ( void; + isLoadingOnRampCountriesAndCurrencies: boolean; } -export const CountryRow = ({ country, onClick }: CountryRowProps) => { - const [iconSrc, setIconSrc] = useState(''); - +export const CountryRow = ({ + country, + onClick, + isLoadingOnRampCountriesAndCurrencies +}: CountryRowProps) => { const { t } = useTranslation(); - useEffect(() => { - if (country.code) { - setIconSrc( - `https://purecatamphetamine.github.io/country-flag-icons/3x2/${country.code}.svg` - ); - } - }, [country.code]); - - const handleError = () => { - setIconSrc('/assets/icons/placeholder-image-gray.svg'); - }; - return ( - + Country @@ -53,24 +47,31 @@ export const CountryRow = ({ country, onClick }: CountryRowProps) => { - {`${country.name}`} - - {country.name} - + {isLoadingOnRampCountriesAndCurrencies ? ( + + ) : ( + <> + {`${country?.name}`} + + {country?.name} + + + )} - - Change - + {isLoadingOnRampCountriesAndCurrencies ? null : ( + + Change + + )} diff --git a/src/apps/popup/pages/buy-cspr/components/currency-row.tsx b/src/apps/popup/pages/buy-cspr/components/currency-row.tsx index 89e799c28..b50cb5602 100644 --- a/src/apps/popup/pages/buy-cspr/components/currency-row.tsx +++ b/src/apps/popup/pages/buy-cspr/components/currency-row.tsx @@ -1,9 +1,9 @@ +import { IOnRampCurrencyItem } from 'casper-wallet-core/src/domain'; import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { CenteredFlexColumn, SpacingSize } from '@libs/layout'; -import { ResponseCurrencyProps } from '@libs/services/buy-cspr-service/types'; import { Tile, Typography } from '@libs/ui/components'; const Container = styled.div` @@ -11,7 +11,7 @@ const Container = styled.div` `; interface CurrencyRowProps { - selectedCurrency: ResponseCurrencyProps; + selectedCurrency: IOnRampCurrencyItem; onClick: () => void; } @@ -33,7 +33,7 @@ export const CurrencyRow = ({ color="contentAction" dataTestId="currency-row" > - {selectedCurrency.code} + {selectedCurrency?.code} diff --git a/src/apps/popup/pages/buy-cspr/components/list-row.tsx b/src/apps/popup/pages/buy-cspr/components/list-row.tsx index c97e13aa8..034847112 100644 --- a/src/apps/popup/pages/buy-cspr/components/list-row.tsx +++ b/src/apps/popup/pages/buy-cspr/components/list-row.tsx @@ -1,3 +1,7 @@ +import { + IOnRampCountry, + IOnRampCurrencyItem +} from 'casper-wallet-core/src/domain'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; @@ -6,10 +10,6 @@ import { AlignedSpaceBetweenFlexRow, SpacingSize } from '@libs/layout'; -import { - ResponseCountryPropsWithId, - ResponseCurrencyProps -} from '@libs/services/buy-cspr-service/types'; import { Checkbox, Typography } from '@libs/ui/components'; const Container = styled(AlignedSpaceBetweenFlexRow)` @@ -19,10 +19,10 @@ const Container = styled(AlignedSpaceBetweenFlexRow)` `; interface ListRowProps { - country?: ResponseCountryPropsWithId; + country?: IOnRampCountry; handleSelect: (e: React.MouseEvent) => void; isSelected: boolean; - currency?: ResponseCurrencyProps; + currency?: IOnRampCurrencyItem; } export const ListRow = ({ @@ -53,18 +53,18 @@ export const ListRow = ({ {country && ( <> {`${country.name}`} - {country.name} + {country?.name} )} {currency && ( - {currency.code} + {currency?.code} )} diff --git a/src/apps/popup/pages/buy-cspr/country.tsx b/src/apps/popup/pages/buy-cspr/country.tsx index 87cb8c7d1..54293eabf 100644 --- a/src/apps/popup/pages/buy-cspr/country.tsx +++ b/src/apps/popup/pages/buy-cspr/country.tsx @@ -1,3 +1,4 @@ +import { IOnRampCountry } from 'casper-wallet-core/src/domain'; import React, { useEffect, useState } from 'react'; import { useForm, useWatch } from 'react-hook-form'; import { Trans, useTranslation } from 'react-i18next'; @@ -9,7 +10,6 @@ import { SpacingSize } from '@libs/layout'; import { useFetchWalletBalance } from '@libs/services/balance-service'; -import { ResponseCountryPropsWithId } from '@libs/services/buy-cspr-service/types'; import { ActiveAccountPlate, Input, @@ -25,20 +25,22 @@ import { ListRow } from './components/list-row'; import { sortCountries } from './utils'; interface CountryProps { - availableCountries: ResponseCountryPropsWithId[]; - setSelectedCountry: React.Dispatch< - React.SetStateAction - >; - selectedCountry: ResponseCountryPropsWithId; + availableCountries: IOnRampCountry[]; + setSelectedCountry: React.Dispatch>; + selectedCountry: IOnRampCountry; + isLoadingOnRampCountriesAndCurrencies: boolean; } +type ExtendedOnRampCountry = IOnRampCountry & { id: number }; + export const Country = ({ availableCountries, setSelectedCountry, - selectedCountry + selectedCountry, + isLoadingOnRampCountriesAndCurrencies }: CountryProps) => { const [sortedCountries, setSortedCountries] = useState< - ResponseCountryPropsWithId[] + ExtendedOnRampCountry[] >([]); const { t } = useTranslation(); @@ -54,11 +56,16 @@ export const Country = ({ useEffect(() => { const sortedCountries = sortCountries( availableCountries, - selectedCountry.code - ).filter( - country => - country?.name.toLowerCase().includes(inputValue?.toLowerCase() || '') - ); + selectedCountry?.code + ) + .filter( + country => + country?.name.toLowerCase().includes(inputValue?.toLowerCase() || '') + ) + .map((country, index) => ({ + ...country, + id: index + })); setSortedCountries(sortedCountries); }, [availableCountries, inputValue, selectedCountry]); @@ -92,7 +99,7 @@ export const Country = ({ rows={sortedCountries} height={280} renderRow={country => { - const isSelected = selectedCountry.code === country.code; + const isSelected = selectedCountry?.code === country?.code; return ( setValue('countryNameSearch', '')} + isLoadingOnRampCountriesAndCurrencies={ + isLoadingOnRampCountriesAndCurrencies + } /> )} loading={!sortedCountries.length} diff --git a/src/apps/popup/pages/buy-cspr/index.tsx b/src/apps/popup/pages/buy-cspr/index.tsx index 2391ee9cf..f87eec164 100644 --- a/src/apps/popup/pages/buy-cspr/index.tsx +++ b/src/apps/popup/pages/buy-cspr/index.tsx @@ -1,3 +1,10 @@ +import { + IGetOnRampProvidersData, + IOnRampCountry, + IOnRampCurrencyItem, + IOnRampProvider, + IProviderSelectionData +} from 'casper-wallet-core/src/domain'; import React, { useEffect, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; @@ -14,17 +21,8 @@ import { PopupLayout, createErrorLocationState } from '@libs/layout'; -import { - dispatchFetchOnRampOptionGet, - dispatchFetchOnRampOptionPost, - dispatchFetchOnRampSelectionPost -} from '@libs/services/buy-cspr-service'; -import { - ProviderProps, - ResponseCountryPropsWithId, - ResponseCurrencyProps, - SelectionPostRequestData -} from '@libs/services/buy-cspr-service/types'; +import { useFetchOnRampCountriesAndCurrencies } from '@libs/services/buy-cspr-service/use-fetch-on-ramp-countries-and-currencies'; +import { useGetOnRampProviders } from '@libs/services/buy-cspr-service/use-get-on-ramp-providers'; import { Button, Typography } from '@libs/ui/components'; import { Amount } from './amount'; @@ -36,160 +34,131 @@ import { BuyCSPRSteps } from './utils'; export const BuyCSPRPage = () => { const [buyCSPRStep, setBuyCSPRStep] = useState(BuyCSPRSteps.Country); const [availableCountries, setAvailableCountries] = useState< - ResponseCountryPropsWithId[] + IOnRampCountry[] >([]); - const [selectedCountry, setSelectedCountry] = - useState({ - id: 0, - name: '', - code: '' - }); - const [currencies, setCurrencies] = useState([]); - const [selectedCurrency, setSelectedCurrency] = - useState({ + const [selectedCountry, setSelectedCountry] = useState({ + name: '', + code: '', + flagUri: '' + }); + const [availableCurrencies, setAvailableCurrencies] = useState< + IOnRampCurrencyItem[] + >([]); + const [selectedCurrency, setSelectedCurrency] = useState( + { id: 0, code: '', type_id: '', rate: 0 - }); + } + ); const [defaultAmount, setDefaultAmount] = useState('0'); const [fiatAmount, setFiatAmount] = useState(0); - const [availableProviders, setAvailableProviders] = useState( - [] - ); + const [availableProviders, setAvailableProviders] = useState< + IOnRampProvider[] + >([]); const [selectedProvider, setSelectedProvider] = - useState(null); - const [loadingAvailableProviders, setLoadingAvailableProviders] = - useState(false); - const [loadingRedirectUrl, setLoadingRedirectUrl] = useState(false); + useState(null); const { t } = useTranslation(); const navigate = useTypedNavigate(); const activeAccount = useSelector(selectVaultActiveAccount); - useEffect(() => { - dispatchFetchOnRampOptionGet() - .then(({ payload }) => { - if ('countries' in payload) { - const countriesWithId = payload.countries.map((country, id) => ({ - id, - ...country - })); - - const defaultSelectedCountry = countriesWithId.find( - country => country.code === payload.defaultCountry - ); + const { + currencies, + countries, + defaultCountry, + defaultCurrency, + defaultDepositAmount, + isLoadingOnRampCountriesAndCurrencies, + onRampCountriesAndCurrenciesError + } = useFetchOnRampCountriesAndCurrencies(); + const { + getOnRampProviders, + isProvidersLoading, + isProviderLocationLoading, + getOnRampProviderLocation + } = useGetOnRampProviders(); - const defaultSelectedCurrency = payload.currencies.find( - currency => currency.code === payload.defaultCurrency - ); + useEffect(() => { + if (onRampCountriesAndCurrenciesError) { + navigate( + ErrorPath, + createErrorLocationState({ + errorHeaderText: t('Something went wrong'), + errorContentText: + onRampCountriesAndCurrenciesError.message || + t( + 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' + ), + errorPrimaryButtonLabel: t('Close'), + errorRedirectPath: RouterPath.Home + }) + ); + } + if (isLoadingOnRampCountriesAndCurrencies) return; - setAvailableCountries(countriesWithId); - setCurrencies(payload.currencies); - setSelectedCountry(defaultSelectedCountry!); - setSelectedCurrency(defaultSelectedCurrency!); - setDefaultAmount(payload.defaultAmount); - setFiatAmount(Number(payload.defaultAmount)); - } else { - navigate( - ErrorPath, - createErrorLocationState({ - errorHeaderText: t('Something went wrong'), - errorContentText: - payload.error.message || - t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), - errorPrimaryButtonLabel: t('Close'), - errorRedirectPath: RouterPath.Home - }) - ); - } - }) - .catch(error => { - console.error(error.message, 'countries request failed'); - - navigate( - ErrorPath, - createErrorLocationState({ - errorHeaderText: error.message || t('Something went wrong'), - errorContentText: - typeof error.data === 'string' - ? error.data - : t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), - errorPrimaryButtonLabel: t('Close'), - errorRedirectPath: RouterPath.Home - }) - ); - }); - }, [navigate, t]); + setAvailableCountries(countries); + setAvailableCurrencies(currencies); + setSelectedCountry(defaultCountry!); + setSelectedCurrency(defaultCurrency!); + setDefaultAmount(defaultDepositAmount!); + setFiatAmount(Number(defaultDepositAmount)); + }, [ + countries, + currencies, + defaultCountry, + defaultCurrency, + defaultDepositAmount, + isLoadingOnRampCountriesAndCurrencies, + navigate, + onRampCountriesAndCurrenciesError, + t + ]); const handleAmountSubmit = () => { - setLoadingAvailableProviders(true); - - dispatchFetchOnRampOptionPost({ + const data: IGetOnRampProvidersData = { amount: fiatAmount, - country: selectedCountry.code, - fiatCurrency: selectedCurrency.code, - paymentCurrency: selectedCurrency.code - }) - .then(({ payload }) => { - if ('availableProviders' in payload) { - if (payload.availableProviders.length === 0) { - setBuyCSPRStep(BuyCSPRSteps.NoProvider); - } else { - setAvailableProviders(payload.availableProviders); - - if (payload.availableProviders.length === 1) { - setSelectedProvider(payload.availableProviders[0]); - } + country: selectedCountry?.code, + fiatCurrency: selectedCurrency?.code, + paymentCurrency: selectedCurrency?.code + }; + getOnRampProviders(data, { + onSuccess: onRampProviders => { + if (onRampProviders.availableProviders.length === 0) { + setBuyCSPRStep(BuyCSPRSteps.NoProvider); + } else { + setAvailableProviders(onRampProviders.availableProviders); - setBuyCSPRStep(BuyCSPRSteps.Provider); + if (onRampProviders.availableProviders.length === 1) { + setSelectedProvider(onRampProviders.availableProviders[0]); } - } else { - navigate( - ErrorPath, - createErrorLocationState({ - errorHeaderText: t('Something went wrong'), - errorContentText: - payload.error.message || - t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), - errorPrimaryButtonLabel: t('Close'), - errorRedirectPath: RouterPath.Home - }) - ); - } - }) - .catch(error => { - console.error(error.message, 'available provider request failed'); + setBuyCSPRStep(BuyCSPRSteps.Provider); + } + }, + onError: error => { navigate( ErrorPath, createErrorLocationState({ - errorHeaderText: error.message || t('Something went wrong'), + errorHeaderText: t('Something went wrong'), errorContentText: - typeof error.data === 'string' - ? error.data - : t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), + error.message || + t( + 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' + ), errorPrimaryButtonLabel: t('Close'), errorRedirectPath: RouterPath.Home }) ); - }) - .finally(() => setLoadingAvailableProviders(false)); + } + }); }; const handleSubmit = () => { - setLoadingRedirectUrl(true); if (activeAccount && selectedProvider) { - const data: SelectionPostRequestData = { + const data: IProviderSelectionData = { account: activeAccount.publicKey, fiatCurrency: selectedCurrency.code, cryptoAmount: null, @@ -198,45 +167,28 @@ export const BuyCSPRPage = () => { fiatAmount }; - dispatchFetchOnRampSelectionPost(data) - .then(({ payload }) => { - if ('location' in payload) { - window.open(payload.location, '_blank'); - } else { - navigate( - ErrorPath, - createErrorLocationState({ - errorHeaderText: t('Something went wrong'), - errorContentText: - payload.error.message || - t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), - errorPrimaryButtonLabel: t('Close'), - errorRedirectPath: RouterPath.Home - }) - ); - } - }) - .catch(error => { + getOnRampProviderLocation(data, { + onSuccess: providerLocation => { + window.open(providerLocation.location, '_blank'); + }, + onError: error => { console.error(error.message, 'provider selection request failed'); navigate( ErrorPath, createErrorLocationState({ - errorHeaderText: error.message || t('Something went wrong'), + errorHeaderText: t('Something went wrong'), errorContentText: - typeof error.data === 'string' - ? error.data - : t( - 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' - ), + error.message || + t( + 'Please check browser console for error details, this will be a valuable for our team to fix the issue.' + ), errorPrimaryButtonLabel: t('Close'), errorRedirectPath: RouterPath.Home }) ); - }) - .finally(() => setLoadingRedirectUrl(false)); + } + }); } }; @@ -246,11 +198,14 @@ export const BuyCSPRPage = () => { availableCountries={availableCountries} selectedCountry={selectedCountry} setSelectedCountry={setSelectedCountry} + isLoadingOnRampCountriesAndCurrencies={ + isLoadingOnRampCountriesAndCurrencies + } /> ), [BuyCSPRSteps.Amount]: ( { ), [BuyCSPRSteps.NoProvider]: ( ) }; @@ -302,7 +257,7 @@ export const BuyCSPRPage = () => { <> @@ -317,7 +272,7 @@ export const BuyCSPRPage = () => { ) : null}