From b4f402da907666d38fbf7d0e29cd7f4b3d2cf383 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 21 Oct 2024 15:59:51 +1000 Subject: [PATCH 1/2] fix: Clear destination account input value after switching from chain --- .../SelectModal/SourceNetworkModal.tsx | 5 ++++- .../transfer/components/ToAccount/index.tsx | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/SourceNetworkModal.tsx b/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/SourceNetworkModal.tsx index 7aa2e454..401f3ed8 100644 --- a/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/SourceNetworkModal.tsx +++ b/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/SourceNetworkModal.tsx @@ -1,6 +1,6 @@ import { Flex, useColorMode, useIntl, useTheme } from '@bnb-chain/space'; -import { useAppSelector } from '@/modules/store/StoreProvider'; +import { useAppDispatch, useAppSelector } from '@/modules/store/StoreProvider'; import { useFromChains } from '@/modules/aggregator/hooks/useFromChains'; import { VirtualList } from '@/core/components/VirtualList'; import { useSelection } from '@/modules/aggregator/hooks/useSelection'; @@ -10,6 +10,7 @@ import { BaseModal } from '@/modules/aggregator/components/SelectModal/component import { useSearch } from '@/modules/aggregator/components/SelectModal/hooks/useSearch'; import { ListItem } from '@/modules/aggregator/components/SelectModal/components/ListItem'; import { reportEvent } from '@/core/utils/gtm'; +import { setToAccount } from '@/modules/transfer/action'; interface SourceNetworkModalProps { isOpen: boolean; @@ -19,6 +20,7 @@ interface SourceNetworkModalProps { export function SourceNetworkModal(props: SourceNetworkModalProps) { const { isOpen, onClose } = props; const { formatMessage } = useIntl(); + const dispatch = useAppDispatch(); const fromChain = useAppSelector((state) => state.transfer.fromChain); const toChain = useAppSelector((state) => state.transfer.toChain); @@ -67,6 +69,7 @@ export function SourceNetworkModal(props: SourceNetworkModalProps) { openLink(item.externalBridgeUrl); } else { selectFromChain(item); + dispatch(setToAccount({ address: '' })); onClose(); } }} diff --git a/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx b/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx index 71b63e2f..2671657c 100644 --- a/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx +++ b/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx @@ -10,6 +10,7 @@ import { InputRightElement, } from '@bnb-chain/space'; import { ChangeEvent, useRef, useState } from 'react'; +import { useEffect } from 'react'; import { setIsToAddressChecked, setToAccount } from '@/modules/transfer/action'; import { useTronTransferInfo } from '@/modules/transfer/hooks/tron/useTronTransferInfo'; @@ -46,6 +47,11 @@ export function ToAccount(props: FlexProps) { }, 500); }; + useEffect(() => { + // Clear input value when toAccount is cleared + if (!toAccount.address) setInputValue(''); + }, [toAccount.address]); + if (!isTronTransfer) { return null; } @@ -106,6 +112,12 @@ export function ToAccount(props: FlexProps) { )} + {isInvalid && ( + + {formatMessage({ id: 'to.section.account.invalid' })} + + )} + {formatMessage({ id: 'to.section.confirm.text' })} - - {isInvalid && ( - - {formatMessage({ id: 'to.section.account.invalid' })} - - )} ); } From d68321053c6f02da13a8340278e9ec35090776f5 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 21 Oct 2024 18:10:30 +1000 Subject: [PATCH 2/2] feat: Tron address validation --- .../adapters/meson/hooks/useTronContract.ts | 21 +++++++++++++++++++ .../transfer/components/ToAccount/index.tsx | 13 +++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 packages/canonical-bridge-widget/src/modules/aggregator/adapters/meson/hooks/useTronContract.ts diff --git a/packages/canonical-bridge-widget/src/modules/aggregator/adapters/meson/hooks/useTronContract.ts b/packages/canonical-bridge-widget/src/modules/aggregator/adapters/meson/hooks/useTronContract.ts new file mode 100644 index 00000000..bb98d879 --- /dev/null +++ b/packages/canonical-bridge-widget/src/modules/aggregator/adapters/meson/hooks/useTronContract.ts @@ -0,0 +1,21 @@ +import { useTronWeb } from '@/core/hooks/useTronWeb'; + +export const useTronContract = () => { + const tronWeb = useTronWeb(); + + const isTronContractInfo = async (address: string) => { + if (!tronWeb) return; + try { + const contractInfo = await tronWeb.trx.getContract(address); + return !!contractInfo?.bytecode; + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + return false; + } + }; + + return { + isTronContractInfo, + }; +}; diff --git a/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx b/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx index 2671657c..3e4b7633 100644 --- a/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx +++ b/packages/canonical-bridge-widget/src/modules/transfer/components/ToAccount/index.tsx @@ -18,6 +18,7 @@ import { ErrorIcon } from '@/core/components/icons/ErrorIcon'; import { CorrectIcon } from '@/core/components/icons/CorrectIcon'; import { useAppDispatch, useAppSelector } from '@/modules/store/StoreProvider'; import { ConfirmCheckbox } from '@/core/components/ConfirmCheckbox'; +import { useTronContract } from '@/modules/aggregator/adapters/meson/hooks/useTronContract'; export function ToAccount(props: FlexProps) { const { colorMode } = useColorMode(); @@ -25,11 +26,13 @@ export function ToAccount(props: FlexProps) { const dispatch = useAppDispatch(); const [isChecked, setIsChecked] = useState(false); + const [isTronContract, setIsTronContract] = useState(null); const toAccount = useAppSelector((state) => state.transfer.toAccount); const toChain = useAppSelector((state) => state.transfer.toChain); const { isTronTransfer, isAvailableAccount } = useTronTransferInfo(); + const { isTronContractInfo } = useTronContract(); const timerRef = useRef(); const [inputValue, setInputValue] = useState(toAccount.address); @@ -38,12 +41,16 @@ export function ToAccount(props: FlexProps) { setInputValue(value); clearTimeout(timerRef.current); - timerRef.current = setTimeout(() => { + timerRef.current = setTimeout(async () => { dispatch( setToAccount({ address: value, }), ); + if (toChain?.chainType === 'tron') { + const result = await isTronContractInfo(value); + setIsTronContract(result === true); + } }, 500); }; @@ -56,7 +63,7 @@ export function ToAccount(props: FlexProps) { return null; } - const isInvalid = !isAvailableAccount && !!toAccount.address; + const isInvalid = (!isAvailableAccount && !!toAccount.address) || isTronContract === false; const onCheckboxChange = (e: React.ChangeEvent) => { if (e.target.checked === true) { @@ -107,7 +114,7 @@ export function ToAccount(props: FlexProps) { {(isInvalid || isAvailableAccount) && ( {isInvalid && } - {isAvailableAccount && } + {isAvailableAccount && !isInvalid && } )}