mirror of
https://github.com/status-im/liquid-funding.git
synced 2025-02-10 18:36:54 +00:00
add authorization check and step progress
This commit is contained in:
parent
1e8f391f61
commit
dcb329557f
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useMemo, useEffect } from 'react'
|
import React, { useContext, useState, useMemo, useEffect } from 'react'
|
||||||
import { Formik } from 'formik'
|
import { Formik } from 'formik'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
@ -27,6 +27,10 @@ import FundStepper from './FundStepper'
|
|||||||
|
|
||||||
const { addGiverAndDonate } = LiquidPledging.methods
|
const { addGiverAndDonate } = LiquidPledging.methods
|
||||||
|
|
||||||
|
const NOT_SUBMITTED = 'Not Submitted'
|
||||||
|
const SUBMITTED = 'Submitted'
|
||||||
|
const CONFIRMED = 'Confirmed'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
const getProjectId = response => {
|
const getProjectId = response => {
|
||||||
const { events: { ProjectAdded: { returnValues: { idProject } } } } = response
|
const { events: { ProjectAdded: { returnValues: { idProject } } } } = response
|
||||||
@ -36,6 +40,20 @@ const addProjectSucessMsg = response => {
|
|||||||
const { events: { ProjectAdded: { returnValues: { idProject } } } } = response
|
const { events: { ProjectAdded: { returnValues: { idProject } } } } = response
|
||||||
return `Project created with ID of ${idProject}, will redirect to your new project page in a few seconds`
|
return `Project created with ID of ${idProject}, will redirect to your new project page in a few seconds`
|
||||||
}
|
}
|
||||||
|
const STEPS = ['Connect', 'Authorize Amount', 'Fund', 'Confirmation']
|
||||||
|
function stepperProgress(values, projectData, submissionState) {
|
||||||
|
console.log({values, projectData})
|
||||||
|
if (submissionState === CONFIRMED) return 4
|
||||||
|
if (submissionState === SUBMITTED) return 3
|
||||||
|
if (!projectData.account) return 0
|
||||||
|
const { manifest: { goalToken }, authorization } = projectData
|
||||||
|
const { amount } = values
|
||||||
|
const { chainReadibleFn } = getTokenByAddress(goalToken)
|
||||||
|
const weiAmount = amount ? chainReadibleFn(amount) : '0'
|
||||||
|
const isAuthorized = toBN(authorization).gte(toBN(weiAmount))
|
||||||
|
if (!isAuthorized) return 1
|
||||||
|
return 2
|
||||||
|
}
|
||||||
const optimisticUpdate = (client, pledgesInfo, weiAmount) => {
|
const optimisticUpdate = (client, pledgesInfo, weiAmount) => {
|
||||||
const { __typename } = pledgesInfo
|
const { __typename } = pledgesInfo
|
||||||
const updatedLifetimeReceived = toBN(weiAmount).add(toBN(pledgesInfo.lifetimeReceived)).toString()
|
const updatedLifetimeReceived = toBN(weiAmount).add(toBN(pledgesInfo.lifetimeReceived)).toString()
|
||||||
@ -51,6 +69,7 @@ const optimisticUpdate = (client, pledgesInfo, weiAmount) => {
|
|||||||
}
|
}
|
||||||
const SubmissionSection = ({ classes, projectData, projectId, profileData, startPolling, client }) => {
|
const SubmissionSection = ({ classes, projectData, projectId, profileData, startPolling, client }) => {
|
||||||
const { account, enableEthereum, openSnackBar, prices } = useContext(FundingContext)
|
const { account, enableEthereum, openSnackBar, prices } = useContext(FundingContext)
|
||||||
|
const [submissionState, setSubmissionState] = useState(NOT_SUBMITTED)
|
||||||
const { projectAge, projectAssets, manifest } = projectData
|
const { projectAge, projectAssets, manifest } = projectData
|
||||||
const { pledgesInfos, projectInfo } = profileData
|
const { pledgesInfos, projectInfo } = profileData
|
||||||
const pledgesInfo = pledgesInfos[0]
|
const pledgesInfo = pledgesInfos[0]
|
||||||
@ -80,11 +99,13 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start
|
|||||||
.send({gas: estimatedGas + 100})
|
.send({gas: estimatedGas + 100})
|
||||||
.on('transactionHash', (hash) => {
|
.on('transactionHash', (hash) => {
|
||||||
optimisticUpdate(client, pledgesInfo, weiAmount)
|
optimisticUpdate(client, pledgesInfo, weiAmount)
|
||||||
|
setSubmissionState(SUBMITTED)
|
||||||
openSnackBar('success', `Submitted funding request to chain. TX Hash: ${hash}`)
|
openSnackBar('success', `Submitted funding request to chain. TX Hash: ${hash}`)
|
||||||
})
|
})
|
||||||
.then(async res => {
|
.then(async res => {
|
||||||
console.log({res})
|
console.log({res})
|
||||||
startPolling(10000)
|
startPolling(10000)
|
||||||
|
setSubmissionState(CONFIRMED)
|
||||||
openSnackBar('success', 'Funding Confirmed')
|
openSnackBar('success', 'Funding Confirmed')
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
@ -110,6 +131,7 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start
|
|||||||
}) => {
|
}) => {
|
||||||
const { firstHalf, secondHalf, fullWidth } = classes
|
const { firstHalf, secondHalf, fullWidth } = classes
|
||||||
const usdValue = manifest ? convertTokenAmountUsd(manifest.goalToken, values.amount, prices) : 0
|
const usdValue = manifest ? convertTokenAmountUsd(manifest.goalToken, values.amount, prices) : 0
|
||||||
|
const activeStep = stepperProgress(values, projectData, submissionState)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className={classes.submissionRoot}>
|
<form onSubmit={handleSubmit} className={classes.submissionRoot}>
|
||||||
@ -182,7 +204,7 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start
|
|||||||
<div className={classes.amountText}>{getTokenLabel(manifest.goalToken)}</div>
|
<div className={classes.amountText}>{getTokenLabel(manifest.goalToken)}</div>
|
||||||
</div>
|
</div>
|
||||||
<Button type="submit" color="primary" variant="contained" className={classnames(classes.formButton)}>{isSubmitting ? 'Ethereum Submission In Progress' : buttonText}</Button>
|
<Button type="submit" color="primary" variant="contained" className={classnames(classes.formButton)}>{isSubmitting ? 'Ethereum Submission In Progress' : buttonText}</Button>
|
||||||
<FundStepper />
|
<FundStepper steps={STEPS} activeStep={activeStep} />
|
||||||
</div>}
|
</div>}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
@ -145,15 +145,8 @@ const useStyles = makeStyles(theme => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function getSteps() {
|
export default function CustomizedSteppers({ activeStep, steps }) {
|
||||||
return ['Connect', 'Authorize Amount', 'Fund', 'Confirmation'];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function CustomizedSteppers() {
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [activeStep, setActiveStep] = React.useState(1);
|
|
||||||
console.log({setActiveStep})
|
|
||||||
const steps = getSteps();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
|
@ -2,6 +2,7 @@ import { useState, useEffect, useMemo, useContext } from 'react'
|
|||||||
import { unnest } from 'ramda'
|
import { unnest } from 'ramda'
|
||||||
import { timeSinceBlock } from '../../utils/dates'
|
import { timeSinceBlock } from '../../utils/dates'
|
||||||
import { getFiles, getFilesWeb, ipfs, getFilesWebTheGraph } from '../../utils/ipfs'
|
import { getFiles, getFilesWeb, ipfs, getFilesWebTheGraph } from '../../utils/ipfs'
|
||||||
|
import { getAllowanceFromAddress } from '../../utils/currencies'
|
||||||
import { arrayToObject } from '../../utils/array'
|
import { arrayToObject } from '../../utils/array'
|
||||||
import { FundingContext } from '../../context'
|
import { FundingContext } from '../../context'
|
||||||
import { getDelegateProfiles } from '../../actions/profiles'
|
import { getDelegateProfiles } from '../../actions/profiles'
|
||||||
@ -110,12 +111,20 @@ const getProjectManifest = (data, assets) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getAuthorization(data, setState) {
|
||||||
|
if (!data.profile) return
|
||||||
|
const { profile: { projectInfo: { goalToken } } } = data
|
||||||
|
const allowance = await getAllowanceFromAddress(goalToken)
|
||||||
|
setState(allowance)
|
||||||
|
}
|
||||||
|
|
||||||
export function useProjectData(projectId, data) {
|
export function useProjectData(projectId, data) {
|
||||||
const [projectAge, setAge] = useState(null)
|
const [projectAge, setAge] = useState(null)
|
||||||
const [creator, setCreator] = useState(null)
|
const [creator, setCreator] = useState(null)
|
||||||
const [projectAssets, setAssets] = useState(null)
|
const [projectAssets, setAssets] = useState(null)
|
||||||
const [ipfsReady, setIpfsState] = useState(null)
|
const [ipfsReady, setIpfsState] = useState(null)
|
||||||
const [delegateProfiles, setDelegateProfiles] = useState(null)
|
const [delegateProfiles, setDelegateProfiles] = useState(null)
|
||||||
|
const [authorization, setAuthorization] = useState(0)
|
||||||
const { account, openSnackBar, syncWithRemote } = useContext(FundingContext)
|
const { account, openSnackBar, syncWithRemote } = useContext(FundingContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -138,10 +147,15 @@ export function useProjectData(projectId, data) {
|
|||||||
getProjectAssets(data, setAssets)
|
getProjectAssets(data, setAssets)
|
||||||
}, [ipfsReady, data])
|
}, [ipfsReady, data])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (account) getAuthorization(data, setAuthorization)
|
||||||
|
}, [account, data])
|
||||||
|
|
||||||
const manifest = useMemo(() => getProjectManifest(data, projectAssets), [data, projectAssets, projectId])
|
const manifest = useMemo(() => getProjectManifest(data, projectAssets), [data, projectAssets, projectId])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
|
authorization,
|
||||||
creator,
|
creator,
|
||||||
projectAge,
|
projectAge,
|
||||||
projectAssets,
|
projectAssets,
|
||||||
|
@ -70,7 +70,7 @@ class App extends React.Component {
|
|||||||
|
|
||||||
enableEthereum = async () => {
|
enableEthereum = async () => {
|
||||||
try {
|
try {
|
||||||
await await window.ethereum.enable()
|
await window.ethereum.enable()
|
||||||
const account = await web3.eth.getCoinbase()
|
const account = await web3.eth.getCoinbase()
|
||||||
this.setState({ account })
|
this.setState({ account })
|
||||||
this.web3Init()
|
this.web3Init()
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
/*global web3*/
|
||||||
import { memoizeWith, identity } from 'ramda'
|
import { memoizeWith, identity } from 'ramda'
|
||||||
import SNT from '../embarkArtifacts/contracts/SNT'
|
import SNT from '../embarkArtifacts/contracts/SNT'
|
||||||
import DAI from '../embarkArtifacts/contracts/DAI'
|
import DAI from '../embarkArtifacts/contracts/DAI'
|
||||||
import cDAI from '../embarkArtifacts/contracts/cDAI'
|
import cDAI from '../embarkArtifacts/contracts/cDAI'
|
||||||
import cETH from '../embarkArtifacts/contracts/cETH'
|
import cETH from '../embarkArtifacts/contracts/cETH'
|
||||||
|
import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging'
|
||||||
import { toEther, toWei, compoundWhole, compoundToChain } from './conversions'
|
import { toEther, toWei, compoundWhole, compoundToChain } from './conversions'
|
||||||
|
|
||||||
export const TOKEN_ICON_API = 'https://raw.githubusercontent.com/TrustWallet/tokens/master/images'
|
export const TOKEN_ICON_API = 'https://raw.githubusercontent.com/TrustWallet/tokens/master/images'
|
||||||
@ -16,7 +18,8 @@ export const currencies = [
|
|||||||
width: '2rem',
|
width: '2rem',
|
||||||
contract: SNT,
|
contract: SNT,
|
||||||
humanReadibleFn: toEther,
|
humanReadibleFn: toEther,
|
||||||
chainReadibleFn: toWei
|
chainReadibleFn: toWei,
|
||||||
|
getAllowance: () => getLpAllowance(SNT)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '0xf5dce57282a584d2746faf1593d3121fcac444dc',
|
value: '0xf5dce57282a584d2746faf1593d3121fcac444dc',
|
||||||
@ -25,7 +28,8 @@ export const currencies = [
|
|||||||
width: '2rem',
|
width: '2rem',
|
||||||
contract: cDAI,
|
contract: cDAI,
|
||||||
humanReadibleFn: compoundWhole,
|
humanReadibleFn: compoundWhole,
|
||||||
chainReadibleFn: compoundToChain
|
chainReadibleFn: compoundToChain,
|
||||||
|
getAllowance: () => getLpAllowance(cDAI)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5',
|
value: '0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5',
|
||||||
@ -34,7 +38,8 @@ export const currencies = [
|
|||||||
width: '2rem',
|
width: '2rem',
|
||||||
contract: cETH,
|
contract: cETH,
|
||||||
humanReadibleFn: compoundWhole,
|
humanReadibleFn: compoundWhole,
|
||||||
chainReadibleFn: compoundToChain
|
chainReadibleFn: compoundToChain,
|
||||||
|
getAllowance: () => getLpAllowance(cETH)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
value: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
||||||
@ -51,7 +56,8 @@ export const currencies = [
|
|||||||
width: '2rem',
|
width: '2rem',
|
||||||
contract: DAI,
|
contract: DAI,
|
||||||
humanReadibleFn: toEther,
|
humanReadibleFn: toEther,
|
||||||
chainReadibleFn: toWei
|
chainReadibleFn: toWei,
|
||||||
|
getAllowance: () => getLpAllowance(DAI)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -71,3 +77,16 @@ export const getFormattedPledgeAmount = pledge => {
|
|||||||
const { humanReadibleFn } = getTokenByAddress(pledge.token)
|
const { humanReadibleFn } = getTokenByAddress(pledge.token)
|
||||||
return humanReadibleFn(pledge.amount)
|
return humanReadibleFn(pledge.amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getAllowanceFromAddress = tokenAddress => {
|
||||||
|
const token = getTokenByAddress(tokenAddress)
|
||||||
|
return token.getAllowance()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLpAllowance = async contract => {
|
||||||
|
const { methods: { allowance } } = contract || SNT
|
||||||
|
const account = await web3.eth.getCoinbase()
|
||||||
|
const spender = LiquidPledging._address
|
||||||
|
const allowanceAmt = await allowance(account, spender).call()
|
||||||
|
return allowanceAmt
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user