diff --git a/packages/boba/gateway/src/actions/balanceAction.js b/packages/boba/gateway/src/actions/balanceAction.js index de70c0bec5..76a76d8522 100644 --- a/packages/boba/gateway/src/actions/balanceAction.js +++ b/packages/boba/gateway/src/actions/balanceAction.js @@ -81,3 +81,7 @@ export function fetchL2BalanceBOBA() { export function fetchUserAndL2LPBalanceBatch(tokenList) { return createAction('FETCH/USER/L2LP/BALANCE/BATCH', () => networkService.getL2UserAndLPBalanceBatch(tokenList)) } + +export function fetchExitFee() { + return createAction('FETCH/EXITFEE', () => networkService.getExitFeeFromBillingContract()) +} diff --git a/packages/boba/gateway/src/actions/nftAction.js b/packages/boba/gateway/src/actions/nftAction.js index a4fbb1d6ed..0212d3b9a4 100644 --- a/packages/boba/gateway/src/actions/nftAction.js +++ b/packages/boba/gateway/src/actions/nftAction.js @@ -40,7 +40,10 @@ export async function addNFT ( NFT ) { tokenID: NFT.tokenID, symbol: NFT.symbol, url: NFT.url, - meta: NFT.meta + meta: NFT.meta, + account: NFT.account, + network: NFT.network, + layer: NFT.layer } store.dispatch({ diff --git a/packages/boba/gateway/src/components/mainMenu/feeSwitcher/FeeSwitcher.js b/packages/boba/gateway/src/components/mainMenu/feeSwitcher/FeeSwitcher.js index 6124de2ccc..cd8d544a1d 100644 --- a/packages/boba/gateway/src/components/mainMenu/feeSwitcher/FeeSwitcher.js +++ b/packages/boba/gateway/src/components/mainMenu/feeSwitcher/FeeSwitcher.js @@ -22,7 +22,7 @@ import { selectAccountEnabled, selectBobaFeeChoice, selectLayer, - selectBobaPriceRatio, + //selectBobaPriceRatio, selectNetwork } from 'selectors/setupSelector' @@ -44,7 +44,7 @@ function FeeSwitcher() { const dispatch = useDispatch() const accountEnabled = useSelector(selectAccountEnabled()) const feeUseBoba = useSelector(selectBobaFeeChoice()) - const feePriceRatio = useSelector(selectBobaPriceRatio()) + //const feePriceRatio = useSelector(selectBobaPriceRatio()) const network = useSelector(selectNetwork()) const layer = useSelector(selectLayer()) @@ -59,8 +59,8 @@ function FeeSwitcher() { const dispatchSwitchFee = useCallback(async (targetFee) => { - console.log("balanceBOBA:",balanceBOBA) - console.log("balanceETH:",balanceETH) + //console.log("balanceBOBA:",balanceBOBA) + //console.log("balanceETH:",balanceETH) let tooSmallETH = false let tooSmallBOBA = false @@ -80,7 +80,7 @@ function FeeSwitcher() { } if (!balanceBOBA && !balanceETH) { - dispatch(openError('Wallet completely empty - please bridge in ETH or BOBA from L1')) + dispatch(openError('Wallet empty - please bridge in ETH or BOBA from L1')) return } @@ -95,8 +95,8 @@ function FeeSwitcher() { else if ( !feeUseBoba && targetFee === 'BOBA' ) { // change to BOBA if( tooSmallBOBA ) { - dispatch(openError('You cannot change the fee token to BOBA since your BOBA balance is below 3 BOBA. \ - If you change fee token now, you might get stuck. Please swap some ETH for BOBA first.')) + dispatch(openError(`You cannot change the fee token to BOBA since your BOBA balance is below 3 BOBA. + If you change fee token now, you might get stuck. Please swap some ETH for BOBA first.`)) } else { res = await dispatch(switchFee(targetFee)) } @@ -104,8 +104,8 @@ function FeeSwitcher() { else if (feeUseBoba && targetFee === 'ETH') { // change to ETH if( tooSmallETH ) { - dispatch(openError('You cannot change the fee token to ETH since your ETH balance is below 0.002 ETH. \ - If you change fee token now, you might get stuck. Please swap some BOBA for ETH first.')) + dispatch(openError(`You cannot change the fee token to ETH since your ETH balance is below 0.002 ETH. + If you change fee token now, you might get stuck. Please swap some BOBA for ETH first.`)) } else { res = await dispatch(switchFee(targetFee)) } diff --git a/packages/boba/gateway/src/components/select/Select.js b/packages/boba/gateway/src/components/select/Select.js index b1f2be5744..b61110cea3 100644 --- a/packages/boba/gateway/src/components/select/Select.js +++ b/packages/boba/gateway/src/components/select/Select.js @@ -17,7 +17,7 @@ import React from 'react'; import { Select as MuiSelect, MenuItem, useTheme } from '@mui/material'; import * as styles from './Select.module.scss'; import * as S from './Select.style'; -import { ArrowDropDownCircleOutlined, ArrowDropDownOutlined } from '@mui/icons-material'; +import { ArrowDropDownOutlined } from '@mui/icons-material'; function Select ({ label, diff --git a/packages/boba/gateway/src/components/walletpicker/WalletPicker.js b/packages/boba/gateway/src/components/walletpicker/WalletPicker.js index 8bdc359a17..e523b3df94 100644 --- a/packages/boba/gateway/src/components/walletpicker/WalletPicker.js +++ b/packages/boba/gateway/src/components/walletpicker/WalletPicker.js @@ -45,14 +45,14 @@ function WalletPicker({ const dispatchBootAccount = useCallback(() => { - console.log("Calling initializeAccount for:", network) + //console.log("Calling initializeAccount for:", network) if (!accountEnabled) initializeAccount() async function initializeAccount() { const initialized = await networkService.initializeAccount(network) - console.log(['initialized',initialized]) + //console.log(['initialized',initialized]) if (initialized === 'wrongnetwork') { dispatch(openModal('wrongNetworkModal')); diff --git a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStep.js b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStep.js index fa593f6b94..5a0949b7e3 100644 --- a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStep.js +++ b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStep.js @@ -43,16 +43,18 @@ import parse from 'html-react-parser' import BN from 'bignumber.js' -import { +import { fetchClassicExitCost, - fetchL2BalanceETH, - fetchL2BalanceBOBA, + fetchL2BalanceETH, + fetchL2BalanceBOBA, + fetchExitFee, } from 'actions/balanceAction' -import { +import { selectClassicExitCost, //estimated total cost of this exit selectL2BalanceETH, selectL2BalanceBOBA, + selectExitFee, } from 'selectors/balanceSelector' function DoExitStep({ handleClose, token }) { @@ -82,13 +84,15 @@ function DoExitStep({ handleClose, token }) { const feeUseBoba = useSelector(selectBobaFeeChoice()) const feePriceRatio = useSelector(selectBobaPriceRatio()) + const exitFee = useSelector(selectExitFee) + function setAmount(value) { const balance = Number(logAmount(token.balance, token.decimals)) const tooSmall = new BN(value).lte(new BN(0.0)) const tooBig = new BN(value).gt(new BN(max_Float)) - + setErrorString('') if (tooSmall || tooBig) { @@ -96,11 +100,11 @@ function DoExitStep({ handleClose, token }) { setValidValue(false) setValue(value) return false - } + } else if ( !feeUseBoba && // check is needed regardless of fee token choice - token.symbol === 'ETH' && - (Number(value) + feeETH) > balance) + token.symbol === 'ETH' && + (Number(value) + feeETH) > balance) { // insufficient ETH to cover the ETH amount plus gas // due to MetaMask issue, this is needed even if you are paying in ETH @@ -111,8 +115,8 @@ function DoExitStep({ handleClose, token }) { } else if ( feeUseBoba && // check is needed regardless of fee token choice - token.symbol === 'ETH' && - (Number(value) + feeETH) > balance) + token.symbol === 'ETH' && + (Number(value) + feeETH) > balance) { // insufficient ETH to cover the ETH amount plus gas // due to MetaMask issue, this is needed even if you are paying in ETH @@ -123,8 +127,8 @@ function DoExitStep({ handleClose, token }) { } else if ( feeUseBoba && - token.symbol === 'BOBA' && - (Number(value) + feeBOBA) > balance) + token.symbol === 'BOBA' && + (Number(value) + feeBOBA) > balance) { // insufficient BOBA to cover the BOBA amount plus gas setErrorString('Warning: BOBA amount + fees > balance') @@ -134,7 +138,7 @@ function DoExitStep({ handleClose, token }) { } else if ( !feeUseBoba && - feeETH > Number(feeBalanceETH)) + feeETH > Number(feeBalanceETH)) { // insufficient ETH to cover exit fees setErrorString('Warning: ETH balance too low.') @@ -144,7 +148,7 @@ function DoExitStep({ handleClose, token }) { } else if ( feeUseBoba && - feeETH > Number(feeBalanceETH)) + feeETH > Number(feeBalanceETH)) { // insufficient ETH to cover exit fees setErrorString('Warning: ETH balance too low. Even if you pay in BOBA, you still need to maintain a minimum ETH balance in your wallet.') @@ -154,7 +158,7 @@ function DoExitStep({ handleClose, token }) { } else if ( feeUseBoba && - feeBOBA > Number(feeBalanceBOBA)) + feeBOBA > Number(feeBalanceBOBA)) { // insufficient BOBA to cover exit fees setErrorString('Warning: BOBA balance too low') @@ -208,13 +212,14 @@ function DoExitStep({ handleClose, token }) { dispatch(fetchClassicExitCost(token.address)) dispatch(fetchL2BalanceETH()) dispatch(fetchL2BalanceBOBA()) + dispatch(fetchExitFee()) } }, [ token, dispatch ]) useEffect(() => { function estimateMax() { - + const safeCost = Number(cost) * 1.04 // 1.04 = safety margin on the cost console.log("ETH fees:", safeCost) console.log("BOBA fees:", safeCost * feePriceRatio) @@ -230,13 +235,13 @@ function DoExitStep({ handleClose, token }) { setMax_Float(balance - safeCost) else setMax_Float(0.0) - } + } else if (token.symbol === 'BOBA' && feeUseBoba) { if(balance - safeCost > 0.0) setMax_Float(balance - safeCost) else setMax_Float(0.0) - } + } else { setMax_Float(balance) } @@ -248,17 +253,17 @@ function DoExitStep({ handleClose, token }) { if(feeETH && Number(feeETH) > 0) { if(feeUseBoba) { - ETHstring = `Estimated gas (approval + exit): ${Number(feeBOBA).toFixed(4)} BOBA` + ETHstring = `Estimated gas (approval + exit): ${Number(feeBOBA).toFixed(4)} BOBA` } else { - ETHstring = `Estimated gas (approval + exit): ${Number(feeETH).toFixed(4)} ETH` + ETHstring = `Estimated gas (approval + exit): ${Number(feeETH).toFixed(4)} ETH` } } - // prohibit ExitAll when paying with the token that is to be exited + // prohibit ExitAll when paying with the token that is to be exited let allowExitall = true if(token.symbol === 'ETH') { allowExitall = false - } + } else if (token.symbol === 'BOBA' && feeUseBoba) { allowExitall = false } @@ -281,6 +286,7 @@ function DoExitStep({ handleClose, token }) { setValue_Wei_String(toWei_String(i.target.value, token.decimals)) }} onUseMax={(i)=>{//they want to use the maximum + console.log(i) setAmount(max_Float) //so the display value updates for the user setValue_Wei_String(token.balance.toString()) }} @@ -304,11 +310,15 @@ function DoExitStep({ handleClose, token }) { on L1. Your funds will be available on L1 in 7 days.`} )} - + {parse(ETHstring)} - + + + {parse(`Exit Fee: ${exitFee} BOBA`)} + + {errorString !== '' && {errorString} diff --git a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js index de4a578122..8d5b861241 100644 --- a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js +++ b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js @@ -45,7 +45,8 @@ import { fetchL1FeeRateN, fetchL2BalanceBOBA, fetchL2BalanceETH, - fetchL1LPLiquidity + fetchL1LPLiquidity, + fetchExitFee, } from 'actions/balanceAction' import { @@ -56,7 +57,8 @@ import { selectL1LPPendingString, selectL2BalanceBOBA, selectL2BalanceETH, - selectL1LPLiquidity + selectL1LPLiquidity, + selectExitFee, } from 'selectors/balanceSelector' import { @@ -104,9 +106,11 @@ function DoExitStepFast({ handleClose, token }) { const lpUnits = logAmount(LPBalance, token.decimals) const balanceSubPending = lpUnits - logAmount(LPPending, token.decimals) //subtract the in flight exits + const exitFee = useSelector(selectExitFee) + function setAmount(value) { - const balance = Number(logAmount(token.balance, token.decimals)) + const balance = Number(logAmount(token.balance, token.decimals)) const tooSmall = new BN(value).lte(new BN(0.0)) const tooBig = new BN(value).gt(new BN(max_Float)) @@ -118,9 +122,9 @@ function DoExitStepFast({ handleClose, token }) { setValidValue(false) setValue(value) return false - } + } else if ( - token.symbol === 'ETH' && + token.symbol === 'ETH' && (Number(value) + feeETH) > balance) { if(feeUseBoba) setErrorString('Warning: ETH amount + fees > balance. Even if you pay in BOBA, you still need to maintain a minimum ETH balance in your wallet') @@ -133,8 +137,8 @@ function DoExitStepFast({ handleClose, token }) { else if ( //pay BOBA, exit BOBA - check BOBA amount feeUseBoba && - token.symbol === 'BOBA' && - (Number(value) + feeBOBA) > balance) + token.symbol === 'BOBA' && + (Number(value) + feeBOBA) > balance) { // insufficient BOBA to cover the BOBA amount plus gas setErrorString('Warning: BOBA amount + fees > balance') @@ -145,7 +149,7 @@ function DoExitStepFast({ handleClose, token }) { else if ( // insufficient ETH to cover exit fees // it does not matter if you are paying in ETH or BOBA - feeETH > Number(feeBalanceETH)) + feeETH > Number(feeBalanceETH)) { // insufficient ETH to cover exit fees if(feeUseBoba) @@ -159,13 +163,13 @@ function DoExitStepFast({ handleClose, token }) { else if ( // insufficient BOBA to cover exit fees feeUseBoba && - feeBOBA > Number(feeBalanceBOBA)) + feeBOBA > Number(feeBalanceBOBA)) { setErrorString('Warning: BOBA balance too low to cover gas') setValidValue(false) setValue(value) return false - } + } else if (Number(LPRatio) < 0.1) { // not enough balance/liquidity ratio // we always want some balance for unstaking @@ -173,7 +177,7 @@ function DoExitStepFast({ handleClose, token }) { setValidValue(false) setValue(value) return false - } + } else if (Number(value) > Number(balanceSubPending) * 0.9) { //not enough absolute balance //we don't want one large bridge to wipe out all the balance @@ -200,7 +204,7 @@ function DoExitStepFast({ handleClose, token }) { async function doExit() { console.log("Amount to exit:", value_Wei_String) - + let res = await dispatch( depositL2LP( token.address, @@ -231,6 +235,7 @@ function DoExitStepFast({ handleClose, token }) { dispatch(fetchFastExitCost(token.address)) dispatch(fetchL2BalanceETH()) dispatch(fetchL2BalanceBOBA()) + dispatch(fetchExitFee()) } // to clean up state and fix the // error in console for max state update. @@ -258,9 +263,9 @@ function DoExitStepFast({ handleClose, token }) { useEffect(() => { function estimateMax() { - + const safeCost = Number(cost) * 1.04 // 1.04 = safety margin on the cost - + //console.log("ETH fees:", safeCost) //console.log("BOBA fees:", safeCost * feePriceRatio) @@ -275,13 +280,13 @@ function DoExitStepFast({ handleClose, token }) { setMax_Float(balance - safeCost) else setMax_Float(0.0) - } + } else if (token.symbol === 'BOBA' && feeUseBoba) { if(balance - safeCost > 0.0) setMax_Float(balance - safeCost) else setMax_Float(0.0) - } + } else { setMax_Float(balance) } @@ -300,17 +305,17 @@ function DoExitStepFast({ handleClose, token }) { let ETHstring = '' if(feeETH && Number(feeETH) > 0) { if(feeUseBoba) { - ETHstring = `Estimated gas (approval + exit): ${Number(feeBOBA).toFixed(4)} BOBA` + ETHstring = `Estimated gas (approval + exit): ${Number(feeBOBA).toFixed(4)} BOBA` } else { - ETHstring = `Estimated gas (approval + exit): ${Number(feeETH).toFixed(4)} ETH` + ETHstring = `Estimated gas (approval + exit): ${Number(feeETH).toFixed(4)} ETH` } } - // prohibit ExitAll when paying with the token that is to be exited + // prohibit ExitAll when paying with the token that is to be exited let allowExitall = true if(token.symbol === 'ETH') { allowExitall = false - } + } else if (token.symbol === 'BOBA' && feeUseBoba) { allowExitall = false } @@ -328,9 +333,9 @@ function DoExitStepFast({ handleClose, token }) { - In most cases, a fast exit takes less than 20 minutes. - However, if Ethereum is congested, it can take as long as 3 hours. - The amount input window will block transactions that are likely to fail. + In most cases, a fast exit takes less than 20 minutes. + However, if Ethereum is congested, it can take as long as 3 hours. + The amount input window will block transactions that are likely to fail. {max_Float > 0.0 && @@ -376,6 +381,10 @@ function DoExitStepFast({ handleClose, token }) { {parse(ETHstring)} + + {parse(`Exit Fee: ${exitFee} BOBA`)} + + {errorString !== '' && {errorString} diff --git a/packages/boba/gateway/src/containers/wallet/Wallet.js b/packages/boba/gateway/src/containers/wallet/Wallet.js index 6844678c63..7dcf29b3d8 100644 --- a/packages/boba/gateway/src/containers/wallet/Wallet.js +++ b/packages/boba/gateway/src/containers/wallet/Wallet.js @@ -5,7 +5,6 @@ import Button from 'components/button/Button' import { Circle, Info } from "@mui/icons-material" import { Box, CircularProgress, Icon, Typography } from '@mui/material' -import Link from 'components/icons/LinkIcon' import { switchChain, getETHMetaTransaction } from 'actions/setupAction' import { openAlert, openError, setActiveHistoryTab, setPage as setPageAction } from 'actions/uiAction' @@ -19,7 +18,6 @@ import * as S from './wallet.styles' import { selectAccountEnabled, selectLayer, - selectBobaFeeChoice, selectNetwork, } from "selectors/setupSelector" @@ -50,8 +48,6 @@ function Wallet() { const accountEnabled = useSelector(selectAccountEnabled()) const network = useSelector(selectNetwork()) - const feeUseBoba = useSelector(selectBobaFeeChoice()) - const unorderedTransactions = useSelector(selectTransactions, isEqual) const orderedTransactions = orderBy(unorderedTransactions, i => i.timeStamp, 'desc') @@ -142,9 +138,9 @@ function Wallet() { const handleSwitch = (l) => { if (l === 'Token') { - setPage('Token'); + setPage('Token') } else if (l === 'NFT') { - setPage('NFT'); + setPage('NFT') } } @@ -154,9 +150,9 @@ function Wallet() { if (res) dispatch(openAlert('Emergency Swap submitted')) } - console.log("layer:", layer) - console.log("tooSmallETH:", tooSmallETH) - console.log("network:", network) + //console.log("layer:", layer) + //console.log("tooSmallETH:", tooSmallETH) + //console.log("network:", network) return ( diff --git a/packages/boba/gateway/src/containers/wallet/nft/Nft.js b/packages/boba/gateway/src/containers/wallet/nft/Nft.js index b35a3f0750..39b55bf4b5 100644 --- a/packages/boba/gateway/src/containers/wallet/nft/Nft.js +++ b/packages/boba/gateway/src/containers/wallet/nft/Nft.js @@ -16,8 +16,6 @@ import AlertIcon from 'components/icons/AlertIcon' import BobaGlassIcon from 'components/icons/BobaGlassIcon' import Copy from 'components/copy/Copy' -import truncate from 'truncate-middle' - class Nft extends React.Component { constructor(props) { @@ -102,6 +100,9 @@ class Nft extends React.Component { networkService.addNFT(this.state.contractAddress, this.state.tokenID) } + // async fetchMyMonsters() { + // networkService.fetchMyMonsters() + // } render() { @@ -111,8 +112,6 @@ class Nft extends React.Component { tokenID, loading, netLayer, - monsterInfo, - monsterNumber } = this.state if (!netLayer) { @@ -187,6 +186,17 @@ class Nft extends React.Component { + {/* + + */} { + let approval = networkService.estimateApprove() + console.log("GasEstimateApprove:",approval) + } + + const debug = false + if (!accountEnabled) { return ( @@ -101,6 +111,15 @@ function TokenPage() { >Oolongswap + {debug && + + } } diff --git a/packages/boba/gateway/src/reducers/balanceReducer.js b/packages/boba/gateway/src/reducers/balanceReducer.js index b01b398e7e..aa42232101 100644 --- a/packages/boba/gateway/src/reducers/balanceReducer.js +++ b/packages/boba/gateway/src/reducers/balanceReducer.js @@ -37,15 +37,16 @@ const initialState = { l2lpETHLiquidity: '', gas: {}, userAndL2LPBlanceBatch: {}, + exitFee: '', } function balanceReducer(state = initialState, action) { switch (action.type) { case 'BALANCE/GET/SUCCESS': const { layer1, layer2 } = action.payload - return { - ...state, - layer1, + return { + ...state, + layer1, layer2 } case 'GAS/GET/SUCCESS': @@ -163,6 +164,11 @@ function balanceReducer(state = initialState, action) { ...state, userAndL2LPBlanceBatch: action.payload } + case 'FETCH/EXITFEE/SUCCESS': + return { + ...state, + exitFee: action.payload + } case 'BALANCE/L1/RESET': return { ...state, diff --git a/packages/boba/gateway/src/selectors/balanceSelector.js b/packages/boba/gateway/src/selectors/balanceSelector.js index 167477953a..7e55567591 100644 --- a/packages/boba/gateway/src/selectors/balanceSelector.js +++ b/packages/boba/gateway/src/selectors/balanceSelector.js @@ -100,3 +100,7 @@ export function selectL2BalanceBOBA (state) { export function selectUserAndL2LPBalanceBatch (state) { return state.balance.userAndL2LPBlanceBatch } + +export function selectExitFee (state) { + return state.balance.exitFee +} diff --git a/packages/boba/gateway/src/services/graphQLService.js b/packages/boba/gateway/src/services/graphQLService.js index c2007b1b2c..8dda1a6594 100644 --- a/packages/boba/gateway/src/services/graphQLService.js +++ b/packages/boba/gateway/src/services/graphQLService.js @@ -29,6 +29,7 @@ class GraphQLService { -H "Content-Type: application/json" \ -d '{"query":"{ governorProposalCreateds {proposalId values description proposer}}"}' \ https://api.thegraph.com/subgraphs/name/bobanetwork/boba-l2-subgraph + */ const client = new apollo.ApolloClient({ @@ -42,6 +43,38 @@ class GraphQLService { return await client.query({ query }) } + + async queryMonsterTransfer() { + + const query = apollo.gql(`query { turingMonstersTransferEvents { to from tokenId } }`) + + /* + curl -g -X POST \ + -H "Content-Type: application/json" \ + -d '{"query":"{ turingMonstersTransferEvents { to from tokenId }}"}' \ + https://api.thegraph.com/subgraphs/name/bobanetwork/boba-l2-subgraph + + curl -g -X POST \ + -H "Content-Type: application/json" \ + -d '{"query":"{ turingMonstersTransferEvents { to from tokenId }}"}' \ + https://graph.rinkeby.boba.network/subgraphs/name/boba/Bridges + */ + const client = new apollo.ApolloClient({ + uri: this.getBridgeEndpoint(), + link: new apollo.HttpLink({ + uri: this.getBridgeEndpoint(), + fetch + }), + cache: new apollo.InMemoryCache() + }) + + return await client.query({ + query, + variables : { + to: '0x4161aEf7ac9F8772B83Cda1E5F054ADe308d9049' + } + }) + } } const graphQLService = new GraphQLService() diff --git a/packages/boba/gateway/src/services/networkService.js b/packages/boba/gateway/src/services/networkService.js index 334cbf1868..fafe9661d0 100644 --- a/packages/boba/gateway/src/services/networkService.js +++ b/packages/boba/gateway/src/services/networkService.js @@ -53,7 +53,7 @@ import L2ERC20Json from '@eth-optimism/contracts/artifacts/contracts/standards/L import OVM_GasPriceOracleJson from '@eth-optimism/contracts/artifacts/contracts/L2/predeploys/OVM_GasPriceOracle.sol/OVM_GasPriceOracle.json' // Boba contracts -import DiscretionaryExitBurnJson from '@boba/contracts/artifacts/contracts/DiscretionaryExitBurn.sol/DiscretionaryExitBurn.json' +import DiscretionaryExitFeeJson from '@boba/contracts/artifacts/contracts/DiscretionaryExitFee.sol/DiscretionaryExitFee.json' import L1LPJson from '@boba/contracts/artifacts/contracts/LP/L1LiquidityPool.sol/L1LiquidityPool.json' import L2LPJson from '@boba/contracts/artifacts/contracts/LP/L2LiquidityPool.sol/L2LiquidityPool.json' import L2SaveJson from '@boba/contracts/artifacts/contracts/BobaFixedSavings.sol/BobaFixedSavings.json' @@ -61,6 +61,7 @@ import L2ERC721Json from '@boba/contracts/artifacts/contracts/standards/L2Standa import Boba from "@boba/contracts/artifacts/contracts/DAO/governance-token/BOBA.sol/BOBA.json" import GovernorBravoDelegate from "@boba/contracts/artifacts/contracts/DAO/governance/GovernorBravoDelegate.sol/GovernorBravoDelegate.json" import GovernorBravoDelegator from "@boba/contracts/artifacts/contracts/DAO/governance/GovernorBravoDelegator.sol/GovernorBravoDelegator.json" +import L2BillingContractJson from "@boba/contracts/artifacts/contracts/L2BillingContract.sol/L2BillingContract.json" //special one-off locations import L1ERC20Json from '../deployment/contracts/L1ERC20.json' @@ -116,6 +117,8 @@ if (process.env.REACT_APP_CHAIN === 'rinkeby') { } let allTokens = {} +const benchmarkAccount = '0x4161aEf7ac9F8772B83Cda1E5F054ADe308d9049' + class NetworkService { constructor() { @@ -647,9 +650,13 @@ class NetworkService { if (!(await this.getAddressCached(addresses, 'Proxy__L1CrossDomainMessenger', 'L1MessengerAddress'))) return if (!(await this.getAddressCached(addresses, 'Proxy__L1CrossDomainMessengerFast', 'L1FastMessengerAddress'))) return if (!(await this.getAddressCached(addresses, 'Proxy__L1StandardBridge', 'L1StandardBridgeAddress'))) return - if (!(await this.getAddressCached(addresses, 'DiscretionaryExitBurn', 'DiscretionaryExitBurn'))) return if (!(await this.getAddressCached(addresses, 'Proxy__BobaFixedSavings', 'BobaFixedSavings'))) return if (!(await this.getAddressCached(addresses, 'Proxy__Boba_GasPriceOracle', 'Boba_GasPriceOracle'))) return + //if (!(await this.getAddressCached(addresses, 'DiscretionaryExitFee', 'DiscretionaryExitFee'))) return + + // not critical + this.getAddressCached(addresses, 'DiscretionaryExitFee', 'DiscretionaryExitFee') + console.log("DiscretionaryExitFee:",allAddresses.DiscretionaryExitFee) // not critical this.getAddressCached(addresses, 'BobaAirdropL1', 'BobaAirdropL1') @@ -1206,10 +1213,23 @@ class NetworkService { } } + async fetchMyMonsters() { + + // let monsterList = await GraphQLService.queryMonsterTransfer() + // console.log("monsterList:",monsterList) + // this returns too many events to be directly useful + + // for (let i = 0; i < totalProposals; i++) { + // const proposalRaw = descriptionList.data.governorProposalCreateds[i] + // if(typeof(proposalRaw) === 'undefined') continue + // let proposalID = proposalRaw.proposalId + // //this is a number such as 2 + // let proposalData = await delegateCheck.proposals(proposalID) + } + async checkMonster() { const NFTs = getNFTs() - //console.log("NFTs:",NFTs) let validMonsters = [] try { @@ -1222,12 +1242,11 @@ class NetworkService { const monsterBalance = await contract.balanceOf(this.account) - let monsterType = 0 let topMagic = 0 let topTop = 0 if(NFTs && Number(monsterBalance) > 0) { - for (const [key, value] of Object.entries(NFTs)) { + for (const [ value ] of Object.entries(NFTs)) { //console.log(`${key}: ${value.name}`) if(value.name === 'TuringMonster') { const owner = await contract.ownerOf(value.tokenID) @@ -1254,7 +1273,6 @@ class NetworkService { validMonsters.push({monsterType: 'crowned wizard'}) } - //console.log("adding monster info:",validMonsters) await addMonster( validMonsters ) } @@ -1268,6 +1286,7 @@ class NetworkService { } + /* This is for manually adding NFTs */ async addNFT( address, tokenID ) { try { @@ -1295,7 +1314,10 @@ class NetworkService { tokenID, symbol: nftSymbol, url, - meta + meta, + account: this.account, + network: this.networkGateway, + layer: this.L1orL2 } await addNFT( NFT ) @@ -2246,32 +2268,62 @@ class NetworkService { updateSignatureStatus_exitTRAD(false) try { + + const L2BillingContract = new ethers.Contract( + allAddresses.Proxy__BobaBillingContract, + L2BillingContractJson.abi, + this.L2Provider, + ) + let BobaApprovalAmount = await L2BillingContract.exitFee() + //now coming in as a value_Wei_String const value = BigNumber.from(value_Wei_String) const allowance = await this.checkAllowance( currencyAddress, - allAddresses.DiscretionaryExitBurn + allAddresses.DiscretionaryExitFee ) - //no need to approve L2 ETH - if( currencyAddress !== allAddresses.L2_ETH_Address && allowance.lt(value) ) { + const BobaAllowance = await this.checkAllowance( + allAddresses.TK_L2BOBA, + allAddresses.DiscretionaryExitFee + ) + + if (utils.getAddress(currencyAddress) === utils.getAddress(allAddresses.TK_L2BOBA)) { + BobaApprovalAmount = BobaApprovalAmount.add(value) + } + + // Should approve BOBA + if ( BobaAllowance.lt(BobaApprovalAmount) ) { const res = await this.approveERC20( - value_Wei_String, + BobaApprovalAmount, + allAddresses.TK_L2BOBA, + allAddresses.DiscretionaryExitFee + ) + if (!res) return false + } + + // Should approve other tokens + if( currencyAddress !== allAddresses.L2_ETH_Address && + utils.getAddress(currencyAddress) !== utils.getAddress(allAddresses.TK_L2BOBA) && + allowance.lt(value) + ) { + const res = await this.approveERC20( + value, currencyAddress, - allAddresses.DiscretionaryExitBurn + allAddresses.DiscretionaryExitFee ) if (!res) return false } - const DiscretionaryExitBurnContract = new ethers.Contract( - allAddresses.DiscretionaryExitBurn, - DiscretionaryExitBurnJson.abi, + const DiscretionaryExitFeeContract = new ethers.Contract( + allAddresses.DiscretionaryExitFee, + DiscretionaryExitFeeJson.abi, this.provider.getSigner() ) - console.log("DiscretionaryExitBurnContract",DiscretionaryExitBurnContract) + console.log("DiscretionaryExitFeeContract",DiscretionaryExitFeeContract) - const tx = await DiscretionaryExitBurnContract.burnAndWithdraw( + const tx = await DiscretionaryExitFeeContract.payAndWithdraw( currencyAddress, value_Wei_String, this.L1GasLimit, @@ -2317,22 +2369,22 @@ class NetworkService { ) const tx = await ERC20Contract.populateTransaction.approve( - allAddresses.DiscretionaryExitBurn, + allAddresses.DiscretionaryExitFee, utils.parseEther('1.0') ) - const approvalGas_BN = await this.L2Provider.estimateGas(tx) + const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: benchmarkAccount}) approvalCost_BN = approvalGas_BN.mul(gasPrice) console.log("Approve cost in ETH:", utils.formatEther(approvalCost_BN)) } - const DiscretionaryExitBurnContract = new ethers.Contract( - allAddresses.DiscretionaryExitBurn, - DiscretionaryExitBurnJson.abi, + const DiscretionaryExitFeeContract = new ethers.Contract( + allAddresses.DiscretionaryExitFee, + DiscretionaryExitFeeJson.abi, this.provider.getSigner() ) - const tx2 = await DiscretionaryExitBurnContract.populateTransaction.burnAndWithdraw( + const tx2 = await DiscretionaryExitFeeContract.populateTransaction.payAndWithdraw( allAddresses.L2_ETH_Address, utils.parseEther('0.00001'), this.L1GasLimit, @@ -2340,7 +2392,7 @@ class NetworkService { { value: utils.parseEther('0.00001') } ) - const gas_BN = await this.L2Provider.estimateGas(tx2) + const gas_BN = await this.L2Provider.estimateGas({...tx2, from: benchmarkAccount}) console.log("Classical exit gas", gas_BN.toString()) const cost_BN = gas_BN.mul(gasPrice) @@ -2667,8 +2719,6 @@ class NetworkService { async liquidityEstimate(currency) { - const benchmarkAccount = '0x4161aEf7ac9F8772B83Cda1E5F054ADe308d9049' - let otherField = { from: benchmarkAccount } @@ -3082,7 +3132,7 @@ class NetworkService { utils.parseEther('1.0') ) - const approvalGas_BN = await this.L2Provider.estimateGas(tx) + const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: benchmarkAccount}) approvalCost_BN = approvalGas_BN.mul(gasPrice) console.log("Approve cost in ETH:", utils.formatEther(approvalCost_BN)) } @@ -3097,7 +3147,7 @@ class NetworkService { currencyAddress === allAddresses.L2_ETH_Address ? { value : '1'} : {} ) - const depositGas_BN = await this.L2Provider.estimateGas(tx2) + const depositGas_BN = await this.L2Provider.estimateGas({...tx2, from: benchmarkAccount}) let l1SecurityFee = BigNumber.from('0') if (this.networkGateway === 'mainnet') { @@ -3231,10 +3281,33 @@ class NetworkService { balance_BN = await this.L2Provider.getBalance(this.account) } + const L2BillingContract = new ethers.Contract( + allAddresses.Proxy__BobaBillingContract, + L2BillingContractJson.abi, + this.L2Provider, + ) + let BobaApprovalAmount = await L2BillingContract.exitFee() + + const BobaAllowance = await this.checkAllowance( + allAddresses.TK_L2BOBA, + allAddresses.L2LPAddress, + ) + try { - //console.log("Address:",currencyAddress) - if( currencyAddress !== allAddresses.L2_ETH_Address ) { + // Approve BOBA first + if (BobaAllowance.lt(BobaApprovalAmount)) { + const approveStatus = await this.approveERC20( + BobaApprovalAmount, + allAddresses.TK_L2BOBA, + allAddresses.L2LPAddress + ) + if (!approveStatus) return false + } + // Approve other tokens + if( currencyAddress !== allAddresses.L2_ETH_Address && + utils.getAddress(currencyAddress) !== utils.getAddress(allAddresses.TK_L2BOBA) + ) { const L2ERC20Contract = new ethers.Contract( currencyAddress, L2ERC20Json.abi, @@ -3380,9 +3453,36 @@ class NetworkService { console.log("depositL2LP currencyAddress",currencyAddress) + const L2BillingContract = new ethers.Contract( + allAddresses.Proxy__BobaBillingContract, + L2BillingContractJson.abi, + this.L2Provider, + ) + let BobaApprovalAmount = await L2BillingContract.exitFee() + + const BobaAllowance = await this.checkAllowance( + allAddresses.TK_L2BOBA, + allAddresses.L2LPAddress, + ) + try { + // Approve BOBA first + if (utils.getAddress(currencyAddress) === utils.getAddress(allAddresses.TK_L2BOBA)) { + BobaApprovalAmount = BobaApprovalAmount.add(BigNumber.from(value_Wei_String)) + } + if (BobaAllowance.lt(BobaApprovalAmount)) { + const approveStatus = await this.approveERC20( + BobaApprovalAmount, + allAddresses.TK_L2BOBA, + allAddresses.L2LPAddress + ) + if (!approveStatus) return false + } - if( currencyAddress !== allAddresses.L2_ETH_Address ) { + // Approve other tokens + if( currencyAddress !== allAddresses.L2_ETH_Address && + utils.getAddress(currencyAddress) !== utils.getAddress(allAddresses.TK_L2BOBA) + ) { const L2ERC20Contract = new ethers.Contract( currencyAddress, @@ -3657,19 +3757,6 @@ class NetworkService { const delegateCheck = await this.delegateContract.attach(allAddresses.GovernorBravoDelegator) -/* - // for text only proposals, set target to a null address - const addresses = ['0x000000000000000000000000000000000000dEaD'] // the address of the contract where the function will be called - const values = [0] // the eth necessary to send to the contract above - const signatures = [''] // the function that will carry out the proposal - - const calldatas = [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - ] - - const description = '# Text only proposal' // the description of the proposal - */ - if( payload.action === 'text-proposal' ) { address = ['0x000000000000000000000000000000000000dEaD'] description = payload.text.slice(0, 252) //100+150+2 @@ -3909,25 +3996,48 @@ class NetworkService { this.account, allAddresses.BobaFixedSavings ) - console.log("Allowance", allowance_BN.toString()) + console.log("Allowance:", allowance_BN.toString()) let depositAmount_BN = BigNumber.from(value_Wei_String) - console.log("Deposit", depositAmount_BN) + console.log("Deposit:", depositAmount_BN) - if (depositAmount_BN.gt(allowance_BN)) { - console.log("Need to approve YES:", depositAmount_BN) - const approveStatus = await this.BobaContract + try { + if (depositAmount_BN.gt(allowance_BN)) { + console.log("Need to approve YES:", depositAmount_BN) + const approveStatus = await this.BobaContract + .connect(this.provider.getSigner()) + .approve( + allAddresses.BobaFixedSavings, + value_Wei_String + ) + const TX = await approveStatus.wait() + console.log("approveStatus:", TX) + } + else { + console.log("Allowance is sufficient:", allowance_BN.toString(), depositAmount_BN.toString()) + } + } catch (error) { + console.log("NS: addFS_Savings approve error:", error) + return error + } + + allowance_BN = await this.BobaContract .connect(this.provider.getSigner()) - .approve( - allAddresses.BobaFixedSavings, - value_Wei_String + .allowance( + this.account, + allAddresses.BobaFixedSavings ) - await approveStatus.wait() - if (!approveStatus) return false + console.log("Updated Allowance:", allowance_BN.toString()) + + if (depositAmount_BN.gt(allowance_BN)) { + console.log("Allowance still too small:", allowance_BN.toString(), depositAmount_BN.toString()) } else { - console.log("Allowance is sufficient:", allowance_BN.toString(), depositAmount_BN.toString()) + console.log("Allowance is now sufficient:", allowance_BN.toString(), depositAmount_BN.toString()) } + console.log("allAddresses.BobaFixedSavings", allAddresses.BobaFixedSavings) + console.log("FixedSavings.address", FixedSavings.address) + const TX = await FixedSavings.stake(value_Wei_String) await TX.wait() return TX @@ -4049,6 +4159,71 @@ class NetworkService { } } + async estimateApprove() { + + const approvalAmount = utils.parseEther('10.0') + let allowance_BN = null + let approveStatus = null + + if(allAddresses.hasOwnProperty('BobaFixedSavings')) { + allowance_BN = await this.BobaContract + .connect(this.provider.getSigner()) + .allowance( + this.account, + allAddresses.BobaFixedSavings + ) + console.log("Fixed Savings Allowance", allowance_BN.toString()) + + approveStatus = await this.BobaContract + .connect(this.provider.getSigner()) + .approve( + allAddresses.BobaFixedSavings, + approvalAmount + ) + await approveStatus.wait() + console.log("Fixed Savings Approval", approveStatus) + } + + if(allAddresses.hasOwnProperty('DiscretionaryExitFee')) { + allowance_BN = await this.BobaContract + .connect(this.provider.getSigner()) + .allowance( + this.account, + allAddresses.DiscretionaryExitFee + ) + console.log("DiscretionaryExitFee Allowance", allowance_BN.toString()) + + approveStatus = await this.BobaContract + .connect(this.provider.getSigner()) + .approve( + allAddresses.DiscretionaryExitFee, + approvalAmount + ) + await approveStatus.wait() + console.log("DiscretionaryExitFee Approval", approveStatus) + } + + if(allAddresses.hasOwnProperty('L2LPAddress')) { + allowance_BN = await this.BobaContract + .connect(this.provider.getSigner()) + .allowance( + this.account, + allAddresses.L2LPAddress + ) + console.log("L2LP", allowance_BN.toString()) + + approveStatus = await this.BobaContract + .connect(this.provider.getSigner()) + .approve( + allAddresses.L2LPAddress, + approvalAmount + ) + await approveStatus.wait() + console.log("L2LP", approveStatus) + } + + } + async getFS_Info() { if(this.account === null) { @@ -4166,6 +4341,18 @@ class NetworkService { } return payload } + + /***********************************************/ + /***** Exit fee *****/ + /***********************************************/ + async getExitFeeFromBillingContract() { + const L2BillingContract = new ethers.Contract( + allAddresses.Proxy__BobaBillingContract, + L2BillingContractJson.abi, + this.L2Provider, + ) + return ethers.utils.formatEther(await L2BillingContract.exitFee()) + } } const networkService = new NetworkService() diff --git a/packages/boba/subgraph/README.md b/packages/boba/subgraph/README.md index 3af5df72bb..71b2015899 100644 --- a/packages/boba/subgraph/README.md +++ b/packages/boba/subgraph/README.md @@ -1,5 +1,19 @@ # Boba Network Subgraphs +Please us the offical hosted service + +https://thegraph.com/hosted-service/subgraph/bobanetwork/boba-l2-subgraph?query=Example%20query + +## Legacy/Outdated Documention + +OUTDATED + +OUTDATED + +OUTDATED + +OUTDATED + These subgraphs index the **StandardBridge**, the **LiquidityPool**, and the **Boba DAO** contracts. ## Requirements