allow user to enable/disable token transfers to vault

This commit is contained in:
Barry Gitarts 2019-02-06 18:02:03 -05:00
parent d0797caa69
commit 448c38b7ee
3 changed files with 188 additions and 129 deletions

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useContext, useState, useEffect } from 'react';
import { Formik } from 'formik'; import { Formik } from 'formik';
import EmbarkJS from 'Embark/EmbarkJS'; import EmbarkJS from 'Embark/EmbarkJS';
import LPVault from 'Embark/contracts/LPVault'; import LPVault from 'Embark/contracts/LPVault';
@ -7,9 +7,14 @@ import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import Snackbar from '@material-ui/core/Snackbar'; import Snackbar from '@material-ui/core/Snackbar';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import web3 from 'Embark/web3'; import FormControlLabel from '@material-ui/core/FormControlLabel'
import { MySnackbarContentWrapper } from './base/SnackBars'; import Switch from '@material-ui/core/Switch'
import web3 from 'Embark/web3'
import { MySnackbarContentWrapper } from './base/SnackBars'
import { currencies, TOKEN_ICON_API, getTokenLabel } from '../utils/currencies' import { currencies, TOKEN_ICON_API, getTokenLabel } from '../utils/currencies'
import { toEther } from '../utils/conversions'
import { getLpAllowance, standardTokenApproval } from '../utils/initialize'
import { FundingContext } from '../context'
const { donate } = LiquidPledging.methods const { donate } = LiquidPledging.methods
const hoursToSeconds = hours => hours * 60 * 60 const hoursToSeconds = hours => hours * 60 * 60
@ -18,125 +23,178 @@ const addFunderSucessMsg = response => {
return `Funder created with ID of ${idGiver}` return `Funder created with ID of ${idGiver}`
} }
const CreateFunding = ({ refreshTable }) => ( const CreateFunding = ({ refreshTable }) => {
<Formik const context = useContext(FundingContext)
initialValues={{ funderId: '', receiverId: '', tokenAddress : '', amount: '' }} const { account } = context
onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => { const [balances, setBalances] = useState({})
const { funderId, receiverId, tokenAddress, amount } = values const [allowances, setAllowances] = useState({})
const account = await web3.eth.getCoinbase()
const args = [funderId, receiverId, tokenAddress, web3.utils.toWei(amount, 'ether')];
const toSend = donate(...args);
const estimateGas = await toSend.estimateGas(); const updateBalancesAllowances = () => {
const latestBalances = {}
toSend.send({ from: account, gas: estimateGas + 2000 }) const latestAllowances = {}
.then(res => { currencies.forEach(async c => {
console.log({res}) if (c.contract) {
setStatus({ const amount = await c.contract.methods.balanceOf(account).call()
snackbar: { variant: 'success', message: 'funding provided!' } const allowance = await getLpAllowance(c.contract)
}) latestBalances[c.value] = toEther(amount)
refreshTable() latestAllowances[c.value] = toEther(allowance)
}) } else {
.catch(e => { latestBalances[c.value] = '0'
console.log({e}) latestAllowances[c.value] = '0'
setStatus({ }
snackbar: { variant: 'error', message: 'There was an error' } })
}) setBalances(latestBalances)
}) setAllowances(latestAllowances)
}} }
>
{({ const toggleAllowance = e => {
values, const token = currencies[e.target.value]
errors, const allowance = allowances[token.value]
touched, standardTokenApproval(
handleChange, token.contract,
handleBlur, Number(allowance) ? '0' : undefined
handleSubmit, ).then(res => {
setFieldValue, const { events: { Approval: { returnValues: { value } } } } = res
setStatus, setAllowances(state => ({ ...state, [token.value]: toEther(value) }))
status })
}) => ( }
<form autoComplete="off" onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column' }}>
<TextField useEffect(() => {
id="funderId" if (account) updateBalancesAllowances()
name="funderId" }, account)
label="Funder Id"
placeholder="Funder Id" return (
margin="normal" <Formik
variant="outlined" initialValues={{ funderId: '', receiverId: '', tokenAddress : '', amount: '' }}
onChange={handleChange} onSubmit={async (values, { setSubmitting, resetForm, setStatus }) => {
onBlur={handleBlur} const { funderId, receiverId, tokenAddress, amount } = values
value={values.funderId || ''} const args = [funderId, receiverId, tokenAddress, web3.utils.toWei(amount, 'ether')];
/>
<TextField const toSend = donate(...args);
id="receiverId"
name="receiverId" const estimateGas = await toSend.estimateGas()
label="Receiver Id"
placeholder="Receiver Id" toSend.send({ from: account, gas: estimateGas + 2000 })
margin="normal" .then(res => {
variant="outlined" console.log({res})
helperText="The receiver of the funding can be any admin, giver, delegate or a project" setStatus({
onChange={handleChange} snackbar: { variant: 'success', message: 'funding provided!' }
onBlur={handleBlur} })
value={values.receiverId || ''} refreshTable()
/> })
<TextField .catch(e => {
id="tokenAddress" console.log({e})
name="tokenAddress" setStatus({
select snackbar: { variant: 'error', message: 'There was an error' }
label="Select token for funding" })
placeholder="Select token for funding" })
margin="normal" }}
variant="outlined" >
onChange={handleChange} {({
onBlur={handleBlur} values,
value={values.tokenAddress || ''} errors,
> touched,
{currencies.map(option => ( handleChange,
<MenuItem style={{ display: 'flex', alignItems: 'center' }} key={option.value} value={option.value}> handleBlur,
<div style={{ display: 'flex', alignItems: 'center' }} > handleSubmit,
{option.icon || <img setFieldValue,
src={option.img || `${TOKEN_ICON_API}/${option.value}.png`} setStatus,
style={{ width: option.width, marginRight: '3%' }} status
/>} }) => (
{option.label} <form autoComplete="off" onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column' }}>
</div> <TextField
</MenuItem> id="funderId"
))} name="funderId"
</TextField> label="Funder Id"
<TextField placeholder="Funder Id"
id="amount" margin="normal"
name="amount" variant="outlined"
label={`Amount of ${getTokenLabel(values.tokenAddress) || 'tokens'} to provide`} onChange={handleChange}
placeholder="Amount of tokens to provide" onBlur={handleBlur}
margin="normal" value={values.funderId || ''}
variant="outlined"
onChange={handleChange}
onBlur={handleBlur}
value={values.amount || ''}
/>
<Button variant="contained" color="primary" type="submit">
PROVIDE FUNDING
</Button>
{status && <Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={!!status.snackbar}
autoHideDuration={6000}
onClose={() => setStatus(null)}
>
<MySnackbarContentWrapper
onClose={() => setStatus(null)}
variant={status.snackbar.variant}
message={status.snackbar.message}
/> />
</Snackbar>} <TextField
</form> id="receiverId"
)} name="receiverId"
</Formik> label="Receiver Id"
) placeholder="Receiver Id"
margin="normal"
variant="outlined"
helperText="The receiver of the funding can be any admin, giver, delegate or a project"
onChange={handleChange}
onBlur={handleBlur}
value={values.receiverId || ''}
/>
<TextField
id="tokenAddress"
name="tokenAddress"
select
label="Select token for funding"
placeholder="Select token for funding"
margin="normal"
variant="outlined"
onChange={handleChange}
onBlur={handleBlur}
value={values.tokenAddress || ''}
>
{currencies.map((option, idx) => (
<MenuItem style={{ display: 'flex', alignItems: 'center' }} key={option.value} value={option.value}>
<div style={{ display: 'flex', alignItems: 'center' }} >
{option.icon || <img
src={option.img || `${TOKEN_ICON_API}/${option.value}.png`}
style={{ width: option.width, marginRight: '3%' }}
/>}
{option.label}
<span style={{ marginLeft: '10%' }}>Your Balance: <strong>{balances[option.value]}</strong></span>
<FormControlLabel
style={{ marginLeft: '10%' }}
onClick={e => e.stopPropagation()}
control={
<Switch
checked={!!Number(allowances[option.value])}
onChange={toggleAllowance}
value={idx}
color="primary"
/>
}
label="Enabled"
/>
</div>
</MenuItem>
))}
</TextField>
<TextField
id="amount"
name="amount"
label={`Amount of ${getTokenLabel(values.tokenAddress) || 'tokens'} to provide`}
placeholder="Amount of tokens to provide"
margin="normal"
variant="outlined"
onChange={handleChange}
onBlur={handleBlur}
value={values.amount || ''}
/>
<Button variant="contained" color="primary" type="submit">
PROVIDE FUNDING
</Button>
{status && <Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={!!status.snackbar}
autoHideDuration={6000}
onClose={() => setStatus(null)}
>
<MySnackbarContentWrapper
onClose={() => setStatus(null)}
variant={status.snackbar.variant}
message={status.snackbar.message}
/>
</Snackbar>}
</form>
)}
</Formik>
)}
export default CreateFunding export default CreateFunding

View File

@ -1,4 +1,4 @@
import StandardToken from 'Embark/contracts/StandardToken' import web3 from 'Embark/web3'
import SNT from 'Embark/contracts/SNT' import SNT from 'Embark/contracts/SNT'
import sntIco from 'cryptocurrency-icons/svg/color/snt.svg' import sntIco from 'cryptocurrency-icons/svg/color/snt.svg'
@ -15,7 +15,8 @@ export const currencies = [
{ {
value: SNT._address, value: SNT._address,
label: 'Status (SNT)', label: 'Status (SNT)',
img: sntIco img: sntIco,
contract: SNT
}, },
{ {
value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359',

View File

@ -25,19 +25,19 @@ export const vaultPledgingNeedsInit = async () => {
return needsInit return needsInit
} }
export const standardTokenApproval = async () => { export const standardTokenApproval = async (contract, amount = '10000000') => {
const { approve } = SNT.methods const { methods: { approve } } = contract || SNT
const spender = LiquidPledging._address const spender = LiquidPledging._address
return await approve( return await approve(
spender, spender,
web3.utils.toWei('10000000', 'tether') web3.utils.toWei(amount, 'tether')
).send() ).send()
} }
export const getLpAllowance = async () => { export const getLpAllowance = async contract => {
const { allowance } = SNT.methods const { methods: { allowance } } = contract || SNT
const account = await web3.eth.getCoinbase() const account = await web3.eth.getCoinbase()
const spender = LiquidPledging._address const spender = LiquidPledging._address
const allowanceAmt = Number(await allowance(account, spender).call()) const allowanceAmt = await allowance(account, spender).call()
return allowanceAmt return allowanceAmt
} }