Use user tokens (#72)

This commit is contained in:
Szymon Szlachtowicz 2021-09-15 00:47:14 +02:00 committed by GitHub
parent 983f557fbc
commit 5acbc88487
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 292 additions and 231 deletions

View File

@ -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"
}
}
]

View File

@ -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
}
}

View File

@ -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<VotingRoom[]>([])
const tokenBalance = useTokenBalance(account, wakuVoting)
useEffect(() => {
const interval = setInterval(async () => {
@ -26,11 +29,11 @@ export function Proposal({ wakuVoting }: ProposalProps) {
return (
<ProposalWrapper>
{votes && votes?.length === 0 ? (
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} />
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} availableAmount={tokenBalance} />
) : (
<ProposalVotesWrapper>
<ProposalHeader theme={blueTheme} wakuVoting={wakuVoting} />
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} />
<ProposalHeader theme={blueTheme} wakuVoting={wakuVoting} availableAmount={tokenBalance} />
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} availableAmount={tokenBalance} />
</ProposalVotesWrapper>
)}

View File

@ -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 (
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
<ProposalInfo votingRoom={votingRoom} />
<ProposalVote votingRoom={votingRoom} theme={theme} />
<ProposalVote votingRoom={votingRoom} theme={theme} availableAmount={availableAmount} />
</Card>
)
}

View File

@ -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}
/>
</Modal>
@ -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}

View File

@ -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<HTMLHeadingElement>(null)
const mobileVersion = useMobileVersion(ref, 600)
return (
<List ref={ref}>
{votes.map((votingRoom) => {
return <ProposalCard votingRoom={votingRoom} theme={theme} key={votingRoom.id} mobileVersion={mobileVersion} />
return (
<ProposalCard
votingRoom={votingRoom}
theme={theme}
key={votingRoom.id}
mobileVersion={mobileVersion}
availableAmount={availableAmount}
/>
)
})}
</List>
)

View File

@ -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
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
<VoteModal
votingRoom={votingRoom}
availableAmount={65245346}
availableAmount={availableAmount}
selectedVote={selectedVoted}
proposingAmount={proposingAmount}
setShowConfirmModal={setNext}

View File

@ -3,6 +3,7 @@ import styled from 'styled-components'
import { ProposingBtn } from './Buttons'
import { TextArea } from './Input'
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
import { BigNumber } from 'ethers'
interface ProposeModalProps {
availableAmount: number

View File

@ -10,9 +10,10 @@ import { WakuVoting } from '@status-waku-voting/core'
type VotingEmptyProps = {
theme: Theme
wakuVoting: WakuVoting
availableAmount: number
}
export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) {
export function VotingEmpty({ wakuVoting, theme, availableAmount }: VotingEmptyProps) {
const { account, activateBrowserWallet } = useEthers()
const [selectConnect, setSelectConnect] = useState(false)
const [showProposeModal, setShowProposeModal] = useState(false)
@ -45,7 +46,7 @@ export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) {
text={text}
setText={setText}
setTitle={setTitle}
availableAmount={6524354}
availableAmount={availableAmount}
setShowProposeVoteModal={setNext}
/>
</Modal>
@ -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}

View File

@ -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<VotingRoom[]>([])
useEffect(() => {
@ -26,11 +27,11 @@ export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) {
return (
<ProposalWrapper>
{votes && votes?.length === 0 ? (
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} />
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} availableAmount={availableAmount} />
) : (
<ProposalVotesWrapper>
<ProposalHeaderMobile theme={blueTheme} />
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} />
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} availableAmount={availableAmount} />
</ProposalVotesWrapper>
)}
<NotificationItem text={'Proposal you finalized will be settled after 10 confirmations.'} address={'#'} />

View File

@ -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 (
<BrowserRouter>
<ProposalWrapper>
<Switch>
<Route exact path="/" render={() => <Redirect to="/proposal" />} />
<Route exact path="/votingRoom/:id">
<ProposalVoteMobile wakuVoting={wakuVoting} availableAmount={123} />
<ProposalVoteMobile wakuVoting={wakuVoting} availableAmount={tokenBalance} />
</Route>
<Route exact path="/creation">
<ProposeMobile availableAmount={tokenBalance} />
</Route>
<Route exact path="/creation" component={ProposeMobile} />
<Route exact path="/proposal">
<ProposalMainMobile wakuVoting={wakuVoting} />
<ProposalMainMobile wakuVoting={wakuVoting} availableAmount={tokenBalance} />
</Route>
</Switch>
</ProposalWrapper>

View File

@ -36,7 +36,7 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
</VoteChartWrap>
{!voteWinner && (
<VotePropose
availableAmount={65245346}
availableAmount={availableAmount}
setProposingAmount={setProposingAmount}
proposingAmount={proposingAmount}
/>

View File

@ -75,7 +75,7 @@ export function ProposeMobile({ availableAmount }: ProposeVoteModalProps) {
<VoteProposeWrap>
<VotePropose
availableAmount={65245555}
availableAmount={availableAmount}
setProposingAmount={setProposingAmount}
proposingAmount={proposingAmount}
/>

View File

@ -40,7 +40,12 @@ function Proposals() {
account={account}
deactivate={deactivate}
/>
{waku && (mobileVersion ? <ProposalMobile wakuVoting={waku} /> : <Proposal wakuVoting={waku} />)}
{waku &&
(mobileVersion ? (
<ProposalMobile wakuVoting={waku} account={account} />
) : (
<Proposal wakuVoting={waku} account={account} />
))}
</Wrapper>
)
}

View File

@ -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",

View File

@ -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
}

View File

@ -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,