diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 204dc54a..42554cce 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -18,7 +18,7 @@ const createStandardTokenContract = async () => { return erc20Token } -const createHumanFriendlyTokenContract = async () => { +export const createHumanFriendlyTokenContract = async () => { const web3 = getWeb3() const humanErc20Token = await contract(HumanFriendlyToken) humanErc20Token.setProvider(web3.currentProvider) diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx index 22322c1e..98b15c45 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/index.jsx @@ -20,6 +20,7 @@ import { setImageToPlaceholder } from '~/routes/safe/components/Balances/utils' import TokenPlaceholder from '~/routes/safe/components/Balances/assets/token_placeholder.svg' import { addressIsTokenContract, doesntExistInTokenList } from './validators' import { styles } from './style' +import { getSymbolAndDecimalsFromContract } from './utils' type Props = { classes: Object, @@ -59,12 +60,31 @@ const AddCustomToken = (props: Props) => { onClose() } - const populateFormValuesFromAddress = (tokenAddress) => {} + const populateFormValuesFromAddress = async (tokenAddress: string) => { + const tokenData = await getSymbolAndDecimalsFromContract(tokenAddress) - const formSpyOnChangeHandler = (state) => { - const { errors, validating, values } = state - if (!errors.address && !validating) { - populateFormValuesFromAddress(values.address) + if (tokenData.length) { + const [symbol, decimals] = tokenData + + setFormValues({ + address: tokenAddress, + symbol, + decimals, + name: symbol, + }) + } + } + + const formSpyOnChangeHandler = async (state) => { + const { + errors, validating, values, dirty, + } = state + if (dirty && !validating && errors.address) { + setFormValues(INITIAL_FORM_STATE) + } + + if (!errors.address && !validating && dirty) { + await populateFormValuesFromAddress(values.address) } } @@ -85,13 +105,23 @@ const AddCustomToken = (props: Props) => { name="address" component={TextField} type="text" - validate={composeValidators(required, mustBeEthereumAddress, doesntExistInTokenList(tokens), addressIsTokenContract)} + validate={composeValidators( + required, + mustBeEthereumAddress, + doesntExistInTokenList(tokens), + addressIsTokenContract, + )} placeholder="Token contract address*" text="Token contract address*" className={classes.addressInput} /> diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/utils.js b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/utils.js new file mode 100644 index 00000000..1bae742e --- /dev/null +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/utils.js @@ -0,0 +1,16 @@ +// @flow +import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens' + +export const getSymbolAndDecimalsFromContract = async (tokenAddress: string) => { + const tokenContract = await getHumanFriendlyToken() + const token = await tokenContract.at(tokenAddress) + let values + + try { + values = await Promise.all([token.symbol(), (await token.decimals()).toString()]) + } catch { + values = [] + } + + return values +} \ No newline at end of file diff --git a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/validators.js b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/validators.js index 21bde352..0872fd8f 100644 --- a/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/validators.js +++ b/src/routes/safe/components/Balances/Tokens/screens/AddCustomToken/validators.js @@ -3,6 +3,7 @@ import { List } from 'immutable' import { getWeb3 } from '~/logic/wallets/getWeb3' import { type Token } from '~/logic/tokens/store/model/token' import { sameAddress } from '~/logic/wallets/ethAddresses' +// import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' export const simpleMemoize = (fn: Function) => { let lastArg @@ -17,14 +18,23 @@ export const simpleMemoize = (fn: Function) => { } // eslint-disable-next-line -export const addressIsTokenContract = simpleMemoize(async (tokenAddress: string) => { +export const addressIsTokenContract = async (tokenAddress: string) => { + // SECOND APPROACH: + // They both seem to work the same + // const tokenContract = await getStandardTokenContract() + // try { + // await tokenContract.at(tokenAddress) + // } catch { + // return 'Not a token address' + // } + const web3 = getWeb3() const call = await web3.eth.call({ to: tokenAddress, data: web3.utils.sha3('totalSupply()') }) if (call === '0x') { return 'Not a token address' } -}) +} export const doesntExistInTokenList = (tokenList: List) => simpleMemoize((tokenAddress: string) => { const tokenIndex = tokenList.findIndex(({ address }) => sameAddress(address, tokenAddress))