diff --git a/src/components/projects/FundProject.jsx b/src/components/projects/FundProject.jsx index 7c08d86..d79f77d 100644 --- a/src/components/projects/FundProject.jsx +++ b/src/components/projects/FundProject.jsx @@ -1,4 +1,4 @@ -import React, { useContext, useMemo, useEffect } from 'react' +import React, { useContext, useState, useMemo, useEffect } from 'react' import { Formik } from 'formik' import { makeStyles } from '@material-ui/core/styles' import classnames from 'classnames' @@ -27,6 +27,10 @@ import FundStepper from './FundStepper' const { addGiverAndDonate } = LiquidPledging.methods +const NOT_SUBMITTED = 'Not Submitted' +const SUBMITTED = 'Submitted' +const CONFIRMED = 'Confirmed' + const useStyles = makeStyles(styles) const getProjectId = response => { const { events: { ProjectAdded: { returnValues: { idProject } } } } = response @@ -36,6 +40,20 @@ const addProjectSucessMsg = 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` } +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 { __typename } = pledgesInfo 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 { account, enableEthereum, openSnackBar, prices } = useContext(FundingContext) + const [submissionState, setSubmissionState] = useState(NOT_SUBMITTED) const { projectAge, projectAssets, manifest } = projectData const { pledgesInfos, projectInfo } = profileData const pledgesInfo = pledgesInfos[0] @@ -80,11 +99,13 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start .send({gas: estimatedGas + 100}) .on('transactionHash', (hash) => { optimisticUpdate(client, pledgesInfo, weiAmount) + setSubmissionState(SUBMITTED) openSnackBar('success', `Submitted funding request to chain. TX Hash: ${hash}`) }) .then(async res => { console.log({res}) startPolling(10000) + setSubmissionState(CONFIRMED) openSnackBar('success', 'Funding Confirmed') }) .catch(e => { @@ -110,6 +131,7 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start }) => { const { firstHalf, secondHalf, fullWidth } = classes const usdValue = manifest ? convertTokenAmountUsd(manifest.goalToken, values.amount, prices) : 0 + const activeStep = stepperProgress(values, projectData, submissionState) return (
@@ -182,7 +204,7 @@ const SubmissionSection = ({ classes, projectData, projectId, profileData, start
{getTokenLabel(manifest.goalToken)}
- + } ) diff --git a/src/components/projects/FundStepper.jsx b/src/components/projects/FundStepper.jsx index b733867..ae50090 100644 --- a/src/components/projects/FundStepper.jsx +++ b/src/components/projects/FundStepper.jsx @@ -145,15 +145,8 @@ const useStyles = makeStyles(theme => ({ }, })); -function getSteps() { - return ['Connect', 'Authorize Amount', 'Fund', 'Confirmation']; -} - -export default function CustomizedSteppers() { +export default function CustomizedSteppers({ activeStep, steps }) { const classes = useStyles(); - const [activeStep, setActiveStep] = React.useState(1); - console.log({setActiveStep}) - const steps = getSteps(); return (
diff --git a/src/components/projects/hooks.js b/src/components/projects/hooks.js index 1df71a5..99c3dbd 100644 --- a/src/components/projects/hooks.js +++ b/src/components/projects/hooks.js @@ -2,6 +2,7 @@ import { useState, useEffect, useMemo, useContext } from 'react' import { unnest } from 'ramda' import { timeSinceBlock } from '../../utils/dates' import { getFiles, getFilesWeb, ipfs, getFilesWebTheGraph } from '../../utils/ipfs' +import { getAllowanceFromAddress } from '../../utils/currencies' import { arrayToObject } from '../../utils/array' import { FundingContext } from '../../context' 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) { const [projectAge, setAge] = useState(null) const [creator, setCreator] = useState(null) const [projectAssets, setAssets] = useState(null) const [ipfsReady, setIpfsState] = useState(null) const [delegateProfiles, setDelegateProfiles] = useState(null) + const [authorization, setAuthorization] = useState(0) const { account, openSnackBar, syncWithRemote } = useContext(FundingContext) useEffect(() => { @@ -138,10 +147,15 @@ export function useProjectData(projectId, data) { getProjectAssets(data, setAssets) }, [ipfsReady, data]) + useEffect(() => { + if (account) getAuthorization(data, setAuthorization) + }, [account, data]) + const manifest = useMemo(() => getProjectManifest(data, projectAssets), [data, projectAssets, projectId]) return { account, + authorization, creator, projectAge, projectAssets, diff --git a/src/dapp.js b/src/dapp.js index 5141702..16c7c87 100644 --- a/src/dapp.js +++ b/src/dapp.js @@ -70,7 +70,7 @@ class App extends React.Component { enableEthereum = async () => { try { - await await window.ethereum.enable() + await window.ethereum.enable() const account = await web3.eth.getCoinbase() this.setState({ account }) this.web3Init() diff --git a/src/utils/currencies.js b/src/utils/currencies.js index 6c7b75c..5085431 100644 --- a/src/utils/currencies.js +++ b/src/utils/currencies.js @@ -1,8 +1,10 @@ +/*global web3*/ import { memoizeWith, identity } from 'ramda' import SNT from '../embarkArtifacts/contracts/SNT' import DAI from '../embarkArtifacts/contracts/DAI' import cDAI from '../embarkArtifacts/contracts/cDAI' import cETH from '../embarkArtifacts/contracts/cETH' +import LiquidPledging from '../embarkArtifacts/contracts/LiquidPledging' import { toEther, toWei, compoundWhole, compoundToChain } from './conversions' export const TOKEN_ICON_API = 'https://raw.githubusercontent.com/TrustWallet/tokens/master/images' @@ -16,7 +18,8 @@ export const currencies = [ width: '2rem', contract: SNT, humanReadibleFn: toEther, - chainReadibleFn: toWei + chainReadibleFn: toWei, + getAllowance: () => getLpAllowance(SNT) }, { value: '0xf5dce57282a584d2746faf1593d3121fcac444dc', @@ -25,7 +28,8 @@ export const currencies = [ width: '2rem', contract: cDAI, humanReadibleFn: compoundWhole, - chainReadibleFn: compoundToChain + chainReadibleFn: compoundToChain, + getAllowance: () => getLpAllowance(cDAI) }, { value: '0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5', @@ -34,7 +38,8 @@ export const currencies = [ width: '2rem', contract: cETH, humanReadibleFn: compoundWhole, - chainReadibleFn: compoundToChain + chainReadibleFn: compoundToChain, + getAllowance: () => getLpAllowance(cETH) }, { value: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', @@ -51,7 +56,8 @@ export const currencies = [ width: '2rem', contract: DAI, humanReadibleFn: toEther, - chainReadibleFn: toWei + chainReadibleFn: toWei, + getAllowance: () => getLpAllowance(DAI) } ] @@ -71,3 +77,16 @@ export const getFormattedPledgeAmount = pledge => { const { humanReadibleFn } = getTokenByAddress(pledge.token) 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 +}