Skip to content

Commit

Permalink
fix: validate withdraw form address by destination type instead of wa…
Browse files Browse the repository at this point in the history
…llet type (#969)

Co-authored-by: Bill He <[email protected]>
  • Loading branch information
tinaszheng and rosepuppy authored Aug 29, 2024
1 parent e86ffe9 commit 3cb269d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
16 changes: 16 additions & 0 deletions src/lib/addressUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fromBech32, fromHex, toBech32, toHex } from '@cosmjs/encoding';
import { isAddress } from 'viem';

/**
*
Expand Down Expand Up @@ -37,3 +38,18 @@ export function validateCosmosAddress(address: string, prefix: string) {
return false;
}
}

type MultiChainAddress =
| { address?: string | null; network: 'cosmos'; prefix: string }
| { address?: string | null; network: 'evm' };

// TODO: Add unit test once `isAddress` works with vitest
export function isValidAddress(input: MultiChainAddress): boolean {
if (!input.address) return false;

if (input.network === 'evm') {
return isAddress(input.address, { strict: true }); // enable checksum matching
}

return validateCosmosAddress(input.address, input.prefix);
}
46 changes: 19 additions & 27 deletions src/views/forms/AccountManagementForms/WithdrawForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import type { NumberFormatValues } from 'react-number-format';
import { shallowEqual } from 'react-redux';
import styled from 'styled-components';
import { isAddress } from 'viem';

import { TransferInputField, TransferInputTokenResource, TransferType } from '@/constants/abacus';
import { AlertType } from '@/constants/alerts';
Expand Down Expand Up @@ -65,7 +64,7 @@ import { getTransferInputs } from '@/state/inputsSelectors';
import { getSelectedLocale } from '@/state/localizationSelectors';

import abacusStateManager from '@/lib/abacus';
import { validateCosmosAddress } from '@/lib/addressUtils';
import { isValidAddress } from '@/lib/addressUtils';
import { track } from '@/lib/analytics/analytics';
import { getRouteErrorMessageOverride } from '@/lib/errors';
import { MustBigNumber } from '@/lib/numbers';
Expand Down Expand Up @@ -106,20 +105,17 @@ export const WithdrawForm = () => {
const { usdcLabel } = useTokenConfigs();
const { usdcWithdrawalCapacity } = useWithdrawalInfo({ transferType: 'withdrawal' });

const isValidAddress = useMemo(() => {
if (toAddress) {
if (walletType === WalletType.Keplr) {
const prefix = GRAZ_CHAINS.find((chain) => chain.chainId === chainIdStr)?.bech32Config
.bech32PrefixAccAddr;

if (prefix) {
return validateCosmosAddress(toAddress, prefix);
}
}
return isAddress(toAddress);
}
return false;
}, [chainIdStr, toAddress, walletType]);
const isValidDestinationAddress = useMemo(() => {
const grazChainPrefix =
GRAZ_CHAINS.find((chain) => chain.chainId === chainIdStr)?.bech32Config.bech32PrefixAccAddr ??
'';
const prefix = exchange ? 'noble' : grazChainPrefix;
return isValidAddress({
address: toAddress,
network: prefix ? 'cosmos' : 'evm',
prefix,
});
}, [exchange, toAddress, chainIdStr]);

const toToken = useMemo(
() => (token ? resources?.tokenResources?.get(token) : undefined),
Expand Down Expand Up @@ -356,7 +352,7 @@ export const WithdrawForm = () => {
value: nobleChainId,
});
}
}, [walletType]);
}, [nobleChainId, walletType]);

const onSelectNetwork = useCallback(
(name: string, type: 'chain' | 'exchange') => {
Expand Down Expand Up @@ -475,7 +471,7 @@ export const WithdrawForm = () => {
}),
};

if (!isValidAddress) {
if (!isValidDestinationAddress) {
return {
errorMessage: stringGetter({
key: STRING_KEYS.ENTER_VALID_ADDRESS,
Expand Down Expand Up @@ -569,22 +565,18 @@ export const WithdrawForm = () => {
stringGetter,
summary,
usdcWithdrawalCapacity,
isValidAddress,
isValidDestinationAddress,
]);

const isInvalidNobleAddress = Boolean(
exchange && toAddress && !validateCosmosAddress(toAddress, 'noble')
);

const isDisabled =
!!errorMessage ||
!toToken ||
(!chainIdStr && !exchange) ||
!toAddress ||
debouncedAmountBN.isNaN() ||
debouncedAmountBN.isZero() ||
isLoading ||
isInvalidNobleAddress;
!isValidDestinationAddress;

const skipEnabled = useStatsigGateValue(StatSigFlags.ffSkipMigration);

return (
Expand Down Expand Up @@ -614,7 +606,7 @@ export const WithdrawForm = () => {
label={
<span>
{stringGetter({ key: STRING_KEYS.DESTINATION })}{' '}
{isValidAddress ? (
{isValidDestinationAddress ? (
<Icon
iconName={IconName.Check}
tw="mx-[1ch] my-0 text-[0.625rem] text-color-success"
Expand All @@ -629,7 +621,7 @@ export const WithdrawForm = () => {
onSelect={onSelectNetwork}
/>
</div>
{isInvalidNobleAddress && (
{toAddress && Boolean(exchange) && !isValidDestinationAddress && (
<AlertMessage type={AlertType.Error}>
{stringGetter({ key: STRING_KEYS.NOBLE_ADDRESS_VALIDATION })}
</AlertMessage>
Expand Down

0 comments on commit 3cb269d

Please sign in to comment.