-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TokenBalance Component #97
Changes from 22 commits
9712a2e
7c843ab
f29734d
065c576
672bba0
2420626
c650fb7
911f8d6
2ed6ea1
69ec3b7
c2d16df
ff091bd
d527562
8161bd0
7c88ae1
89e25f5
6df8770
965f3f7
e912a93
9c521d5
12b1ea2
a3d9073
5b2dc8f
4f8d41a
c36708c
34c4e46
9b397f7
8ef2478
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,9 @@ | ||
{ | ||
"$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", | ||
"changelog": [ | ||
"@changesets/changelog-github", | ||
{ "repo": "Developer-DAO/web3-ui" } | ||
], | ||
"changelog": ["@changesets/changelog-github", { "repo": "Developer-DAO/web3-ui" }], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should not be changed. Can you make sure this change goes away please? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sir, I almost lost my mind on this but I got the feeling this file was formatted by the commit hook. I have pushed it multiple times just to notice that this file still has unwanted changes. |
||
"commit": false, | ||
"linked": [], | ||
"access": "public", | ||
"baseBranch": "main", | ||
"updateInternalDependencies": "patch" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@web3-ui/components': minor | ||
'@web3-ui/hooks': minor | ||
--- | ||
|
||
Added token-balance component to display the users amount of a certain ERC20 token |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ | |
"module": "dist/web3-ui-components.esm.js", | ||
"types": "dist/web3-ui-components.cjs.d.ts", | ||
"dependencies": { | ||
"@web3-ui/hooks": "0.4.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One more thing that came to my mind recently is that the This is why I feel like we shouldn't do any data fetching at all inside any of our
Let me know if this is unclear. More than happy to discuss this in further detail since I think this is an important topic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean this component shouldn't have any state at all and just renders given props ? Then we can remove the useTokenBalance hook from the Component. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AlexNi245 yes! The current verison of this component which does have some state and fetches data should be in the tldr:
|
||
"@babel/runtime": "^7.16.3", | ||
"@chakra-ui/react": "^1.7.2", | ||
"@emotion/core": "^11.0.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { Provider, Web3Context } from '@web3-ui/hooks'; | ||
import React, { useContext } from 'react'; | ||
import { TokenBalance, TokenBalanceProps } from './TokenBalance'; | ||
import { Button } from '@chakra-ui/react'; | ||
|
||
export default { | ||
title: 'Components/TokenBalance', | ||
component: TokenBalance, | ||
}; | ||
|
||
const exampleProps: TokenBalanceProps = { | ||
value: 0.9955, | ||
accountAddress: '0x503828976D22510aad0201ac7EC88293211D23Da', | ||
tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', | ||
}; | ||
|
||
export const TokeBalance = () => ( | ||
<Provider network='mainnet'> | ||
<WalletContextTestWrapper child={<TokenBalance {...exampleProps} />} /> | ||
</Provider> | ||
); | ||
|
||
export const InvalidContract = () => ( | ||
<Provider network='mainnet'> | ||
<WalletContextTestWrapper child={<TokenBalance {...exampleProps} tokenAddress={'0x0'} />} /> | ||
</Provider> | ||
); | ||
|
||
const WalletContextTestWrapper = ({ child }): JSX.Element => { | ||
const { connected, connectWallet } = useContext(Web3Context); | ||
return !connected ? <Button onClick={connectWallet}>Connect with Wallet</Button> : child; | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,93 @@ | ||||||||||||||||||||||||||
import React, { useContext, useEffect, useState } from 'react'; | ||||||||||||||||||||||||||
import { Box, Flex, FlexProps, Heading, Image } from '@chakra-ui/react'; | ||||||||||||||||||||||||||
import { ERC20ABI, useTokenBalance, Web3Context } from '@web3-ui/hooks'; | ||||||||||||||||||||||||||
import { ethers } from 'ethers'; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export interface TokenBalanceProps { | ||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
* The contract address of the ERC20 Token | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
tokenAddress: string; | ||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
* The owners address | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
accountAddress: string; | ||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
* The value of one token in USD | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
value: number; | ||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||
* Image of the token (optional) | ||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||
imgUrl?: string | undefined; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export const TokenBalance: React.FC<TokenBalanceProps & FlexProps> = props => { | ||||||||||||||||||||||||||
const { tokenAddress, accountAddress, value, imgUrl } = props; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const web3Context = useContext(Web3Context); | ||||||||||||||||||||||||||
const provider = web3Context?.provider; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const [name, setName] = useState(''); | ||||||||||||||||||||||||||
const [symbol, setSymbol] = useState(''); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const { balance, decimals } = useTokenBalance({ tokenAddress, accountAddress }); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||
getTokenNameAndSymbol(); | ||||||||||||||||||||||||||
}, []); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
//Just display the first 3 decimal places of the balance | ||||||||||||||||||||||||||
const calcBalance = () => { | ||||||||||||||||||||||||||
if (balance === undefined || decimals === undefined) { | ||||||||||||||||||||||||||
return 0; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
return Number.parseFloat((Number.parseInt(balance) / 10 ** decimals).toFixed(3)); | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
//Just display the first 3 decimal places of the value | ||||||||||||||||||||||||||
const calcValue = () => { | ||||||||||||||||||||||||||
const balance = calcBalance(); | ||||||||||||||||||||||||||
return (balance * value).toFixed(3); | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
//Fetch name and symbol from the smart contract | ||||||||||||||||||||||||||
//Maybe it would make sense to provide them as props to avoid loading time ? | ||||||||||||||||||||||||||
const getTokenNameAndSymbol = async () => { | ||||||||||||||||||||||||||
const contract = new ethers.Contract(tokenAddress, ERC20ABI, provider!); | ||||||||||||||||||||||||||
const [name, symbol] = await Promise.all([contract.name(), contract.symbol()]); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
setName(name); | ||||||||||||||||||||||||||
setSymbol(symbol); | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const Headline = (name: string) => ( | ||||||||||||||||||||||||||
<Heading as='h3' size='sm'> | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inline components can't maintain their referential identity and are subject to constant remounting. Hoisting outside of this closure will resolve that |
||||||||||||||||||||||||||
{name} | ||||||||||||||||||||||||||
</Heading> | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like Jovi suggested:
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const TokenLogo = ({ tokenContractAddress }) => ( | ||||||||||||||||||||||||||
<Image | ||||||||||||||||||||||||||
src={`https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${tokenContractAddress}/logo.png`} | ||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||
<Flex borderRadius='lg' borderWidth='1px' overflow='hidden' px='4' py='2' {...props}> | ||||||||||||||||||||||||||
<Box w='50px' pr='4'> | ||||||||||||||||||||||||||
{imgUrl ? <Image src={imgUrl} /> : <TokenLogo tokenContractAddress={tokenAddress} />} | ||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||
<Box flex='2'> | ||||||||||||||||||||||||||
{Headline(symbol)} | ||||||||||||||||||||||||||
<p>{name}</p> | ||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||
<Box flex='1'> | ||||||||||||||||||||||||||
{Headline('Balance')} | ||||||||||||||||||||||||||
<p>{calcBalance()}</p> | ||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||
<Box flex='1'> | ||||||||||||||||||||||||||
{Headline('Value')} | ||||||||||||||||||||||||||
<p>{calcValue()}</p> | ||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||
</Flex> | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
[ | ||
{ | ||
"constant": true, | ||
"inputs": [], | ||
"name": "name", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "string" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you rename this file to |
||
}, | ||
{ | ||
"constant": false, | ||
"inputs": [ | ||
{ | ||
"name": "_spender", | ||
"type": "address" | ||
}, | ||
{ | ||
"name": "_value", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": "approve", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "bool" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": true, | ||
"inputs": [], | ||
"name": "totalSupply", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": false, | ||
"inputs": [ | ||
{ | ||
"name": "_from", | ||
"type": "address" | ||
}, | ||
{ | ||
"name": "_to", | ||
"type": "address" | ||
}, | ||
{ | ||
"name": "_value", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": "transferFrom", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "bool" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": true, | ||
"inputs": [], | ||
"name": "decimals", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "uint8" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": true, | ||
"inputs": [ | ||
{ | ||
"name": "_owner", | ||
"type": "address" | ||
} | ||
], | ||
"name": "balanceOf", | ||
"outputs": [ | ||
{ | ||
"name": "balance", | ||
"type": "uint256" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": true, | ||
"inputs": [], | ||
"name": "symbol", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "string" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": false, | ||
"inputs": [ | ||
{ | ||
"name": "_to", | ||
"type": "address" | ||
}, | ||
{ | ||
"name": "_value", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": "transfer", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "bool" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"constant": true, | ||
"inputs": [ | ||
{ | ||
"name": "_owner", | ||
"type": "address" | ||
}, | ||
{ | ||
"name": "_spender", | ||
"type": "address" | ||
} | ||
], | ||
"name": "allowance", | ||
"outputs": [ | ||
{ | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"payable": false, | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"payable": true, | ||
"stateMutability": "payable", | ||
"type": "fallback" | ||
}, | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": true, | ||
"name": "owner", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": true, | ||
"name": "spender", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": false, | ||
"name": "value", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": "Approval", | ||
"type": "event" | ||
}, | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": true, | ||
"name": "from", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": true, | ||
"name": "to", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": false, | ||
"name": "value", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": "Transfer", | ||
"type": "event" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './TokenBalance'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
export { useWallet, useContract } from './hooks'; | ||
export { useTokenBalance } from './hooks/useTokenBalance'; | ||
export { Provider, Web3Context } from './Provider'; | ||
export type { ProviderProps, Web3ContextType } from './Provider'; | ||
export { NETWORKS, CHAIN_ID_TO_NETWORK } from './constants'; | ||
export {useWallet, useContract} from './hooks'; | ||
export {useTokenBalance} from './hooks/useTokenBalance'; | ||
export {Provider, Web3Context} from './Provider'; | ||
export type {ProviderProps, Web3ContextType} from './Provider'; | ||
export {NETWORKS, CHAIN_ID_TO_NETWORK, ERC20ABI} from './constants'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of these lines should not be changed. Only the last line is actually being changed. Can you reset these? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This must be also the result of the post commit hook. I reverted the first few lines just to notice that they have changed again after I committed my changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. No worries then. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you removing this, this is repo config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this was not on purpose. Must have occurred during the upstream merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll revert this