From f86dcd090e6ff4a1f419960ebc545a82348cb9eb Mon Sep 17 00:00:00 2001 From: wenty22 Date: Fri, 6 Dec 2024 14:47:07 +0800 Subject: [PATCH] feat: Show token address on `You Receive` --- .release/.changeset/light-emus-switch.md | 5 + .release/.changeset/pre.json | 13 ++ .release/.changeset/sharp-dryers-hear.md | 5 + .release/.changeset/slimy-crabs-know.md | 5 + .../token-config/mainnet/chains.ts | 28 ++-- .../token-config/mainnet/useTransferConfig.ts | 2 +- packages/canonical-bridge-widget/CHANGELOG.md | 31 ++++ packages/canonical-bridge-widget/package.json | 2 +- .../src/core/components/InfoTooltip/index.tsx | 29 ++-- .../src/core/components/icons/AlertIcon.tsx | 27 ++++ .../src/core/locales/en.ts | 4 +- .../src/core/utils/address.ts | 2 +- .../SelectModal/ChooseTokenModal.tsx | 27 ++-- .../transfer/components/ReceiveInfo/index.tsx | 1 + .../TransferOverview/RouteInfo/RouteTitle.tsx | 133 +++++++++++++++--- 15 files changed, 250 insertions(+), 64 deletions(-) create mode 100644 .release/.changeset/light-emus-switch.md create mode 100644 .release/.changeset/pre.json create mode 100644 .release/.changeset/sharp-dryers-hear.md create mode 100644 .release/.changeset/slimy-crabs-know.md create mode 100644 packages/canonical-bridge-widget/src/core/components/icons/AlertIcon.tsx diff --git a/.release/.changeset/light-emus-switch.md b/.release/.changeset/light-emus-switch.md new file mode 100644 index 00000000..a63eadc9 --- /dev/null +++ b/.release/.changeset/light-emus-switch.md @@ -0,0 +1,5 @@ +--- +'@bnb-chain/canonical-bridge-widget': patch +--- + +Show token address on `You Receive` diff --git a/.release/.changeset/pre.json b/.release/.changeset/pre.json new file mode 100644 index 00000000..a2f4fa95 --- /dev/null +++ b/.release/.changeset/pre.json @@ -0,0 +1,13 @@ +{ + "mode": "pre", + "tag": "alpha", + "initialVersions": { + "@bnb-chain/canonical-bridge-sdk": "0.4.2", + "@bnb-chain/canonical-bridge-widget": "0.5.7" + }, + "changesets": [ + "light-emus-switch", + "sharp-dryers-hear", + "slimy-crabs-know" + ] +} diff --git a/.release/.changeset/sharp-dryers-hear.md b/.release/.changeset/sharp-dryers-hear.md new file mode 100644 index 00000000..4c231116 --- /dev/null +++ b/.release/.changeset/sharp-dryers-hear.md @@ -0,0 +1,5 @@ +--- +"@bnb-chain/canonical-bridge-widget": patch +--- + +Support searching token by address diff --git a/.release/.changeset/slimy-crabs-know.md b/.release/.changeset/slimy-crabs-know.md new file mode 100644 index 00000000..d819d83e --- /dev/null +++ b/.release/.changeset/slimy-crabs-know.md @@ -0,0 +1,5 @@ +--- +"@bnb-chain/canonical-bridge-widget": patch +--- + +Show token address on `You Receive` diff --git a/apps/canonical-bridge-ui/token-config/mainnet/chains.ts b/apps/canonical-bridge-ui/token-config/mainnet/chains.ts index e66aa78b..1edae413 100644 --- a/apps/canonical-bridge-ui/token-config/mainnet/chains.ts +++ b/apps/canonical-bridge-ui/token-config/mainnet/chains.ts @@ -1,6 +1,20 @@ import { IChainConfig } from '@bnb-chain/canonical-bridge-widget'; export const chains: IChainConfig[] = [ + { + id: 56, + name: 'BNB Smart Chain', + nativeCurrency: { + name: 'BNB Chain Native Token', + symbol: 'BNB', + decimals: 18, + }, + rpcUrl: 'https://bsc-dataseed.bnbchain.org', + explorer: { + name: 'bscscan', + url: 'https://bscscan.com', + }, + }, { id: 1, name: 'Ethereum', @@ -71,20 +85,6 @@ export const chains: IChainConfig[] = [ url: 'https://crab-scan.darwinia.network', }, }, - { - id: 56, - name: 'BNB Smart Chain', - nativeCurrency: { - name: 'BNB Chain Native Token', - symbol: 'BNB', - decimals: 18, - }, - rpcUrl: 'https://bsc-dataseed.bnbchain.org', - explorer: { - name: 'bscscan', - url: 'https://bscscan.com', - }, - }, { id: 57, name: 'Syscoin', diff --git a/apps/canonical-bridge-ui/token-config/mainnet/useTransferConfig.ts b/apps/canonical-bridge-ui/token-config/mainnet/useTransferConfig.ts index a68d93bb..aab46a77 100644 --- a/apps/canonical-bridge-ui/token-config/mainnet/useTransferConfig.ts +++ b/apps/canonical-bridge-ui/token-config/mainnet/useTransferConfig.ts @@ -125,7 +125,7 @@ export function useTransferConfig() { exclude: { chains: [], tokens: { - 1: ['cUSDCv3'], + 1: ['cUSDCv3', '0x5e21d1ee5cf0077b314c381720273ae82378d613'], 56: [ '0x67d66e8ec1fd25d98b3ccd3b19b7dc4b4b7fc493', '0x0000000000000000000000000000000000000000', diff --git a/packages/canonical-bridge-widget/CHANGELOG.md b/packages/canonical-bridge-widget/CHANGELOG.md index 7ae3936b..37efd502 100644 --- a/packages/canonical-bridge-widget/CHANGELOG.md +++ b/packages/canonical-bridge-widget/CHANGELOG.md @@ -1,5 +1,36 @@ # @bnb-chain/canonical-bridge-widget +## 0.5.8-alpha.4 + +### Patch Changes + +- Show token address on `You Receive` + +## 0.5.8-alpha.3 + +### Patch Changes + +- Show token address on `You Receive` + +## 0.5.8-alpha.2 + +### Patch Changes + +- Support searching token by address + +## 0.5.8-alpha.1 + +### Patch Changes + +- Show token address on `You Receive` +- Show token address on `You Receive` + +## 0.5.8-alpha.0 + +### Patch Changes + +- Show token address on `You Recivce` + ## 0.5.7 ### Patch Changes diff --git a/packages/canonical-bridge-widget/package.json b/packages/canonical-bridge-widget/package.json index 2eaa8ef1..eb4ef0ed 100644 --- a/packages/canonical-bridge-widget/package.json +++ b/packages/canonical-bridge-widget/package.json @@ -1,6 +1,6 @@ { "name": "@bnb-chain/canonical-bridge-widget", - "version": "0.5.7", + "version": "0.5.8-alpha.4", "description": "canonical bridge widget", "author": "bnb-chain", "private": false, diff --git a/packages/canonical-bridge-widget/src/core/components/InfoTooltip/index.tsx b/packages/canonical-bridge-widget/src/core/components/InfoTooltip/index.tsx index 6dd4aed3..9658f8cb 100644 --- a/packages/canonical-bridge-widget/src/core/components/InfoTooltip/index.tsx +++ b/packages/canonical-bridge-widget/src/core/components/InfoTooltip/index.tsx @@ -6,17 +6,32 @@ import { useBreakpointValue, useDisclosure, } from '@bnb-chain/space'; +import React from 'react'; +import { useMemo } from 'react'; interface InfoTooltipProps extends Omit { iconProps?: IconProps; + children?: React.ReactElement; } export const InfoTooltip = (props: InfoTooltipProps) => { - const { iconProps, ...restProps } = props; + const { iconProps, children, ...restProps } = props; // Make tooltip controlled on mobile devices, default tooltip doesn't work. const isBase = useBreakpointValue({ base: true, md: false }) ?? false; const { isOpen, onOpen, onToggle, onClose } = useDisclosure(); + const clone = useMemo(() => { + const element = children || ; + return React.cloneElement(element, { + ...iconProps, + ...(isBase && { + onMouseEnter: onOpen, + onMouseLeave: onClose, + onClick: onToggle, + }), + }); + }, [children, iconProps, isBase, onClose, onOpen, onToggle]); + if (!restProps.label) return null; return ( { })} {...restProps} > - + {clone} ); }; diff --git a/packages/canonical-bridge-widget/src/core/components/icons/AlertIcon.tsx b/packages/canonical-bridge-widget/src/core/components/icons/AlertIcon.tsx new file mode 100644 index 00000000..1e04ee42 --- /dev/null +++ b/packages/canonical-bridge-widget/src/core/components/icons/AlertIcon.tsx @@ -0,0 +1,27 @@ +import { Icon, IconProps } from '@bnb-chain/space'; + +export function AlertIcon(props: IconProps) { + return ( + + + + + + + + + ); +} diff --git a/packages/canonical-bridge-widget/src/core/locales/en.ts b/packages/canonical-bridge-widget/src/core/locales/en.ts index 2991cc42..ad0829fa 100644 --- a/packages/canonical-bridge-widget/src/core/locales/en.ts +++ b/packages/canonical-bridge-widget/src/core/locales/en.ts @@ -24,6 +24,8 @@ export const en = { 'route.fees.title': 'Fees:', 'route.time.title': 'Time:', 'route.allowed-send-amount': 'Your send amount should be between {min} to {max} {symbol}', + 'route.token-address.tips': + 'Please double check the received token address before making the transaction.', 'route.no-found.title': 'No Available Routes', 'route.no-found.desc': `Low liquidity, small input, or incompatible network/token. Adjust and retry.`, @@ -84,7 +86,7 @@ export const en = { 'Try adjusting your search request to find what you’re looking for', 'select-modal.token.title': 'Choose Token', - 'select-modal.token.placeholder': 'Search token by name', + 'select-modal.token.placeholder': 'Search token by name or address', 'select-modal.token.column.name': 'Name', 'select-modal.token.column.balance': 'Wallet Balance', 'select-modal.token.incompatible.tooltip': diff --git a/packages/canonical-bridge-widget/src/core/utils/address.ts b/packages/canonical-bridge-widget/src/core/utils/address.ts index 89bf1b60..6147ccef 100644 --- a/packages/canonical-bridge-widget/src/core/utils/address.ts +++ b/packages/canonical-bridge-widget/src/core/utils/address.ts @@ -50,7 +50,7 @@ export function isEvmAddress(address?: string) { return !!address && /^0x[a-f0-9]{40}$/i.test(address); } -export function isNativeToken(tokenAddress: string, chainType: ChainType = 'evm') { +export function isNativeToken(tokenAddress?: string, chainType: ChainType = 'evm') { if (chainType === 'solana') { return tokenAddress === '11111111111111111111111111111111'; } diff --git a/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/ChooseTokenModal.tsx b/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/ChooseTokenModal.tsx index 2b9e162e..84ccf876 100644 --- a/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/ChooseTokenModal.tsx +++ b/packages/canonical-bridge-widget/src/modules/aggregator/components/SelectModal/ChooseTokenModal.tsx @@ -48,7 +48,8 @@ export function ChooseTokenModal(props: ChooseTokenModalProps) { filter: (item, keyword) => { return ( item.displaySymbol?.toLowerCase().includes(keyword) || - item.name?.toLowerCase().includes(keyword) + item.name?.toLowerCase().includes(keyword) || + isSameAddress(item.address, keyword) ); }, }); @@ -146,24 +147,22 @@ export function ChooseTokenModal(props: ChooseTokenModalProps) { - {(!isActive || isNative) && ( - - {item.name} - - )} + + {item.name} + {!isNative && ( { receiveAmt ? formatNumber(Number(Number(receiveAmt)), 8) : undefined } toTokenInfo={toTokenInfo?.[bridgeType]} + hoverToShowTokenAddress={false} /> )} diff --git a/packages/canonical-bridge-widget/src/modules/transfer/components/TransferOverview/RouteInfo/RouteTitle.tsx b/packages/canonical-bridge-widget/src/modules/transfer/components/TransferOverview/RouteInfo/RouteTitle.tsx index 69a5423a..5bd08573 100644 --- a/packages/canonical-bridge-widget/src/modules/transfer/components/TransferOverview/RouteInfo/RouteTitle.tsx +++ b/packages/canonical-bridge-widget/src/modules/transfer/components/TransferOverview/RouteInfo/RouteTitle.tsx @@ -1,23 +1,34 @@ -import { Flex, useColorMode, useTheme } from '@bnb-chain/space'; +import { Center, Flex, Link, useColorMode, useIntl, useTheme } from '@bnb-chain/space'; +import React from 'react'; import { TokenInfoTooltip } from '@/modules/transfer/components/TransferOverview/RouteInfo/TokenInfoTooltip'; import { IconImage } from '@/core/components/IconImage'; import { useAppSelector } from '@/modules/store/StoreProvider'; import { formatTokenUrl } from '@/core/utils/string'; import { IBridgeTokenBaseInfo } from '@/modules/aggregator/types'; +import { AlertIcon } from '@/core/components/icons/AlertIcon'; +import { InfoTooltip } from '@/core/components/InfoTooltip'; +import { formatAppAddress, isNativeToken } from '@/core/utils/address'; interface RouteTitleProps { receiveAmt?: string; toTokenInfo?: IBridgeTokenBaseInfo; isError?: boolean; + hoverToShowTokenAddress?: boolean; } -export const RouteTitle = ({ receiveAmt, toTokenInfo, isError }: RouteTitleProps) => { +export const RouteTitle = ({ + receiveAmt, + toTokenInfo, + isError, + hoverToShowTokenAddress = true, +}: RouteTitleProps) => { const theme = useTheme(); const { colorMode } = useColorMode(); const toChain = useAppSelector((state) => state.transfer.toChain); const tokenUrl = formatTokenUrl(toChain?.tokenUrlPattern, toTokenInfo?.address); + const isNative = isNativeToken(toTokenInfo?.address, toChain?.chainType); return ( {receiveAmt} - {toTokenInfo && ( + {toTokenInfo && hoverToShowTokenAddress && ( - - - {toTokenInfo.displaySymbol} - + )} + + {toTokenInfo && !hoverToShowTokenAddress && ( + + )} ); }; + +interface ToTokenInfoProps { + toTokenInfo: IBridgeTokenBaseInfo; + tokenUrl: string; + hoverToShowTokenAddress: boolean; + isNative: boolean; +} + +export const ToTokenInfo = React.forwardRef( + (props: ToTokenInfoProps, ref: React.LegacyRef) => { + const { + toTokenInfo, + tokenUrl, + hoverToShowTokenAddress = true, + isNative = false, + ...restProps + } = props; + const theme = useTheme(); + const { colorMode } = useColorMode(); + const { formatMessage } = useIntl(); + + return ( + + + {toTokenInfo.displaySymbol} + {!hoverToShowTokenAddress && !isNative && ( + + + ( + {formatAppAddress({ + address: toTokenInfo.address, + })} + ) + + +
+ +
+
+
+ )} +
+ ); + }, +); + +ToTokenInfo.displayName = 'ToTokenInfo';