diff --git a/packages/core/src/abi/ERC20.json b/packages/core/src/abi/ERC20.json index 43bd340..58f67d9 100644 --- a/packages/core/src/abi/ERC20.json +++ b/packages/core/src/abi/ERC20.json @@ -1,230 +1,222 @@ -{ - "contractName": "ERC20", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "from", - "type": "address" - }, - { - "indexed": true, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], - "name": "Approval", - "type": "event" - }, - { + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ - { - "name": "", - "type": "uint256" - } + { + "name": "", + "type": "uint256" + } ], "payable": false, "stateMutability": "view", "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "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" - }, - { + }, + { "constant": false, "inputs": [ - { - "name": "to", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "spender", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "from", - "type": "address" - }, - { - "name": "to", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - } + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], "name": "transferFrom", "outputs": [ - { - "name": "", - "type": "bool" - } + { + "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": "spender", - "type": "address" - }, - { - "name": "addedValue", - "type": "uint256" - } + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], - "name": "increaseAllowance", + "name": "transfer", "outputs": [ - { - "name": "", - "type": "bool" - } + { + "name": "", + "type": "bool" + } ], "payable": false, "stateMutability": "nonpayable", "type": "function" - }, - { - "constant": false, + }, + { + "constant": true, "inputs": [ - { - "name": "spender", - "type": "address" - }, - { - "name": "subtractedValue", - "type": "uint256" - } + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } ], - "name": "decreaseAllowance", + "name": "allowance", "outputs": [ - { - "name": "", - "type": "bool" - } + { + "name": "", + "type": "uint256" + } ], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b506105dd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806370a082311161007857806370a0823114610166578063a457c2d71461018c578063a9059cbb146101b8578063dd62ed3e146101e4576100a5565b8063095ea7b3146100aa57806318160ddd146100ea57806323b872dd14610104578063395093511461013a575b600080fd5b6100d6600480360360408110156100c057600080fd5b50600160a060020a038135169060200135610212565b604080519115158252519081900360200190f35b6100f2610290565b60408051918252519081900360200190f35b6100d66004803603606081101561011a57600080fd5b50600160a060020a03813581169160208101359091169060400135610296565b6100d66004803603604081101561015057600080fd5b50600160a060020a03813516906020013561035f565b6100f26004803603602081101561017c57600080fd5b5035600160a060020a031661040f565b6100d6600480360360408110156101a257600080fd5b50600160a060020a03813516906020013561042a565b6100d6600480360360408110156101ce57600080fd5b50600160a060020a038135169060200135610475565b6100f2600480360360408110156101fa57600080fd5b50600160a060020a038135811691602001351661048b565b6000600160a060020a038316151561022957600080fd5b336000818152600160209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60025490565b600160a060020a03831660009081526001602090815260408083203384529091528120546102ca908363ffffffff6104b616565b600160a060020a03851660009081526001602090815260408083203384529091529020556102f98484846104cb565b600160a060020a0384166000818152600160209081526040808320338085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b6000600160a060020a038316151561037657600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff61059816565b336000818152600160209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a031660009081526020819052604090205490565b6000600160a060020a038316151561044157600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff6104b616565b60006104823384846104cb565b50600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000828211156104c557600080fd5b50900390565b600160a060020a03821615156104e057600080fd5b600160a060020a038316600090815260208190526040902054610509908263ffffffff6104b616565b600160a060020a03808516600090815260208190526040808220939093559084168152205461053e908263ffffffff61059816565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000828201838110156105aa57600080fd5b939250505056fea165627a7a72305820722c0187518ce2856a424bdba350d5a263c8f98fcb19cb4cc161372bc3b794c90029", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806370a082311161007857806370a0823114610166578063a457c2d71461018c578063a9059cbb146101b8578063dd62ed3e146101e4576100a5565b8063095ea7b3146100aa57806318160ddd146100ea57806323b872dd14610104578063395093511461013a575b600080fd5b6100d6600480360360408110156100c057600080fd5b50600160a060020a038135169060200135610212565b604080519115158252519081900360200190f35b6100f2610290565b60408051918252519081900360200190f35b6100d66004803603606081101561011a57600080fd5b50600160a060020a03813581169160208101359091169060400135610296565b6100d66004803603604081101561015057600080fd5b50600160a060020a03813516906020013561035f565b6100f26004803603602081101561017c57600080fd5b5035600160a060020a031661040f565b6100d6600480360360408110156101a257600080fd5b50600160a060020a03813516906020013561042a565b6100d6600480360360408110156101ce57600080fd5b50600160a060020a038135169060200135610475565b6100f2600480360360408110156101fa57600080fd5b50600160a060020a038135811691602001351661048b565b6000600160a060020a038316151561022957600080fd5b336000818152600160209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60025490565b600160a060020a03831660009081526001602090815260408083203384529091528120546102ca908363ffffffff6104b616565b600160a060020a03851660009081526001602090815260408083203384529091529020556102f98484846104cb565b600160a060020a0384166000818152600160209081526040808320338085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b6000600160a060020a038316151561037657600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff61059816565b336000818152600160209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a031660009081526020819052604090205490565b6000600160a060020a038316151561044157600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff6104b616565b60006104823384846104cb565b50600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000828211156104c557600080fd5b50900390565b600160a060020a03821615156104e057600080fd5b600160a060020a038316600090815260208190526040902054610509908263ffffffff6104b616565b600160a060020a03808516600090815260208190526040808220939093559084168152205461053e908263ffffffff61059816565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000828201838110156105aa57600080fd5b939250505056fea165627a7a72305820722c0187518ce2856a424bdba350d5a263c8f98fcb19cb4cc161372bc3b794c90029", - "compiler": { - "name": "solc", - "version": "0.5.4+commit.9549d8ff.Emscripten.clang" + }, + { + "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" } -} +] \ No newline at end of file diff --git a/packages/core/src/classes/WakuMessaging.ts b/packages/core/src/classes/WakuMessaging.ts index 21bb031..81515d0 100644 --- a/packages/core/src/classes/WakuMessaging.ts +++ b/packages/core/src/classes/WakuMessaging.ts @@ -25,12 +25,13 @@ type WakuMessageStores = { export class WakuMessaging { protected appName: string protected waku: Waku | undefined - public tokenAddress: string + protected token: Contract protected provider: Provider protected chainId = 0 protected wakuMessages: WakuMessageStores = {} protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = [] protected multicall: Contract + public tokenDecimals: number | undefined protected constructor( appName: string, @@ -41,10 +42,10 @@ export class WakuMessaging { waku?: Waku ) { this.appName = appName - this.tokenAddress = tokenAddress this.waku = waku this.provider = provider this.chainId = chainId + this.token = new Contract(tokenAddress, ERC20, this.provider) this.multicall = new Contract(multicall, ABI, this.provider) } @@ -54,6 +55,8 @@ export class WakuMessaging { } protected async setObserver() { + this.tokenDecimals = await this.token.decimals() + this.waku = await createWaku(this.waku) await Promise.all( Object.values(this.wakuMessages).map(async (msgObj) => { @@ -100,7 +103,7 @@ export class WakuMessaging { } } - protected addressesBalances: { [address: string]: BigNumber } = {} + protected addressesBalances: { [address: string]: BigNumber | undefined } = {} protected lastBlockBalances = 0 protected async updateBalances(newAddress?: string) { @@ -136,18 +139,27 @@ export class WakuMessaging { const addressesToUpdateArray = Object.keys(addressesToUpdate) if (addressesToUpdateArray.length > 0) { - const erc20 = new Interface(ERC20.abi) + const erc20 = this.token.interface const callData = addressesToUpdateArray.map((addr) => { - return [this.tokenAddress, erc20.encodeFunctionData('balanceOf', [addr])] + return [this.token.address, erc20.encodeFunctionData('balanceOf', [addr])] + }) + const result = (await this.multicall.aggregate(callData))[1].map((data: any) => { + try { + return erc20.decodeFunctionResult('balanceOf', data) + } catch { + return undefined + } }) - const result = (await this.multicall.aggregate(callData))[1].map((data: any) => - erc20.decodeFunctionResult('balanceOf', data) - ) result.forEach((e: any, idx: number) => { - this.addressesBalances[addressesToUpdateArray[idx]] = e[0] + this.addressesBalances[addressesToUpdateArray[idx]] = e ? e[0] : undefined }) this.lastBlockBalances = currentBlock } } + + public async getTokenBalance(address: string) { + await this.updateBalances(address) + return this.addressesBalances[address] ?? undefined + } } diff --git a/packages/proposal-components/src/components/Proposal.tsx b/packages/proposal-components/src/components/Proposal.tsx index 6f47713..36a5c48 100644 --- a/packages/proposal-components/src/components/Proposal.tsx +++ b/packages/proposal-components/src/components/Proposal.tsx @@ -7,13 +7,16 @@ import { NotificationItem } from './NotificationItem' import { WakuVoting } from '@status-waku-voting/core' import { VotingEmpty } from './VotingEmpty' import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType' +import { useTokenBalance } from '@status-waku-voting/react-components' type ProposalProps = { wakuVoting: WakuVoting + account: string | null | undefined } -export function Proposal({ wakuVoting }: ProposalProps) { +export function Proposal({ wakuVoting, account }: ProposalProps) { const [votes, setVotes] = useState([]) + const tokenBalance = useTokenBalance(account, wakuVoting) useEffect(() => { const interval = setInterval(async () => { @@ -26,11 +29,11 @@ export function Proposal({ wakuVoting }: ProposalProps) { return ( {votes && votes?.length === 0 ? ( - + ) : ( - - + + )} diff --git a/packages/proposal-components/src/components/ProposalCard.tsx b/packages/proposal-components/src/components/ProposalCard.tsx index 343ba15..b3155e6 100644 --- a/packages/proposal-components/src/components/ProposalCard.tsx +++ b/packages/proposal-components/src/components/ProposalCard.tsx @@ -11,15 +11,16 @@ interface ProposalCardProps { mobileVersion?: boolean theme: Theme hideModalFunction?: (val: boolean) => void + availableAmount: number } -export function ProposalCard({ theme, votingRoom, mobileVersion }: ProposalCardProps) { +export function ProposalCard({ theme, votingRoom, mobileVersion, availableAmount }: ProposalCardProps) { const history = useHistory() return ( mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}> - + ) } diff --git a/packages/proposal-components/src/components/ProposalHeader.tsx b/packages/proposal-components/src/components/ProposalHeader.tsx index 14f7956..e089cbb 100644 --- a/packages/proposal-components/src/components/ProposalHeader.tsx +++ b/packages/proposal-components/src/components/ProposalHeader.tsx @@ -11,9 +11,10 @@ import { BigNumber } from 'ethers' type ProposalHeaderProps = { theme: Theme wakuVoting: WakuVoting + availableAmount: number } -export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) { +export function ProposalHeader({ theme, wakuVoting, availableAmount }: ProposalHeaderProps) { const { activateBrowserWallet, account, library } = useEthers() const [selectConnect, setSelectConnect] = useState(false) const [showProposeModal, setShowProposeModal] = useState(false) @@ -41,7 +42,7 @@ export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) { text={text} setText={setText} setTitle={setTitle} - availableAmount={6524354} + availableAmount={availableAmount} setShowProposeVoteModal={setNext} /> @@ -52,7 +53,7 @@ export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) { wakuVoting={wakuVoting} title={title} text={text} - availableAmount={6524354} + availableAmount={availableAmount} setShowModal={setShowProposeVoteModal} setText={setText} setTitle={setTitle} diff --git a/packages/proposal-components/src/components/ProposalList.tsx b/packages/proposal-components/src/components/ProposalList.tsx index 9e86f2e..adfd3c8 100644 --- a/packages/proposal-components/src/components/ProposalList.tsx +++ b/packages/proposal-components/src/components/ProposalList.tsx @@ -10,14 +10,23 @@ type ProposalListProps = { theme: Theme wakuVoting: WakuVoting votes: VotingRoom[] + availableAmount: number } -export function ProposalList({ theme, wakuVoting, votes }: ProposalListProps) { +export function ProposalList({ theme, wakuVoting, votes, availableAmount }: ProposalListProps) { const ref = useRef(null) const mobileVersion = useMobileVersion(ref, 600) return ( {votes.map((votingRoom) => { - return + return ( + + ) })} ) diff --git a/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx b/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx index b1899d0..32176bb 100644 --- a/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx +++ b/packages/proposal-components/src/components/ProposalVoteCard/ProposalVote.tsx @@ -13,10 +13,11 @@ import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType interface ProposalVoteProps { theme: Theme votingRoom: VotingRoom + availableAmount: number hideModalFunction?: (val: boolean) => void } -export function ProposalVote({ votingRoom, theme, hideModalFunction }: ProposalVoteProps) { +export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunction }: ProposalVoteProps) { const { account } = useEthers() const [showVoteModal, setShowVoteModal] = useState(false) const [showConfirmModal, setShowConfirmModal] = useState(false) @@ -41,7 +42,7 @@ export function ProposalVote({ votingRoom, theme, hideModalFunction }: ProposalV @@ -56,7 +57,7 @@ export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) { wakuVoting={wakuVoting} title={title} text={text} - availableAmount={6524354} + availableAmount={availableAmount} setShowModal={setShowProposeVoteModal} setText={setText} setTitle={setTitle} diff --git a/packages/proposal-components/src/components/mobile/ProposalMainMobile.tsx b/packages/proposal-components/src/components/mobile/ProposalMainMobile.tsx index 701cd19..1b7d2f9 100644 --- a/packages/proposal-components/src/components/mobile/ProposalMainMobile.tsx +++ b/packages/proposal-components/src/components/mobile/ProposalMainMobile.tsx @@ -11,9 +11,10 @@ import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType type ProposalMainMobileProps = { wakuVoting: WakuVoting + availableAmount: number } -export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) { +export function ProposalMainMobile({ wakuVoting, availableAmount }: ProposalMainMobileProps) { const [votes, setVotes] = useState([]) useEffect(() => { @@ -26,11 +27,11 @@ export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) { return ( {votes && votes?.length === 0 ? ( - + ) : ( - + )} diff --git a/packages/proposal-components/src/components/mobile/ProposalMobile.tsx b/packages/proposal-components/src/components/mobile/ProposalMobile.tsx index 1753d72..7c0b94a 100644 --- a/packages/proposal-components/src/components/mobile/ProposalMobile.tsx +++ b/packages/proposal-components/src/components/mobile/ProposalMobile.tsx @@ -6,23 +6,28 @@ import { ProposalVoteMobile } from './ProposalVoteMobile' import { ProposeMobile } from './ProposeMobile' import { ProposalMainMobile } from './ProposalMainMobile' import { WakuVoting } from '@status-waku-voting/core' +import { useTokenBalance } from '@status-waku-voting/react-components' type ProposalMobileProps = { wakuVoting: WakuVoting + account: string | null | undefined } -export function ProposalMobile({ wakuVoting }: ProposalMobileProps) { +export function ProposalMobile({ wakuVoting, account }: ProposalMobileProps) { + const tokenBalance = useTokenBalance(account, wakuVoting) return ( } /> - + + + + - - + diff --git a/packages/proposal-components/src/components/mobile/ProposalVoteMobile.tsx b/packages/proposal-components/src/components/mobile/ProposalVoteMobile.tsx index 8a161d3..8debb4e 100644 --- a/packages/proposal-components/src/components/mobile/ProposalVoteMobile.tsx +++ b/packages/proposal-components/src/components/mobile/ProposalVoteMobile.tsx @@ -36,7 +36,7 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote {!voteWinner && ( diff --git a/packages/proposal-components/src/components/mobile/ProposeMobile.tsx b/packages/proposal-components/src/components/mobile/ProposeMobile.tsx index 1540e08..d556bf2 100644 --- a/packages/proposal-components/src/components/mobile/ProposeMobile.tsx +++ b/packages/proposal-components/src/components/mobile/ProposeMobile.tsx @@ -75,7 +75,7 @@ export function ProposeMobile({ availableAmount }: ProposeVoteModalProps) { diff --git a/packages/proposal-page/src/index.tsx b/packages/proposal-page/src/index.tsx index 4c5f940..855a7d7 100644 --- a/packages/proposal-page/src/index.tsx +++ b/packages/proposal-page/src/index.tsx @@ -40,7 +40,12 @@ function Proposals() { account={account} deactivate={deactivate} /> - {waku && (mobileVersion ? : )} + {waku && + (mobileVersion ? ( + + ) : ( + + ))} ) } diff --git a/packages/react-components/package.json b/packages/react-components/package.json index 7a9013c..b42f5a9 100644 --- a/packages/react-components/package.json +++ b/packages/react-components/package.json @@ -32,7 +32,8 @@ "dependencies": { "ethers": "^5.4.4", "react": "^17.0.2", - "styled-components": "^5.3.0" + "styled-components": "^5.3.0", + "@status-waku-voting/core": "^0.1.0" }, "devDependencies": { "@types/chai": "^4.2.21", diff --git a/packages/react-components/src/hooks/useTokenBalance.ts b/packages/react-components/src/hooks/useTokenBalance.ts new file mode 100644 index 0000000..70a0888 --- /dev/null +++ b/packages/react-components/src/hooks/useTokenBalance.ts @@ -0,0 +1,26 @@ +import { WakuMessaging } from '@status-waku-voting/core' +import { BigNumber } from 'ethers' +import React, { useEffect, useState } from 'react' + +export function useTokenBalance(address: string | null | undefined, wakuVoting: WakuMessaging) { + const [tokenBalance, setTokenBalance] = useState(0) + + useEffect(() => { + const updateBalances = async () => { + if (address) { + const tokenDecimals = wakuVoting.tokenDecimals + if (tokenDecimals) { + const balance = (await wakuVoting.getTokenBalance(address))?.div(BigNumber.from(10).pow(tokenDecimals)) + if (balance && !balance.eq(tokenBalance)) { + setTokenBalance(balance.toNumber()) + } + } + } + } + setTimeout(updateBalances, 1000) + const interval = setInterval(updateBalances, 10000) + return () => clearInterval(interval) + }, [address]) + + return tokenBalance +} diff --git a/packages/react-components/src/index.tsx b/packages/react-components/src/index.tsx index 905a3d7..d945983 100644 --- a/packages/react-components/src/index.tsx +++ b/packages/react-components/src/index.tsx @@ -16,7 +16,9 @@ import statusIcon from './assets/svg/status.svg' import themes, { Theme } from './style/themes' import { useRefSize } from './hooks/useRefSize' import { useMobileVersion } from './hooks/useMobileVersion' +import { useTokenBalance } from './hooks/useTokenBalance' export { + useTokenBalance, useMobileVersion, useRefSize, Modal,