Use user tokens (#72)
This commit is contained in:
parent
983f557fbc
commit
5acbc88487
|
@ -1,27 +1,179 @@
|
||||||
|
[
|
||||||
{
|
{
|
||||||
"contractName": "ERC20",
|
"constant": true,
|
||||||
"abi": [
|
"inputs": [],
|
||||||
|
"name": "name",
|
||||||
|
"outputs": [
|
||||||
{
|
{
|
||||||
"anonymous": false,
|
"name": "",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
"indexed": true,
|
"name": "_spender",
|
||||||
"name": "from",
|
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": true,
|
"name": "_value",
|
||||||
"name": "to",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "value",
|
|
||||||
"type": "uint256"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "Transfer",
|
"name": "approve",
|
||||||
"type": "event"
|
"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,
|
"anonymous": false,
|
||||||
|
@ -46,185 +198,25 @@
|
||||||
"type": "event"
|
"type": "event"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"constant": true,
|
"anonymous": false,
|
||||||
"inputs": [],
|
|
||||||
"name": "totalSupply",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"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": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
"indexed": true,
|
||||||
"name": "from",
|
"name": "from",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"indexed": true,
|
||||||
"name": "to",
|
"name": "to",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"indexed": false,
|
||||||
"name": "value",
|
"name": "value",
|
||||||
"type": "uint256"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "transferFrom",
|
"name": "Transfer",
|
||||||
"outputs": [
|
"type": "event"
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "spender",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "addedValue",
|
|
||||||
"type": "uint256"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "increaseAllowance",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "spender",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "subtractedValue",
|
|
||||||
"type": "uint256"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "decreaseAllowance",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bytecode": "0x608060405234801561001057600080fd5b506105dd806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806370a082311161007857806370a0823114610166578063a457c2d71461018c578063a9059cbb146101b8578063dd62ed3e146101e4576100a5565b8063095ea7b3146100aa57806318160ddd146100ea57806323b872dd14610104578063395093511461013a575b600080fd5b6100d6600480360360408110156100c057600080fd5b50600160a060020a038135169060200135610212565b604080519115158252519081900360200190f35b6100f2610290565b60408051918252519081900360200190f35b6100d66004803603606081101561011a57600080fd5b50600160a060020a03813581169160208101359091169060400135610296565b6100d66004803603604081101561015057600080fd5b50600160a060020a03813516906020013561035f565b6100f26004803603602081101561017c57600080fd5b5035600160a060020a031661040f565b6100d6600480360360408110156101a257600080fd5b50600160a060020a03813516906020013561042a565b6100d6600480360360408110156101ce57600080fd5b50600160a060020a038135169060200135610475565b6100f2600480360360408110156101fa57600080fd5b50600160a060020a038135811691602001351661048b565b6000600160a060020a038316151561022957600080fd5b336000818152600160209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60025490565b600160a060020a03831660009081526001602090815260408083203384529091528120546102ca908363ffffffff6104b616565b600160a060020a03851660009081526001602090815260408083203384529091529020556102f98484846104cb565b600160a060020a0384166000818152600160209081526040808320338085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b6000600160a060020a038316151561037657600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff61059816565b336000818152600160209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a031660009081526020819052604090205490565b6000600160a060020a038316151561044157600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff6104b616565b60006104823384846104cb565b50600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000828211156104c557600080fd5b50900390565b600160a060020a03821615156104e057600080fd5b600160a060020a038316600090815260208190526040902054610509908263ffffffff6104b616565b600160a060020a03808516600090815260208190526040808220939093559084168152205461053e908263ffffffff61059816565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000828201838110156105aa57600080fd5b939250505056fea165627a7a72305820722c0187518ce2856a424bdba350d5a263c8f98fcb19cb4cc161372bc3b794c90029",
|
|
||||||
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a5576000357c01000000000000000000000000000000000000000000000000000000009004806370a082311161007857806370a0823114610166578063a457c2d71461018c578063a9059cbb146101b8578063dd62ed3e146101e4576100a5565b8063095ea7b3146100aa57806318160ddd146100ea57806323b872dd14610104578063395093511461013a575b600080fd5b6100d6600480360360408110156100c057600080fd5b50600160a060020a038135169060200135610212565b604080519115158252519081900360200190f35b6100f2610290565b60408051918252519081900360200190f35b6100d66004803603606081101561011a57600080fd5b50600160a060020a03813581169160208101359091169060400135610296565b6100d66004803603604081101561015057600080fd5b50600160a060020a03813516906020013561035f565b6100f26004803603602081101561017c57600080fd5b5035600160a060020a031661040f565b6100d6600480360360408110156101a257600080fd5b50600160a060020a03813516906020013561042a565b6100d6600480360360408110156101ce57600080fd5b50600160a060020a038135169060200135610475565b6100f2600480360360408110156101fa57600080fd5b50600160a060020a038135811691602001351661048b565b6000600160a060020a038316151561022957600080fd5b336000818152600160209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b60025490565b600160a060020a03831660009081526001602090815260408083203384529091528120546102ca908363ffffffff6104b616565b600160a060020a03851660009081526001602090815260408083203384529091529020556102f98484846104cb565b600160a060020a0384166000818152600160209081526040808320338085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b6000600160a060020a038316151561037657600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff61059816565b336000818152600160209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a031660009081526020819052604090205490565b6000600160a060020a038316151561044157600080fd5b336000908152600160209081526040808320600160a060020a03871684529091529020546103aa908363ffffffff6104b616565b60006104823384846104cb565b50600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000828211156104c557600080fd5b50900390565b600160a060020a03821615156104e057600080fd5b600160a060020a038316600090815260208190526040902054610509908263ffffffff6104b616565b600160a060020a03808516600090815260208190526040808220939093559084168152205461053e908263ffffffff61059816565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b6000828201838110156105aa57600080fd5b939250505056fea165627a7a72305820722c0187518ce2856a424bdba350d5a263c8f98fcb19cb4cc161372bc3b794c90029",
|
|
||||||
"compiler": {
|
|
||||||
"name": "solc",
|
|
||||||
"version": "0.5.4+commit.9549d8ff.Emscripten.clang"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
]
|
|
@ -25,12 +25,13 @@ type WakuMessageStores = {
|
||||||
export class WakuMessaging {
|
export class WakuMessaging {
|
||||||
protected appName: string
|
protected appName: string
|
||||||
protected waku: Waku | undefined
|
protected waku: Waku | undefined
|
||||||
public tokenAddress: string
|
protected token: Contract
|
||||||
protected provider: Provider
|
protected provider: Provider
|
||||||
protected chainId = 0
|
protected chainId = 0
|
||||||
protected wakuMessages: WakuMessageStores = {}
|
protected wakuMessages: WakuMessageStores = {}
|
||||||
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
|
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
|
||||||
protected multicall: Contract
|
protected multicall: Contract
|
||||||
|
public tokenDecimals: number | undefined
|
||||||
|
|
||||||
protected constructor(
|
protected constructor(
|
||||||
appName: string,
|
appName: string,
|
||||||
|
@ -41,10 +42,10 @@ export class WakuMessaging {
|
||||||
waku?: Waku
|
waku?: Waku
|
||||||
) {
|
) {
|
||||||
this.appName = appName
|
this.appName = appName
|
||||||
this.tokenAddress = tokenAddress
|
|
||||||
this.waku = waku
|
this.waku = waku
|
||||||
this.provider = provider
|
this.provider = provider
|
||||||
this.chainId = chainId
|
this.chainId = chainId
|
||||||
|
this.token = new Contract(tokenAddress, ERC20, this.provider)
|
||||||
this.multicall = new Contract(multicall, ABI, this.provider)
|
this.multicall = new Contract(multicall, ABI, this.provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +55,8 @@ export class WakuMessaging {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async setObserver() {
|
protected async setObserver() {
|
||||||
|
this.tokenDecimals = await this.token.decimals()
|
||||||
|
|
||||||
this.waku = await createWaku(this.waku)
|
this.waku = await createWaku(this.waku)
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Object.values(this.wakuMessages).map(async (msgObj) => {
|
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 lastBlockBalances = 0
|
||||||
|
|
||||||
protected async updateBalances(newAddress?: string) {
|
protected async updateBalances(newAddress?: string) {
|
||||||
|
@ -136,18 +139,27 @@ export class WakuMessaging {
|
||||||
|
|
||||||
const addressesToUpdateArray = Object.keys(addressesToUpdate)
|
const addressesToUpdateArray = Object.keys(addressesToUpdate)
|
||||||
if (addressesToUpdateArray.length > 0) {
|
if (addressesToUpdateArray.length > 0) {
|
||||||
const erc20 = new Interface(ERC20.abi)
|
const erc20 = this.token.interface
|
||||||
const callData = addressesToUpdateArray.map((addr) => {
|
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) => {
|
result.forEach((e: any, idx: number) => {
|
||||||
this.addressesBalances[addressesToUpdateArray[idx]] = e[0]
|
this.addressesBalances[addressesToUpdateArray[idx]] = e ? e[0] : undefined
|
||||||
})
|
})
|
||||||
this.lastBlockBalances = currentBlock
|
this.lastBlockBalances = currentBlock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getTokenBalance(address: string) {
|
||||||
|
await this.updateBalances(address)
|
||||||
|
return this.addressesBalances[address] ?? undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,16 @@ import { NotificationItem } from './NotificationItem'
|
||||||
import { WakuVoting } from '@status-waku-voting/core'
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
import { VotingEmpty } from './VotingEmpty'
|
import { VotingEmpty } from './VotingEmpty'
|
||||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
|
import { useTokenBalance } from '@status-waku-voting/react-components'
|
||||||
|
|
||||||
type ProposalProps = {
|
type ProposalProps = {
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
|
account: string | null | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Proposal({ wakuVoting }: ProposalProps) {
|
export function Proposal({ wakuVoting, account }: ProposalProps) {
|
||||||
const [votes, setVotes] = useState<VotingRoom[]>([])
|
const [votes, setVotes] = useState<VotingRoom[]>([])
|
||||||
|
const tokenBalance = useTokenBalance(account, wakuVoting)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
|
@ -26,11 +29,11 @@ export function Proposal({ wakuVoting }: ProposalProps) {
|
||||||
return (
|
return (
|
||||||
<ProposalWrapper>
|
<ProposalWrapper>
|
||||||
{votes && votes?.length === 0 ? (
|
{votes && votes?.length === 0 ? (
|
||||||
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} />
|
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} availableAmount={tokenBalance} />
|
||||||
) : (
|
) : (
|
||||||
<ProposalVotesWrapper>
|
<ProposalVotesWrapper>
|
||||||
<ProposalHeader theme={blueTheme} wakuVoting={wakuVoting} />
|
<ProposalHeader theme={blueTheme} wakuVoting={wakuVoting} availableAmount={tokenBalance} />
|
||||||
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} />
|
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} availableAmount={tokenBalance} />
|
||||||
</ProposalVotesWrapper>
|
</ProposalVotesWrapper>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -11,15 +11,16 @@ interface ProposalCardProps {
|
||||||
mobileVersion?: boolean
|
mobileVersion?: boolean
|
||||||
theme: Theme
|
theme: Theme
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
|
availableAmount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalCard({ theme, votingRoom, mobileVersion }: ProposalCardProps) {
|
export function ProposalCard({ theme, votingRoom, mobileVersion, availableAmount }: ProposalCardProps) {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
|
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
|
||||||
<ProposalInfo votingRoom={votingRoom} />
|
<ProposalInfo votingRoom={votingRoom} />
|
||||||
<ProposalVote votingRoom={votingRoom} theme={theme} />
|
<ProposalVote votingRoom={votingRoom} theme={theme} availableAmount={availableAmount} />
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@ import { BigNumber } from 'ethers'
|
||||||
type ProposalHeaderProps = {
|
type ProposalHeaderProps = {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
|
availableAmount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) {
|
export function ProposalHeader({ theme, wakuVoting, availableAmount }: ProposalHeaderProps) {
|
||||||
const { activateBrowserWallet, account, library } = useEthers()
|
const { activateBrowserWallet, account, library } = useEthers()
|
||||||
const [selectConnect, setSelectConnect] = useState(false)
|
const [selectConnect, setSelectConnect] = useState(false)
|
||||||
const [showProposeModal, setShowProposeModal] = useState(false)
|
const [showProposeModal, setShowProposeModal] = useState(false)
|
||||||
|
@ -41,7 +42,7 @@ export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) {
|
||||||
text={text}
|
text={text}
|
||||||
setText={setText}
|
setText={setText}
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
availableAmount={6524354}
|
availableAmount={availableAmount}
|
||||||
setShowProposeVoteModal={setNext}
|
setShowProposeVoteModal={setNext}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -52,7 +53,7 @@ export function ProposalHeader({ theme, wakuVoting }: ProposalHeaderProps) {
|
||||||
wakuVoting={wakuVoting}
|
wakuVoting={wakuVoting}
|
||||||
title={title}
|
title={title}
|
||||||
text={text}
|
text={text}
|
||||||
availableAmount={6524354}
|
availableAmount={availableAmount}
|
||||||
setShowModal={setShowProposeVoteModal}
|
setShowModal={setShowProposeVoteModal}
|
||||||
setText={setText}
|
setText={setText}
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
|
|
|
@ -10,14 +10,23 @@ type ProposalListProps = {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
votes: VotingRoom[]
|
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 ref = useRef<HTMLHeadingElement>(null)
|
||||||
const mobileVersion = useMobileVersion(ref, 600)
|
const mobileVersion = useMobileVersion(ref, 600)
|
||||||
return (
|
return (
|
||||||
<List ref={ref}>
|
<List ref={ref}>
|
||||||
{votes.map((votingRoom) => {
|
{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>
|
</List>
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,10 +13,11 @@ import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType
|
||||||
interface ProposalVoteProps {
|
interface ProposalVoteProps {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
votingRoom: VotingRoom
|
votingRoom: VotingRoom
|
||||||
|
availableAmount: number
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalVote({ votingRoom, theme, hideModalFunction }: ProposalVoteProps) {
|
export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunction }: ProposalVoteProps) {
|
||||||
const { account } = useEthers()
|
const { account } = useEthers()
|
||||||
const [showVoteModal, setShowVoteModal] = useState(false)
|
const [showVoteModal, setShowVoteModal] = useState(false)
|
||||||
const [showConfirmModal, setShowConfirmModal] = 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}>
|
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
|
||||||
<VoteModal
|
<VoteModal
|
||||||
votingRoom={votingRoom}
|
votingRoom={votingRoom}
|
||||||
availableAmount={65245346}
|
availableAmount={availableAmount}
|
||||||
selectedVote={selectedVoted}
|
selectedVote={selectedVoted}
|
||||||
proposingAmount={proposingAmount}
|
proposingAmount={proposingAmount}
|
||||||
setShowConfirmModal={setNext}
|
setShowConfirmModal={setNext}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import styled from 'styled-components'
|
||||||
import { ProposingBtn } from './Buttons'
|
import { ProposingBtn } from './Buttons'
|
||||||
import { TextArea } from './Input'
|
import { TextArea } from './Input'
|
||||||
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
|
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
|
||||||
|
import { BigNumber } from 'ethers'
|
||||||
|
|
||||||
interface ProposeModalProps {
|
interface ProposeModalProps {
|
||||||
availableAmount: number
|
availableAmount: number
|
||||||
|
|
|
@ -10,9 +10,10 @@ import { WakuVoting } from '@status-waku-voting/core'
|
||||||
type VotingEmptyProps = {
|
type VotingEmptyProps = {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
|
availableAmount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) {
|
export function VotingEmpty({ wakuVoting, theme, availableAmount }: VotingEmptyProps) {
|
||||||
const { account, activateBrowserWallet } = useEthers()
|
const { account, activateBrowserWallet } = useEthers()
|
||||||
const [selectConnect, setSelectConnect] = useState(false)
|
const [selectConnect, setSelectConnect] = useState(false)
|
||||||
const [showProposeModal, setShowProposeModal] = useState(false)
|
const [showProposeModal, setShowProposeModal] = useState(false)
|
||||||
|
@ -45,7 +46,7 @@ export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) {
|
||||||
text={text}
|
text={text}
|
||||||
setText={setText}
|
setText={setText}
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
availableAmount={6524354}
|
availableAmount={availableAmount}
|
||||||
setShowProposeVoteModal={setNext}
|
setShowProposeVoteModal={setNext}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -56,7 +57,7 @@ export function VotingEmpty({ wakuVoting, theme }: VotingEmptyProps) {
|
||||||
wakuVoting={wakuVoting}
|
wakuVoting={wakuVoting}
|
||||||
title={title}
|
title={title}
|
||||||
text={text}
|
text={text}
|
||||||
availableAmount={6524354}
|
availableAmount={availableAmount}
|
||||||
setShowModal={setShowProposeVoteModal}
|
setShowModal={setShowProposeVoteModal}
|
||||||
setText={setText}
|
setText={setText}
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
|
|
|
@ -11,9 +11,10 @@ import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType
|
||||||
|
|
||||||
type ProposalMainMobileProps = {
|
type ProposalMainMobileProps = {
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
|
availableAmount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) {
|
export function ProposalMainMobile({ wakuVoting, availableAmount }: ProposalMainMobileProps) {
|
||||||
const [votes, setVotes] = useState<VotingRoom[]>([])
|
const [votes, setVotes] = useState<VotingRoom[]>([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -26,11 +27,11 @@ export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) {
|
||||||
return (
|
return (
|
||||||
<ProposalWrapper>
|
<ProposalWrapper>
|
||||||
{votes && votes?.length === 0 ? (
|
{votes && votes?.length === 0 ? (
|
||||||
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} />
|
<VotingEmpty wakuVoting={wakuVoting} theme={blueTheme} availableAmount={availableAmount} />
|
||||||
) : (
|
) : (
|
||||||
<ProposalVotesWrapper>
|
<ProposalVotesWrapper>
|
||||||
<ProposalHeaderMobile theme={blueTheme} />
|
<ProposalHeaderMobile theme={blueTheme} />
|
||||||
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} />
|
<ProposalList theme={blueTheme} wakuVoting={wakuVoting} votes={votes} availableAmount={availableAmount} />
|
||||||
</ProposalVotesWrapper>
|
</ProposalVotesWrapper>
|
||||||
)}
|
)}
|
||||||
<NotificationItem text={'Proposal you finalized will be settled after 10 confirmations.'} address={'#'} />
|
<NotificationItem text={'Proposal you finalized will be settled after 10 confirmations.'} address={'#'} />
|
||||||
|
|
|
@ -6,23 +6,28 @@ import { ProposalVoteMobile } from './ProposalVoteMobile'
|
||||||
import { ProposeMobile } from './ProposeMobile'
|
import { ProposeMobile } from './ProposeMobile'
|
||||||
import { ProposalMainMobile } from './ProposalMainMobile'
|
import { ProposalMainMobile } from './ProposalMainMobile'
|
||||||
import { WakuVoting } from '@status-waku-voting/core'
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
|
import { useTokenBalance } from '@status-waku-voting/react-components'
|
||||||
|
|
||||||
type ProposalMobileProps = {
|
type ProposalMobileProps = {
|
||||||
wakuVoting: WakuVoting
|
wakuVoting: WakuVoting
|
||||||
|
account: string | null | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalMobile({ wakuVoting }: ProposalMobileProps) {
|
export function ProposalMobile({ wakuVoting, account }: ProposalMobileProps) {
|
||||||
|
const tokenBalance = useTokenBalance(account, wakuVoting)
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<ProposalWrapper>
|
<ProposalWrapper>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" render={() => <Redirect to="/proposal" />} />
|
<Route exact path="/" render={() => <Redirect to="/proposal" />} />
|
||||||
<Route exact path="/votingRoom/:id">
|
<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>
|
||||||
<Route exact path="/creation" component={ProposeMobile} />
|
|
||||||
<Route exact path="/proposal">
|
<Route exact path="/proposal">
|
||||||
<ProposalMainMobile wakuVoting={wakuVoting} />
|
<ProposalMainMobile wakuVoting={wakuVoting} availableAmount={tokenBalance} />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</ProposalWrapper>
|
</ProposalWrapper>
|
||||||
|
|
|
@ -36,7 +36,7 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
|
||||||
</VoteChartWrap>
|
</VoteChartWrap>
|
||||||
{!voteWinner && (
|
{!voteWinner && (
|
||||||
<VotePropose
|
<VotePropose
|
||||||
availableAmount={65245346}
|
availableAmount={availableAmount}
|
||||||
setProposingAmount={setProposingAmount}
|
setProposingAmount={setProposingAmount}
|
||||||
proposingAmount={proposingAmount}
|
proposingAmount={proposingAmount}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -75,7 +75,7 @@ export function ProposeMobile({ availableAmount }: ProposeVoteModalProps) {
|
||||||
|
|
||||||
<VoteProposeWrap>
|
<VoteProposeWrap>
|
||||||
<VotePropose
|
<VotePropose
|
||||||
availableAmount={65245555}
|
availableAmount={availableAmount}
|
||||||
setProposingAmount={setProposingAmount}
|
setProposingAmount={setProposingAmount}
|
||||||
proposingAmount={proposingAmount}
|
proposingAmount={proposingAmount}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -40,7 +40,12 @@ function Proposals() {
|
||||||
account={account}
|
account={account}
|
||||||
deactivate={deactivate}
|
deactivate={deactivate}
|
||||||
/>
|
/>
|
||||||
{waku && (mobileVersion ? <ProposalMobile wakuVoting={waku} /> : <Proposal wakuVoting={waku} />)}
|
{waku &&
|
||||||
|
(mobileVersion ? (
|
||||||
|
<ProposalMobile wakuVoting={waku} account={account} />
|
||||||
|
) : (
|
||||||
|
<Proposal wakuVoting={waku} account={account} />
|
||||||
|
))}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ethers": "^5.4.4",
|
"ethers": "^5.4.4",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"styled-components": "^5.3.0"
|
"styled-components": "^5.3.0",
|
||||||
|
"@status-waku-voting/core": "^0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chai": "^4.2.21",
|
"@types/chai": "^4.2.21",
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -16,7 +16,9 @@ import statusIcon from './assets/svg/status.svg'
|
||||||
import themes, { Theme } from './style/themes'
|
import themes, { Theme } from './style/themes'
|
||||||
import { useRefSize } from './hooks/useRefSize'
|
import { useRefSize } from './hooks/useRefSize'
|
||||||
import { useMobileVersion } from './hooks/useMobileVersion'
|
import { useMobileVersion } from './hooks/useMobileVersion'
|
||||||
|
import { useTokenBalance } from './hooks/useTokenBalance'
|
||||||
export {
|
export {
|
||||||
|
useTokenBalance,
|
||||||
useMobileVersion,
|
useMobileVersion,
|
||||||
useRefSize,
|
useRefSize,
|
||||||
Modal,
|
Modal,
|
||||||
|
|
Loading…
Reference in New Issue