diff --git a/packages/omgx/wallet-frontend/src/actions/networkAction.js b/packages/omgx/wallet-frontend/src/actions/networkAction.js
index 06b5d63f663ff..57c38df38bc08 100644
--- a/packages/omgx/wallet-frontend/src/actions/networkAction.js
+++ b/packages/omgx/wallet-frontend/src/actions/networkAction.js
@@ -60,7 +60,15 @@ export function depositL2LP(token, value) {
)
}
-//DEPOSIT ETH
+//SWAP RELATED - Depositing into the L2LP triggers the swap-exit - variant of depositL2LP
+//that handles Exit All
+export function fastExitAll(token) {
+ return createAction('EXIT/CREATE', () =>
+ networkService.fastExitAll(token)
+ )
+}
+
+//CLASSICAL DEPOSIT ETH
export function depositETHL2(value) {
return createAction('DEPOSIT/CREATE', () => {
return networkService.depositETHL2(value)
diff --git a/packages/omgx/wallet-frontend/src/components/input/Input.js b/packages/omgx/wallet-frontend/src/components/input/Input.js
index 01968593e72fb..dfeba3713052e 100644
--- a/packages/omgx/wallet-frontend/src/components/input/Input.js
+++ b/packages/omgx/wallet-frontend/src/components/input/Input.js
@@ -41,6 +41,9 @@ function Input({
variant,
newStyle = false,
allowUseAll = false,
+ allowExitAll = false,
+ onExitAll,
+ loading,
}) {
async function handlePaste() {
@@ -104,7 +107,6 @@ function Input({
Max Amount: {Number(maxValue).toFixed(3)}
-
{allowUseAll && (
)}
+ {allowExitAll && (
+
+
+
+ )}
)}
{paste && (
diff --git a/packages/omgx/wallet-frontend/src/components/input/Input.styles.js b/packages/omgx/wallet-frontend/src/components/input/Input.styles.js
index 6a333d02a1247..6f6cc74d5117c 100644
--- a/packages/omgx/wallet-frontend/src/components/input/Input.styles.js
+++ b/packages/omgx/wallet-frontend/src/components/input/Input.styles.js
@@ -58,6 +58,7 @@ export const InputWrapper = styled(Box)(({ theme }) => ({
export const ActionsWrapper = styled(Box)`
display: flex;
flex-direction: column;
- align-items: flex-end;
+ align-items: center;
flex: 3;
+ margin-left: 10px;
`;
diff --git a/packages/omgx/wallet-frontend/src/containers/account/Account.js b/packages/omgx/wallet-frontend/src/containers/account/Account.js
index 57eed0d7fa14a..9e3bd32d4a568 100644
--- a/packages/omgx/wallet-frontend/src/containers/account/Account.js
+++ b/packages/omgx/wallet-frontend/src/containers/account/Account.js
@@ -231,7 +231,7 @@ function Account () {
You are using Mainnet.
WARNING: the mainnet smart contracts are not fully audited and funds may be at risk.
- Please exercise caution when using Mainnet.
+ Please be cautious when using Mainnet.
}
@@ -249,7 +249,7 @@ function Account () {
variant="body2"
component="p"
>
- Note: Balance altering transaction in progress - please be patient
+ Transaction in progress - please be patient
diff --git a/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStepFast.js b/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStepFast.js
index 2aea023210c22..e18d5252e4704 100644
--- a/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStepFast.js
+++ b/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStepFast.js
@@ -17,7 +17,7 @@ import React, { useState, useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
-import { depositL2LP } from 'actions/networkAction'
+import { depositL2LP, fastExitAll } from 'actions/networkAction'
import { openAlert } from 'actions/uiAction'
import { selectLoading } from 'selectors/loadingSelector'
@@ -42,11 +42,14 @@ function DoExitStepFast({ handleClose, token }) {
const dispatch = useDispatch()
const [ value, setValue ] = useState('')
- const [ value_Wei_String, setValue_Wei_String ] = useState('0') //support for Use Max
+ const [ value_Wei_String, setValue_Wei_String ] = useState('0')
- const [LPBalance, setLPBalance] = useState(0)
- const [feeRate, setFeeRate] = useState(0)
- const [validValue, setValidValue] = useState(false)
+ const [ LPBalance, setLPBalance ] = useState(0)
+ const [ feeRate, setFeeRate ] = useState(0)
+ const [ l1gas, setl1gas ] = useState(0)
+ const [ l2FeeBalance, setL2FeeBalance ] = useState(0)
+
+ const [ validValue, setValidValue ] = useState(false)
const loading = useSelector(selectLoading(['EXIT/CREATE']))
@@ -57,15 +60,10 @@ function DoExitStepFast({ handleClose, token }) {
function setAmount(value) {
- //console.log("setAmount")
-
const tooSmall = new BN(value).lte(new BN(0.0))
const tooBig = new BN(value).gt(new BN(maxValue))
- //console.log("tooSmall",tooSmall)
- //console.log("tooBig",tooBig)
-
- if (tooSmall || tooBig) {
+ if (tooSmall || tooBig || (Number(l1gas) > Number(l2FeeBalance))) {
setValidValue(false)
} else {
setValidValue(true)
@@ -101,6 +99,28 @@ function DoExitStepFast({ handleClose, token }) {
}
+ async function doExitAll() {
+
+ console.log("Amount to exit:", token.balance.toString())
+
+ let res = await dispatch(
+ fastExitAll(
+ token.address
+ )
+ )
+
+ if (res) {
+ dispatch(
+ openAlert(
+ `${token.symbol} was bridged. You will receive
+ ${receivableAmount(value)} ${token.symbol} minus gas fees (if bridging ETH) on L1.`
+ )
+ )
+ handleClose()
+ }
+
+ }
+
useEffect(() => {
if (typeof(token) !== 'undefined') {
networkService.L1LPBalance(token.addressL1).then((res) => {
@@ -109,12 +129,19 @@ function DoExitStepFast({ handleClose, token }) {
networkService.getTotalFeeRate().then((feeRate) => {
setFeeRate(feeRate)
})
+ networkService.getFastExitCost(token.address).then((fee) => {
+ setl1gas(fee)
+ })
+ networkService.getL2FeeBalance().then((ETHbalance) => {
+ setL2FeeBalance(ETHbalance)
+ })
}
// to clean up state and fix the
// error in console for max state update.
return ()=>{
setLPBalance(0)
setFeeRate(0)
+ setl1gas(0)
}
}, [ token ])
@@ -134,9 +161,27 @@ function DoExitStepFast({ handleClose, token }) {
let buttonLabel = 'Cancel'
if( loading ) buttonLabel = 'Close'
+ let ETHstring = ''
+
+ if(l1gas && Number(l1gas) > 0) {
+ if(Number(l1gas) > Number(l2FeeBalance)){
+ ETHstring = `The estimated gas fee for this transaction (approval + bridge) is ${Number(l1gas).toFixed(4)} ETH.
+ WARNING: your L2 ETH balance of ${Number(l2FeeBalance).toFixed(4)} is too small to cover this transaction.
+ THE TRANSACTION WILL FAIL.`
+ } else if (Number(l1gas) > Number(l2FeeBalance) * 0.9) {
+ ETHstring = `The estimated gas fee for this transaction (approval + bridge) is ${Number(l1gas).toFixed(4)} ETH.
+ CAUTION: your L2 ETH balance of ${Number(l2FeeBalance).toFixed(4)} is very close to the estimated cost.
+ This transaction might fail. It would be safer to have slightly more ETH in your L2 wallet to cover gas fees.`
+ } else {
+ ETHstring = `The estimated gas fee for this transaction (approval + bridge) is ${Number(l1gas).toFixed(4)} ETH.
+ Your L2 ETH balance of ${Number(l2FeeBalance).toFixed(4)} is sufficent to cover this transaction.`
+ }
+ }
+
return (
<>
+
Fast Bridge to L1
@@ -152,15 +197,13 @@ function DoExitStepFast({ handleClose, token }) {
setAmount(i.target.value)
setValue_Wei_String(toWei_String(i.target.value, token.decimals))
}}
- onUseMax={(i)=>{//they want to use the maximum
- setAmount(maxValue) //so the input value updates for the user
- setValue_Wei_String(token.balance.toString())
- }}
- allowUseAll={true}
unit={token.symbol}
maxValue={maxValue}
newStyle
variant="standard"
+ loading={loading}
+ onExitAll={doExitAll}
+ allowExitAll={true}
/>
{validValue && token && (
@@ -175,6 +218,18 @@ function DoExitStepFast({ handleClose, token }) {
)}
+ {Number(l1gas) > 0 && Number(l1gas) > Number(l2FeeBalance) && (
+
+ {ETHstring}
+
+ )}
+
+ {Number(l1gas) > 0 && Number(l1gas) <= Number(l2FeeBalance) && (
+
+ {ETHstring}
+
+ )}
+
{Number(LPBalance) < Number(value) && (
The liquidity pool balance (of {LPBalance}) is too low to cover your bridge - please
@@ -189,27 +244,29 @@ function DoExitStepFast({ handleClose, token }) {
)}
+
+
-
-
+
+
>
)
diff --git a/packages/omgx/wallet-frontend/src/services/networkService.js b/packages/omgx/wallet-frontend/src/services/networkService.js
index 25468ebfda6ce..8c42ce8bbd7fd 100644
--- a/packages/omgx/wallet-frontend/src/services/networkService.js
+++ b/packages/omgx/wallet-frontend/src/services/networkService.js
@@ -1203,6 +1203,19 @@ class NetworkService {
})
}
+ async getL2FeeBalance() {
+ try {
+ const layer2Balance = await this.L2Provider.getBalance(this.account)
+ return utils.formatEther(layer2Balance)
+ } catch (error) {
+ throw new WebWalletError({
+ originalError: error,
+ reportToSentry: false,
+ reportToUi: false,
+ })
+ }
+ }
+
async getBalances() {
try {
@@ -1394,7 +1407,8 @@ class NetworkService {
this.L2LPAddress
)
- let depositAmount_BN = new BN(value_Wei_String)
+ //let depositAmount_BN = new BN(value_Wei_String)
+ let depositAmount_BN = BigNumber.from(value_Wei_String)
if (depositAmount_BN.gt(allowance_BN)) {
const approveStatus = await L2ERC20Contract.approve(
@@ -2052,6 +2066,141 @@ class NetworkService {
return balance.toString()
}
+ async getFastExitCost(currencyAddress) {
+
+ const L2ERC20Contract = new ethers.Contract(
+ currencyAddress,
+ L2ERC20Json.abi,
+ this.provider.getSigner()
+ )
+
+ const tx = await L2ERC20Contract.populateTransaction.approve(
+ this.L2LPAddress,
+ utils.parseEther('1.0')
+ )
+
+ const approvalGas_BN = await this.L2Provider.estimateGas(tx)
+ const approvalCost_BN = approvalGas_BN.mul('15000000')
+ console.log("Approve (ETH):", utils.formatEther(approvalCost_BN))
+
+ const tx2 = await this.L2LPContract.populateTransaction.clientDepositL2(
+ utils.parseEther('0'), //needs to be zero here otherwise will fail due to allowance
+ currencyAddress
+ )
+
+ const despositGas_BN = await this.L2Provider.estimateGas(tx2)
+ const despositCost_BN = despositGas_BN.mul('15000000')
+ console.log("Deposit gas cost (ETH)", utils.formatEther(despositCost_BN))
+
+ //returns total cost in ETH
+ return utils.formatEther(despositCost_BN.add(approvalCost_BN))
+ }
+
+ /**************************************************************/
+ /***** SWAP OFF from BOBA by depositing funds to the L2LP *****/
+ /**************************************************************/
+ async fastExitAll(currencyAddress) {
+
+ updateSignatureStatus_exitLP(false)
+
+ let approvalGas_BN = BigNumber.from("0")
+ let approvalCost_BN = BigNumber.from("0")
+
+ console.log("Address:",currencyAddress)
+
+ const L2ERC20Contract = new ethers.Contract(
+ currencyAddress,
+ L2ERC20Json.abi,
+ this.provider.getSigner()
+ )
+
+ let balance_BN = await L2ERC20Contract.balanceOf(
+ this.account
+ )
+ console.log("Initial Balance:", utils.formatEther(balance_BN))
+
+ let allowance_BN = await L2ERC20Contract.allowance(
+ this.account,
+ this.L2LPAddress
+ )
+ console.log("Allowance:",utils.formatEther(allowance_BN))
+
+ if (balance_BN.gt(allowance_BN)) {
+
+ //Estimate gas
+ const tx = await L2ERC20Contract.populateTransaction.approve(
+ this.L2LPAddress,
+ balance_BN
+ )
+
+ approvalGas_BN = await this.L2Provider.estimateGas(tx)
+ approvalCost_BN = approvalGas_BN.mul('15000000')
+ console.log("Cost to Approve:", utils.formatEther(approvalCost_BN))
+
+ const approveStatus = await L2ERC20Contract.approve(
+ this.L2LPAddress,
+ balance_BN
+ )
+ await approveStatus.wait()
+
+ if (!approveStatus)
+ return false
+
+ } else {
+ //console.log("Balance:",balance_BN)
+ console.log("Allowance already suitable:", utils.formatEther(allowance_BN))
+ }
+
+
+ if(currencyAddress === this.L2_ETH_Address) {
+ //if fee token, need to debit allowance cost if any
+ balance_BN = balance_BN.sub(approvalCost_BN)
+ console.log("ETH: Balance after approval", utils.formatEther(balance_BN))
+ }
+
+ const tx2 = await this.L2LPContract.populateTransaction.clientDepositL2(
+ balance_BN,
+ currencyAddress
+ )
+ //console.log("tx2",tx2)
+
+ const despositGas_BN = await this.L2Provider.estimateGas(tx2)
+ const despositCost_BN = despositGas_BN.mul('15000000')
+ console.log("Deposit gas cost (ETH)", utils.formatEther(despositCost_BN))
+
+ let amount_BN = balance_BN
+
+ if(currencyAddress === this.L2_ETH_Address) {
+ //if fee token, need to consider cost to exit
+ amount_BN = balance_BN.sub(despositCost_BN)
+ }
+ console.log("Amount to exit:", utils.formatEther(amount_BN))
+
+ const depositTX = await this.L2LPContract.clientDepositL2(
+ amount_BN.toString(),
+ currencyAddress
+ )
+
+ //at this point the tx has been submitted, and we are waiting...
+ await depositTX.wait()
+
+ //closes the modal
+ updateSignatureStatus_exitLP(true)
+
+ // Waiting for the response from L1
+ const [L2ToL1msgHash] = await this.fastWatcher.getMessageHashesFromL2Tx(
+ depositTX.hash
+ )
+ console.log(' got L2->L1 message hash', L2ToL1msgHash)
+
+ const L1Receipt = await this.fastWatcher.getL1TransactionReceipt(
+ L2ToL1msgHash
+ )
+ console.log(' completed Deposit! L1 tx hash:', L1Receipt.transactionHash)
+
+ return L1Receipt
+ }
+
/**************************************************************/
/***** SWAP OFF from BOBA by depositing funds to the L2LP *****/
/**************************************************************/
@@ -2070,7 +2219,8 @@ class NetworkService {
this.L2LPAddress
)
- let depositAmount_BN = new BN(value_Wei_String)
+ //let depositAmount_BN = new BN(value_Wei_String)
+ let depositAmount_BN = BigNumber.from(value_Wei_String)
if (depositAmount_BN.gt(allowance_BN)) {
const approveStatus = await L2ERC20Contract.approve(