import React, {useEffect, useState} from 'react'; import './wallet.scss'; import {useService} from '@xstate/react'; import {formatEther} from '@ethersproject/units'; import {Button, Heading, Flex, Text, Box, Link, Loader, Tooltip, Icon} from 'rimble-ui'; import {BN} from '@statechannels/wallet-core'; import {ApproveBudgetAndFundService} from '../workflows/approve-budget-and-fund'; import {track} from '../segment-analytics'; import {getAmountsFromBudget} from './selectors'; import {ETH_ASSET_HOLDER_ADDRESS, TARGET_NETWORK, FAUCET_LINK} from '../config'; interface Props { service: ApproveBudgetAndFundService; } export const ApproveBudgetAndFund = (props: Props) => { const [current, _send] = useService(props.service); const {budget} = current.context; const {playerAmount, hubAmount} = getAmountsFromBudget(budget); const send = ( event: | 'USER_APPROVES_BUDGET' | 'USER_REJECTS_BUDGET' | 'USER_APPROVES_RETRY' | 'USER_REJECTS_RETRY' ) => () => { track(event, {domain: current.context.budget.domain}); _send(event); }; // Sets a timer that expires after 1.5 minutes // Used to determine if we've timed out waiting for the hub let stateTimer; const [stateTimerExpired, setStateTimerExpired] = useState(false); useEffect(() => { setStateTimerExpired(false); stateTimer = setTimeout(() => setStateTimerExpired(true), 90_000 /* 1.5 min */); return () => { clearTimeout(stateTimer); }; }, [current]); const waitForSufficientFundsInit = ( App Budget Checking if your Metamask account has sufficient ETH ); const waitForSufficientFunds = ( App Budget You don't have enough ETH in your wallet! You'll need at least {formatEther(BN.from(playerAmount))} ETH in your Metamask wallet to fund the channel. You can get more ETH{' '} here. ); const waitForUserApproval = ({waiting}: {waiting: boolean} = {waiting: false}) => ( App Budget Approve budget? Send: {formatEther(BN.from(playerAmount))} ETH Receive: {formatEther(BN.from(hubAmount))} ETH {budget.domain} will manage these funds. You will deposit {formatEther(BN.from(playerAmount))} ETH into a channel. Our hub will also make a deposit. Cancel ); const waitForPreFS = ( Deposit funds Waiting for the hub to respond.

); const depositInit = ( Deposit funds Querying blockchain

); const depositWaitTurn = ( Deposit funds The hub is now depositing funds on-chain. This may take a moment. Click{' '} here {' '} to follow the progress on etherscan.

); const depositSubmitTransaction = ( Deposit funds Please approve the transaction in metamask ); const depositWaitMining = ({transactionId}: {transactionId: string}) => ( Deposit funds Waiting for your transaction to be mined. Click{' '} here {' '} to follow the progress on etherscan.

); const depositRetry = () => ( Deposit Funds Your deposit transaction failed. Do you want to retry? Cancel ); // in the current setup, the hub deposits first, so this should never be shown const depositFullyFunded = ( Deposit funds Waiting for hub to deposit

); const hubTimeout = ( Deposit Funds We haven't heard back from the hub in a bit so something might have gone wrong. You can click{' '} here {' '} to see the progress on etherscan or you can download your log files and reach out to us on{' '} {' '} github. ); if (current.matches('waitForUserApproval')) { return waitForUserApproval(); } else if (current.matches({waitForSufficientFunds: 'init'})) { return waitForSufficientFundsInit; } else if (current.matches({waitForSufficientFunds: 'waitForFunds'})) { return waitForSufficientFunds; } else if (current.matches('createLedger')) { return waitForSufficientFunds; } else if (current.matches('waitForPreFS')) { return waitForPreFS; } else if (current.matches({deposit: 'init'})) { return depositInit; } else if (current.matches({deposit: 'waitTurn'})) { if (stateTimerExpired) { return hubTimeout; } else { return depositWaitTurn; } } else if (current.matches({deposit: 'submitTransaction'})) { return depositSubmitTransaction; } else if (current.matches({deposit: 'waitMining'})) { return depositWaitMining(current.context); } else if (current.matches({deposit: 'retry'})) { return depositRetry(); } else if (current.matches({deposit: 'waitFullyFunded'})) { return depositFullyFunded; } else if (current.matches('createBudget')) { return depositFullyFunded; } else if (current.matches('done')) { // workflow hides ui, so user shouldn't ever see this return
Success! Returning to app..
; } else if (current.matches('failure')) { // workflow hides ui, so user shouldn't ever see this return
Failed :(. Returning to app..
; } else { return
Todo
; } };