utils#isAddress TypeScript Examples
The following examples show how to use
utils#isAddress.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
useGetProfileAvatar = (account: string) => {
const profileAvatar = useSelector((state: State) => state.profile.profileAvatars[account])
const { username, nft } = profileAvatar || {}
const dispatch = useAppDispatch()
useEffect(() => {
const address = isAddress(account)
if (!nft && address) {
dispatch(fetchProfileAvatar(account))
}
if (!username && nft && address) {
dispatch(fetchProfileUsername(account))
}
}, [account, nft, username, dispatch])
return { username, nft }
}
Example #2
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
/**
* Returns a map of the given addresses to their eventually consistent BNB balances.
*/
export function useBNBBalances(uncheckedAddresses?: (string | undefined)[]): {
[address: string]: CurrencyAmount | undefined
} {
const multicallContract = useMulticallContract()
const addresses: string[] = useMemo(
() =>
uncheckedAddresses
? uncheckedAddresses
.map(isAddress)
.filter((a): a is string => a !== false)
.sort()
: [],
[uncheckedAddresses],
)
const results = useSingleContractMultipleData(
multicallContract,
'getEthBalance',
addresses.map((address) => [address]),
)
return useMemo(
() =>
addresses.reduce<{ [address: string]: CurrencyAmount }>((memo, address, i) => {
const value = results?.[i]?.result?.[0]
if (value) memo[address] = CurrencyAmount.ether(JSBI.BigInt(value.toString()))
return memo
}, {}),
[addresses, results],
)
}
Example #3
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
function parseCurrencyFromURLParameter(urlParam: any): string {
if (typeof urlParam === 'string') {
const valid = isAddress(urlParam)
if (valid) return valid
if (urlParam.toUpperCase() === 'ELA') return 'ELA'
if (valid === false) return 'ELA'
}
return 'ELA' ?? ''
}
Example #4
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
/**
* Returns a map of token addresses to their eventually consistent token balances for a single account.
*/
export function useTokenBalancesWithLoadingIndicator(
address?: string,
tokens?: (Token | undefined)[],
): [{ [tokenAddress: string]: TokenAmount | undefined }, boolean] {
const validatedTokens: Token[] = useMemo(
() => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [],
[tokens],
)
const validatedTokenAddresses = useMemo(() => validatedTokens.map((vt) => vt.address), [validatedTokens])
const balances = useMultipleContractSingleData(validatedTokenAddresses, ERC20_INTERFACE, 'balanceOf', [address])
const anyLoading: boolean = useMemo(() => balances.some((callState) => callState.loading), [balances])
return [
useMemo(
() =>
address && validatedTokens.length > 0
? validatedTokens.reduce<{ [tokenAddress: string]: TokenAmount | undefined }>((memo, token, i) => {
const value = balances?.[i]?.result?.[0]
const amount = value ? JSBI.BigInt(value.toString()) : undefined
if (amount) {
memo[token.address] = new TokenAmount(token, amount)
}
return memo
}, {})
: {},
[address, validatedTokens, balances],
),
anyLoading,
]
}
Example #5
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
useTokenData = (address: string | undefined): TokenData | undefined => {
const allTokenData = useAllTokenData()
const addNewTokenKeys = useAddTokenKeys()
if (!address || !isAddress(address)) {
return undefined
}
// if token not tracked yet track it
if (!allTokenData[address]) {
addNewTokenKeys([address])
}
return allTokenData[address]?.data
}
Example #6
Source File: filtering.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
export function filterTokens(tokens: Token[], search: string): Token[] {
if (search.length === 0) return tokens
const searchingAddress = isAddress(search)
if (searchingAddress) {
return tokens.filter((token) => token.address === searchingAddress)
}
const lowerSearchParts = search
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (lowerSearchParts.length === 0) {
return tokens
}
const matchesSearch = (s: string): boolean => {
const sParts = s
.toLowerCase()
.split(/\s+/)
.filter((s_) => s_.length > 0)
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
}
return tokens.filter((token) => {
const { symbol, name } = token
return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name))
})
}
Example #7
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 6 votes |
function parseCurrencyFromURLParameter(urlParam: any): string {
if (typeof urlParam === 'string') {
const valid = isAddress(urlParam)
if (valid) return valid
if (urlParam.toUpperCase() === 'ELA') return 'ELA'
if (valid === false) return 'ELA'
}
return 'ELA' ?? ''
}
Example #8
Source File: index.tsx From glide-frontend with GNU General Public License v3.0 | 6 votes |
CurrencyLogo: React.FC<{
address?: string
size?: string
}> = ({ address, size = '24px', ...rest }) => {
const src = useMemo(() => {
const checksummedAddress = isAddress(address)
if (checksummedAddress) {
// return `https://assets.trustwalletapp.com/blockchains/smartchain/assets/${checksummedAddress}/logo.png`
return `${BASE_URL}/images/tokens/${checksummedAddress}.png`
}
return null
}, [address])
return <StyledLogo size={size} src={src} alt="token logo" {...rest} />
}
Example #9
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
useGetOrFetchLeaderboardAddressResult = (account: string) => {
const addressResult = useGetAddressResult(account)
const dispatch = useAppDispatch()
useEffect(() => {
const address = isAddress(account)
// If address result is null it means we already tried fetching the results and none came back
if (!addressResult && addressResult !== null && address) {
dispatch(fetchAddressResult(account))
}
}, [dispatch, account, addressResult])
return addressResult
}
Example #10
Source File: filtering.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
export function filterTokens(tokens: Token[], search: string): Token[] {
if (search.length === 0) return tokens;
const searchingAddress = isAddress(search);
if (searchingAddress) {
return tokens.filter((token) => token.address === searchingAddress);
}
const lowerSearchParts = search
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0);
if (lowerSearchParts.length === 0) {
return tokens;
}
const matchesSearch = (s: string): boolean => {
const sParts = s
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0);
return lowerSearchParts.every(
(p) =>
p.length === 0 ||
sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)),
);
};
return tokens.filter((token) => {
const { symbol, name } = token;
return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name));
});
}
Example #11
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
function parseCurrencyFromURLParameter(urlParam: any): string {
if (typeof urlParam === 'string') {
const valid = isAddress(urlParam)
if (valid) return valid
if (urlParam.toUpperCase() === 'CRO') return 'CRO'
if (valid === false) return 'CRO'
}
return 'CRO' ?? ''
}
Example #12
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
function parseCurrencyFromURLParameter(urlParam: any): string {
if (typeof urlParam === 'string') {
const valid = isAddress(urlParam);
if (valid) return valid;
if (urlParam.toUpperCase() === 'ETH') return 'ETH';
if (valid === false) return 'ETH';
}
return 'ETH' ?? '';
}
Example #13
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
/**
* Returns a map of the given addresses to their eventually consistent CRO balances.
*/
export function useCROBalances(uncheckedAddresses?: (string | undefined)[]): {
[address: string]: CurrencyAmount | undefined
} {
const multicallContract = useMulticallContract()
const addresses: string[] = useMemo(
() =>
uncheckedAddresses
? uncheckedAddresses
.map(isAddress)
.filter((a): a is string => a !== false)
.sort()
: [],
[uncheckedAddresses],
)
const results = useSingleContractMultipleData(
multicallContract,
'getEthBalance',
addresses.map((address) => [address]),
)
return useMemo(
() =>
addresses.reduce<{ [address: string]: CurrencyAmount }>((memo, address, i) => {
const value = results?.[i]?.result?.[0]
if (value) memo[address] = CurrencyAmount.ether(JSBI.BigInt(value.toString()))
return memo
}, {}),
[addresses, results],
)
}
Example #14
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 6 votes |
/**
* Returns a map of token addresses to their eventually consistent token balances for a single account.
*/
export function useTokenBalancesWithLoadingIndicator(
address?: string,
tokens?: (Token | undefined)[],
): [{ [tokenAddress: string]: TokenAmount | undefined }, boolean] {
const validatedTokens: Token[] = useMemo(
() => tokens?.filter((t?: Token): t is Token => isAddress(t?.address) !== false) ?? [],
[tokens],
)
const validatedTokenAddresses = useMemo(() => validatedTokens.map((vt) => vt.address), [validatedTokens])
const balances = useMultipleContractSingleData(validatedTokenAddresses, ERC20_INTERFACE, 'balanceOf', [address])
const anyLoading: boolean = useMemo(() => balances.some((callState) => callState.loading), [balances])
return [
useMemo(
() =>
address && validatedTokens.length > 0
? validatedTokens.reduce<{ [tokenAddress: string]: TokenAmount | undefined }>((memo, token, i) => {
const value = balances?.[i]?.result?.[0]
const amount = value ? JSBI.BigInt(value.toString()) : undefined
if (amount) {
memo[token.address] = new TokenAmount(token, amount)
}
return memo
}, {})
: {},
[address, validatedTokens, balances],
),
anyLoading,
]
}
Example #15
Source File: useENSName.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
/**
* Does a reverse lookup for an address to find its ENS name.
* Note this is not the same as looking up an ENS name to find an address.
*/
export default function useENSName(
address?: string,
): { ENSName: string | null; loading: boolean } {
const debouncedAddress = useDebounce(address, 200);
const ensNodeArgument = useMemo(() => {
if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined];
try {
return debouncedAddress
? [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)]
: [undefined];
} catch (error) {
return [undefined];
}
}, [debouncedAddress]);
const registrarContract = useENSRegistrarContract(false);
const resolverAddress = useSingleCallResult(
registrarContract,
'resolver',
ensNodeArgument,
);
const resolverAddressResult = resolverAddress.result?.[0];
const resolverContract = useENSResolverContract(
resolverAddressResult && !isZero(resolverAddressResult)
? resolverAddressResult
: undefined,
false,
);
const name = useSingleCallResult(resolverContract, 'name', ensNodeArgument);
const changed = debouncedAddress !== address;
return {
ENSName: changed ? null : name.result?.[0] ?? null,
loading: changed || resolverAddress.loading || name.loading,
};
}
Example #16
Source File: useENS.ts From interface-v2 with GNU General Public License v3.0 | 6 votes |
/**
* Given a name or address, does a lookup to resolve to an address and name
* @param nameOrAddress ENS name or address
*/
export default function useENS(
nameOrAddress?: string | null,
): { loading: boolean; address: string | null; name: string | null } {
const validated = isAddress(nameOrAddress);
const reverseLookup = useENSName(validated ? validated : undefined);
const lookup = useENSAddress(nameOrAddress);
return {
loading: reverseLookup.loading || lookup.loading,
address: validated ? validated : lookup.address,
name: reverseLookup.ENSName
? reverseLookup.ENSName
: !validated && lookup.address
? nameOrAddress || null
: null,
};
}
Example #17
Source File: index.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
CurrencyLogo: React.FC<{
address?: string
size?: string
}> = ({ address, size = '24px', ...rest }) => {
const src = useMemo(() => {
const checkSummedAddress = isAddress(address)
if (checkSummedAddress) {
return `${process.env.REACT_APP_BASE_URL}/images/tokens/${checkSummedAddress}.svg` // XXX: update URL for token logo
}
return null
}, [address])
return <StyledLogo size={size} src={src} alt="token logo" {...rest} />
}
Example #18
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 5 votes |
function validatedRecipient(recipient: any): string | null {
if (typeof recipient !== 'string') return null
const address = isAddress(recipient)
if (address) return address
if (ENS_NAME_REGEX.test(recipient)) return recipient
if (ADDRESS_REGEX.test(recipient)) return recipient
return null
}
Example #19
Source File: hooks.ts From vvs-ui with GNU General Public License v3.0 | 5 votes |
function validatedRecipient(recipient: any): string | null {
if (typeof recipient !== 'string') return null
const address = isAddress(recipient)
if (address) return address
if (ENS_NAME_REGEX.test(recipient)) return recipient
if (ADDRESS_REGEX.test(recipient)) return recipient
return null
}
Example #20
Source File: index.test.ts From vvs-ui with GNU General Public License v3.0 | 5 votes |
describe('utils', () => {
describe('#getBscScanLink', () => {
it('correct for tx', () => {
expect(getExplorerLink('abc', 'transaction', ChainId.MAINNET)).toEqual('https://bscscan.com/tx/abc')
})
it('correct for token', () => {
expect(getExplorerLink('abc', 'token', ChainId.MAINNET)).toEqual('https://bscscan.com/token/abc')
})
it('correct for address', () => {
expect(getExplorerLink('abc', 'address', ChainId.MAINNET)).toEqual('https://bscscan.com/address/abc')
})
it('enum', () => {
expect(getExplorerLink('abc', 'address', ChainId.TESTNET)).toEqual('https://testnet.bscscan.com/address/abc')
})
})
describe('#calculateSlippageAmount', () => {
it('bounds are correct', () => {
const tokenAmount = new TokenAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100')
expect(() => calculateSlippageAmount(tokenAmount, -1)).toThrow()
expect(calculateSlippageAmount(tokenAmount, 0).map((bound) => bound.toString())).toEqual(['100', '100'])
expect(calculateSlippageAmount(tokenAmount, 100).map((bound) => bound.toString())).toEqual(['99', '101'])
expect(calculateSlippageAmount(tokenAmount, 200).map((bound) => bound.toString())).toEqual(['98', '102'])
expect(calculateSlippageAmount(tokenAmount, 10000).map((bound) => bound.toString())).toEqual(['0', '200'])
expect(() => calculateSlippageAmount(tokenAmount, 10001)).toThrow()
})
})
describe('#isAddress', () => {
it('returns false if not', () => {
expect(isAddress('')).toBe(false)
expect(isAddress('0x0000')).toBe(false)
expect(isAddress(1)).toBe(false)
expect(isAddress({})).toBe(false)
expect(isAddress(undefined)).toBe(false)
})
it('returns the checksummed address', () => {
expect(isAddress('0xf164fc0ec4e93095b804a4795bbe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
expect(isAddress('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
})
it('succeeds even without prefix', () => {
expect(isAddress('f164fc0ec4e93095b804a4795bbe1e041497b92a')).toBe('0xf164fC0Ec4E93095b804a4795bBe1e041497b92a')
})
it('fails if too long', () => {
expect(isAddress('f164fc0ec4e93095b804a4795bbe1e041497b92a0')).toBe(false)
})
})
describe('#calculateGasMargin', () => {
it('adds 10%', () => {
expect(calculateGasMargin(BigNumber.from(1000)).toString()).toEqual('1100')
expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('55')
})
})
describe('#basisPointsToPercent', () => {
it('converts basis points numbers to percents', () => {
expect(basisPointsToPercent(100).equalTo(new Percent(JSBI.BigInt(1), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(500).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(50).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(1000)))).toBeTruthy()
})
})
})
Example #21
Source File: AddressSearch.tsx From vvs-ui with GNU General Public License v3.0 | 5 votes |
AddressSearch = () => {
const [state, setState] = useState(initialState)
const addressResult = useGetAddressResult(state.value)
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { isFetching, resultFound, value } = state
const [onPresentWalletStatsModal] = useModal(
<WalletStatsModal account={state.value} onBeforeDismiss={() => setState(initialState)} />,
)
const handleChange = (evt: ChangeEvent<HTMLInputElement>) => {
const { value: newValue } = evt.target
setState((prevState) => ({
...prevState,
value: newValue,
}))
}
const handleClick = () => {
setState(initialState)
onPresentWalletStatsModal()
}
// When we have a valid address fetch the data
useEffect(() => {
const isValidAddress = isAddress(value) !== false
const getAddressResult = async () => {
try {
setState((prevState) => ({ ...prevState, isFetching: true }))
await dispatch(fetchAddressResult(value))
} finally {
setState((prevState) => ({ ...prevState, isFetching: false }))
}
}
if (isValidAddress) {
getAddressResult()
} else {
setState((prevState) => ({ ...prevState, resultFound: ResultStatus.NOT_VALID }))
}
}, [value, dispatch, setState])
useEffect(() => {
// Undefined means we have not checked yet
if (addressResult !== undefined) {
setState((prevState) => ({
...prevState,
resultFound: addressResult === null ? ResultStatus.NOT_FOUND : ResultStatus.FOUND,
}))
}
}, [addressResult, setState])
return (
<Box position="relative">
<Input
placeholder={t('Search %subject%', { subject: t('Address').toLowerCase() })}
value={state.value}
onChange={handleChange}
style={{ position: 'relative', zIndex: 16, paddingRight: '40px' }}
/>
{isFetching && (
<Box position="absolute" top="12px" right="16px" style={{ zIndex: 17 }}>
<CircleLoader />
</Box>
)}
<SubMenu isOpen={resultFound !== ResultStatus.NOT_VALID}>
{resultFound === ResultStatus.FOUND ? (
<AddressLink onClick={handleClick}>{state.value}</AddressLink>
) : (
<Text px="16px" fontWeight="bold">
{t('No results found.')}
</Text>
)}
</SubMenu>
</Box>
)
}
Example #22
Source File: hooks.ts From glide-frontend with GNU General Public License v3.0 | 5 votes |
function validatedRecipient(recipient: any): string | null {
if (typeof recipient !== 'string') return null
const address = isAddress(recipient)
if (address) return address
if (ENS_NAME_REGEX.test(recipient)) return recipient
if (ADDRESS_REGEX.test(recipient)) return recipient
return null
}
Example #23
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 5 votes |
function validatedRecipient(recipient: any): string | null {
if (typeof recipient !== 'string') return null;
const address = isAddress(recipient);
if (address) return address;
if (ENS_NAME_REGEX.test(recipient)) return recipient;
if (ADDRESS_REGEX.test(recipient)) return recipient;
return null;
}
Example #24
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 5 votes |
/**
* Returns a map of the given addresses to their eventually consistent ETH balances.
*/
export function useETHBalances(
uncheckedAddresses?: (string | undefined)[],
): {
[address: string]: CurrencyAmount | undefined;
} {
const multicallContract = useMulticallContract();
const addresses: string[] = useMemo(
() =>
uncheckedAddresses
? uncheckedAddresses
.map(isAddress)
.filter((a): a is string => a !== false)
.sort()
: [],
[uncheckedAddresses],
);
const results = useSingleContractMultipleData(
multicallContract,
'getEthBalance',
addresses.map((address) => [address]),
);
return useMemo(
() =>
addresses.reduce<{ [address: string]: CurrencyAmount }>(
(memo, address, i) => {
const value = results?.[i]?.result?.[0];
if (value)
memo[address] = CurrencyAmount.ether(JSBI.BigInt(value.toString()));
return memo;
},
{},
),
[addresses, results],
);
}
Example #25
Source File: hooks.ts From interface-v2 with GNU General Public License v3.0 | 5 votes |
/**
* Returns a map of token addresses to their eventually consistent token balances for a single account.
*/
export function useTokenBalancesWithLoadingIndicator(
address?: string,
tokens?: (Token | undefined)[],
): [{ [tokenAddress: string]: TokenAmount | undefined }, boolean] {
const validatedTokens: Token[] = useMemo(
() =>
tokens?.filter(
(t?: Token): t is Token => isAddress(t?.address) !== false,
) ?? [],
[tokens],
);
const validatedTokenAddresses = useMemo(
() => validatedTokens.map((vt) => vt.address),
[validatedTokens],
);
const balances = useMultipleContractSingleData(
validatedTokenAddresses,
ERC20_INTERFACE,
'balanceOf',
[address],
);
const anyLoading: boolean = useMemo(
() => balances.some((callState) => callState.loading),
[balances],
);
return [
useMemo(
() =>
address && validatedTokens.length > 0
? validatedTokens.reduce<{
[tokenAddress: string]: TokenAmount | undefined;
}>((memo, token, i) => {
const value = balances?.[i]?.result?.[0];
const amount = value ? JSBI.BigInt(value.toString()) : undefined;
if (amount) {
memo[token.address] = new TokenAmount(token, amount);
}
return memo;
}, {})
: {},
[address, validatedTokens, balances],
),
anyLoading,
];
}
Example #26
Source File: BlockchainLink.tsx From dxvote with GNU Affero General Public License v3.0 | 5 votes |
BlockchainLink = ({
text,
size = 'default',
type = 'default',
toCopy = false,
onlyIcon = false,
onlyText = false,
}) => {
const {
context: { configStore, ensService },
} = useContext();
const rpcUrls = useRpcUrls();
const networkName = configStore.getActiveChainName();
const [ensName, setENSName] = useState('');
const erc20Token = getERC20Token(text);
const dxVoteContract = getDxVoteContract(text);
useEffect(() => {
async function getENS() {
const response = await ensService.resolveENSName(text);
setENSName(response);
}
getENS();
}, [text, rpcUrls]);
let formatedAddress;
if (!ensName && !dxVoteContract && !erc20Token) {
if (onlyIcon) formatedAddress = <FiExternalLink />;
else formatedAddress = toAddressStub(text, size);
}
/*
If the address is an ens domain show the ens domain name with a link to the blockchain explorer address and option to copy the address.
If the address is an ERC20 token registered in the config show the token symbol instead with links to the token explorer, and the option to copy the token address.
If the address is an known dxvote contract (avatar,controller, etc) domain show the contract name with a link to the blockchain explorer address and option to copy the address.
else show formatted address
*/
const Address = () => (
<>
{ensName}
{!ensName && erc20Token && <Icon src={erc20Token.logoURI} />}
{!ensName && dxVoteContract && dxVoteContract?.contract}
{formatedAddress}
</>
);
return (
<AddressLink>
{!onlyText ? (
<a
href={getBlockchainLink(
text,
networkName,
isAddress(text) ? 'address' : type
)}
target="_blank"
rel="noreferrer"
>
<Address />
</a>
) : (
<div>
<Address />
</div>
)}
{toCopy ? <Copy toCopy={text} /> : null}
</AddressLink>
);
}
Example #27
Source File: ManageTokens.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
export default function ManageTokens({
setModalView,
setImportToken,
}: {
setModalView: (view: CurrencyModalView) => void
setImportToken: (token: Token) => void
}) {
const { chainId } = useActiveWeb3React()
const { t } = useTranslation()
const [searchQuery, setSearchQuery] = useState<string>('')
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>()
const handleInput = useCallback((event) => {
const input = event.target.value
const checksummedInput = isAddress(input)
setSearchQuery(checksummedInput || input)
}, [])
// if they input an address, use it
const searchToken = useToken(searchQuery)
// all tokens for local list
const userAddedTokens: Token[] = useUserAddedTokens()
const removeToken = useRemoveUserAddedToken()
const handleRemoveAll = useCallback(() => {
if (chainId && userAddedTokens) {
userAddedTokens.map((token) => {
return removeToken(chainId, token.address)
})
}
}, [removeToken, userAddedTokens, chainId])
const tokenList = useMemo(() => {
return (
chainId &&
userAddedTokens.map((token) => (
<RowBetween key={token.address} width="100%">
<RowFixed>
<CurrencyLogo currency={token} size="20px" />
<Link external href={getExplorerLink(token.address, 'address', chainId)} color="textSubtle" ml="10px">
{token.symbol}
</Link>
</RowFixed>
<RowFixed>
<IconButton variant="text" onClick={() => removeToken(chainId, token.address)}>
<CloseIcon />
</IconButton>
<LinkExternal href={getExplorerLink(token.address, 'address', chainId)} />
</RowFixed>
</RowBetween>
))
)
}, [userAddedTokens, chainId, removeToken])
const isAddressValid = searchQuery === '' || isAddress(searchQuery)
return (
<Wrapper>
<Column style={{ width: '100%', flex: '1 1' }}>
<AutoColumn gap="14px">
<Row>
<Input
id="token-search-input"
scale="lg"
placeholder="0x0000"
value={searchQuery}
autoComplete="off"
ref={inputRef as RefObject<HTMLInputElement>}
onChange={handleInput}
isWarning={!isAddressValid}
/>
</Row>
{!isAddressValid && <Text color="failure">{t('Enter valid token address')}</Text>}
{searchToken && (
<ImportRow
token={searchToken}
showImportView={() => setModalView(CurrencyModalView.importToken)}
setImportToken={setImportToken}
style={{ height: 'fit-content' }}
/>
)}
</AutoColumn>
{tokenList}
<Footer>
<Text bold color="textSubtle">
{userAddedTokens?.length} {userAddedTokens.length === 1 ? t('Custom Token') : t('Custom Tokens')}
</Text>
{userAddedTokens.length > 0 && (
<Button variant="tertiary" onClick={handleRemoveAll}>
{t('Clear all')}
</Button>
)}
</Footer>
</Column>
</Wrapper>
)
}
Example #28
Source File: CurrencySearch.tsx From interface-v2 with GNU General Public License v3.0 | 4 votes |
CurrencySearch: React.FC<CurrencySearchProps> = ({
selectedCurrency,
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
onDismiss,
isOpen,
}) => {
const classes = useStyles();
const { t } = useTranslation();
const { account, chainId } = useActiveWeb3React();
const dispatch = useDispatch<AppDispatch>();
const fixedList = useRef<FixedSizeList>();
const handleInput = useCallback((input: string) => {
const checksummedInput = isAddress(input);
setSearchQuery(checksummedInput || input);
fixedList.current?.scrollTo(0);
}, []);
const [searchQuery, setSearchQuery] = useState<string>('');
const [searchQueryInput, setSearchQueryInput] = useDebouncedChangeHandler(
searchQuery,
handleInput,
);
const allTokens = useAllTokens();
// if they input an address, use it
const isAddressSearch = isAddress(searchQuery);
const searchToken = useToken(searchQuery);
useEffect(() => {
if (isAddressSearch) {
ReactGA.event({
category: 'Currency Select',
action: 'Search by address',
label: isAddressSearch,
});
}
}, [isAddressSearch]);
const showETH: boolean = useMemo(() => {
const s = searchQuery.toLowerCase().trim();
return s === '' || s === 'e' || s === 'et' || s === 'eth';
}, [searchQuery]);
const tokenComparator = useTokenComparator(false);
const filteredTokens: Token[] = useMemo(() => {
if (isAddressSearch) return searchToken ? [searchToken] : [];
return filterTokens(Object.values(allTokens), searchQuery);
}, [isAddressSearch, searchToken, allTokens, searchQuery]);
const filteredSortedTokens: Token[] = useMemo(() => {
if (searchToken) return [searchToken];
const sorted = filteredTokens.sort(tokenComparator);
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0);
if (symbolMatch.length > 1) return sorted;
return [
...(searchToken ? [searchToken] : []),
// sort any exact symbol matches first
...sorted.filter(
(token) => token.symbol?.toLowerCase() === symbolMatch[0],
),
...sorted.filter(
(token) => token.symbol?.toLowerCase() !== symbolMatch[0],
),
];
}, [filteredTokens, searchQuery, searchToken, tokenComparator]);
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency);
onDismiss();
},
[onDismiss, onCurrencySelect],
);
// clear the input on open
useEffect(() => {
if (isOpen) setSearchQuery('');
}, [isOpen]);
const handleEnter = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = searchQuery.toLowerCase().trim();
if (s === 'eth') {
handleCurrencySelect(ETHER);
} else if (filteredSortedTokens.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() ===
searchQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0]);
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, searchQuery],
);
// manage focus on modal show
const inputRef = useRef<HTMLInputElement>();
let selectedListInfo = useSelectedListInfo();
if (selectedListInfo.current === null) {
dispatch(selectList(GlobalConst.utils.DEFAULT_TOKEN_LIST_URL));
}
selectedListInfo = useSelectedListInfo();
return (
<Box className={classes.wrapper}>
<Box className={classes.header}>
<Typography variant='subtitle2'>Select a token</Typography>
<CloseIcon onClick={onDismiss} />
</Box>
<Box className={classes.searchInputWrapper}>
<SearchIcon />
<input
type='text'
placeholder={t('tokenSearchPlaceholder')}
value={searchQueryInput}
ref={inputRef as RefObject<HTMLInputElement>}
onChange={(e) => setSearchQueryInput(e.target.value)}
onKeyDown={handleEnter}
/>
</Box>
{showCommonBases && (
<CommonBases
chainId={chainId}
onSelect={handleCurrencySelect}
selectedCurrency={selectedCurrency}
/>
)}
<Divider />
<Box flex={1}>
<AutoSizer disableWidth>
{({ height }) => (
<CurrencyList
showETH={showETH}
height={height}
currencies={filteredSortedTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
/>
)}
</AutoSizer>
</Box>
<Box className={classes.footer} />
</Box>
);
}
Example #29
Source File: Tokens.ts From interface-v2 with GNU General Public License v3.0 | 4 votes |
// undefined if invalid or does not exist
// null if loading
// otherwise returns the token
export function useToken(tokenAddress?: string): Token | undefined | null {
const { chainId } = useActiveWeb3React();
const tokens = useAllTokens();
const address = isAddress(tokenAddress);
const tokenContract = useTokenContract(address ? address : undefined, false);
const tokenContractBytes32 = useBytes32TokenContract(
address ? address : undefined,
false,
);
const token: Token | undefined = address ? tokens[address] : undefined;
const tokenName = useSingleCallResult(
token ? undefined : tokenContract,
'name',
undefined,
NEVER_RELOAD,
);
const tokenNameBytes32 = useSingleCallResult(
token ? undefined : tokenContractBytes32,
'name',
undefined,
NEVER_RELOAD,
);
const symbol = useSingleCallResult(
token ? undefined : tokenContract,
'symbol',
undefined,
NEVER_RELOAD,
);
const symbolBytes32 = useSingleCallResult(
token ? undefined : tokenContractBytes32,
'symbol',
undefined,
NEVER_RELOAD,
);
const decimals = useSingleCallResult(
token ? undefined : tokenContract,
'decimals',
undefined,
NEVER_RELOAD,
);
return useMemo(() => {
if (token) return token;
if (!chainId || !address) return undefined;
if (decimals.loading || symbol.loading || tokenName.loading) return null;
if (decimals.result) {
return new Token(
chainId,
address,
decimals.result[0],
parseStringOrBytes32(
symbol.result?.[0],
symbolBytes32.result?.[0],
'UNKNOWN',
),
parseStringOrBytes32(
tokenName.result?.[0],
tokenNameBytes32.result?.[0],
'Unknown Token',
),
);
}
return undefined;
}, [
address,
chainId,
decimals.loading,
decimals.result,
symbol.loading,
symbol.result,
symbolBytes32.result,
token,
tokenName.loading,
tokenName.result,
tokenNameBytes32.result,
]);
}