diff --git a/.github/workflows/omgx-publish-master.yml b/.github/workflows/omgx-publish-master.yml index acce211ae869..00e0d3b3e2e4 100644 --- a/.github/workflows/omgx-publish-master.yml +++ b/.github/workflows/omgx-publish-master.yml @@ -16,6 +16,13 @@ jobs: username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + - uses: actions/checkout@v2 - name: Get yarn cache directory path @@ -57,3 +64,9 @@ jobs: echo "$1" docker push "$i" done + + - name: Build and push docker images to AWS + working-directory: ./ops_omgx + run: | + rm -rf cloudformation/deployer-rinkeby.yaml cloudformation/dummy-transaction.yaml cloudformation/omgx-monitor.yaml cloudformation/blockexplorer-blockscout.yaml cloudformation/transaction-monitor.yaml + ./cfn-devenv.sh push2aws --from-tag ${{ steps.tag.outputs.VERSION }} --deploy-tag ${{ steps.tag.outputs.VERSION }} diff --git a/.gitignore b/.gitignore index 8bd4a2fa8faf..db3caf236e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,4 @@ generated packages/omgx/subgraph/L1/yarn.lock packages/omgx/subgraph/L2/yarn.lock packages/omgx/subgraph/L1/bin -packages/omgx/subgraph/L2/bin \ No newline at end of file +packages/omgx/subgraph/L2/bin diff --git a/ops_omgx/api/watcher-api/env-mainnet.yml b/ops_omgx/api/watcher-api/env-mainnet.yml deleted file mode 100644 index 74ed8a13c126..000000000000 --- a/ops_omgx/api/watcher-api/env-mainnet.yml +++ /dev/null @@ -1,10 +0,0 @@ -ROLE: arn:aws:iam::942431445534:role/Enyasmc -SECURITYGROUP: sg-06d0389929cf31a18 -SUBNET_ID_1: subnet-838566a2 -SUBNET_ID_2: subnet-d92acfbf -SECURITY_GROUPS: sg-0efc38a735756ed2f -LAYERS: arn:aws:lambda:us-east-1:942431445534:layer:Python:1 -RDS_ENDPOINT: boba-db.cjka46punles.us-east-1.rds.amazonaws.com -RDS_MYSQL_NAME: admin -RDS_MYSQL_PASSWORD: c5B0bRB83DmangdQshANl -RDS_DBNAME: OMGXMainnetV1 diff --git a/ops_omgx/api/watcher-api/env-rinkeby.yml b/ops_omgx/api/watcher-api/env-rinkeby.yml deleted file mode 100644 index fb3abf723a57..000000000000 --- a/ops_omgx/api/watcher-api/env-rinkeby.yml +++ /dev/null @@ -1,10 +0,0 @@ -ROLE: arn:aws:iam::942431445534:role/Enyasmc -SECURITYGROUP: sg-06d0389929cf31a18 -SUBNET_ID_1: subnet-838566a2 -SUBNET_ID_2: subnet-d92acfbf -SECURITY_GROUPS: sg-0efc38a735756ed2f -LAYERS: arn:aws:lambda:us-east-1:942431445534:layer:Python:1 -RDS_ENDPOINT: boba-db.cjka46punles.us-east-1.rds.amazonaws.com -RDS_MYSQL_NAME: admin -RDS_MYSQL_PASSWORD: c5B0bRB83DmangdQshANl -RDS_DBNAME: OMGXRinkebyV2 diff --git a/ops_omgx/api/watcher-api/watcher_getL2CrossDomainMessage.py b/ops_omgx/api/watcher-api/watcher_getL2CrossDomainMessage.py index 1dc753065804..e6848378065c 100644 --- a/ops_omgx/api/watcher-api/watcher_getL2CrossDomainMessage.py +++ b/ops_omgx/api/watcher-api/watcher_getL2CrossDomainMessage.py @@ -60,8 +60,8 @@ def watcher_getL2CrossDomainMessage(event, context): crossDomainMessageSendTime = transactionDataRaw[8] fastRelay = transactionDataRaw[11] if fastRelay == True: - # Estimate time is 5 minutes - crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + 60 * 5 + # Estimate time + crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + int(config.get('ESTIMATE_FINIALIZED_TIME')) else: # Estimate time is 7 days crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + 60 * 60 * 24 * 7 diff --git a/ops_omgx/api/watcher-api/watcher_getL2Transactions.py b/ops_omgx/api/watcher-api/watcher_getL2Transactions.py index 49810316c65a..2d35f7c4841a 100644 --- a/ops_omgx/api/watcher-api/watcher_getL2Transactions.py +++ b/ops_omgx/api/watcher-api/watcher_getL2Transactions.py @@ -64,8 +64,8 @@ def watcher_getL2Transactions(event, context): crossDomainMessageSendTime = transactionDataRaw[8] fastRelay = transactionDataRaw[11] if fastRelay == True: - # Estimate time is 5 minutes - crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + 60 * 5 + # Estimate time + crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + int(config.get('ESTIMATE_FINIALIZED_TIME')) else: # Estimate time is 7 days crossDomainMessageEstimateFinalizedTime = int(crossDomainMessageSendTime) + 60 * 60 * 24 * 7 diff --git a/ops_omgx/cloudformation/blockexplorer-blockscout.yaml b/ops_omgx/cloudformation/blockexplorer-blockscout.yaml index 0c548fcd21ed..b28d8aa8d58d 100644 --- a/ops_omgx/cloudformation/blockexplorer-blockscout.yaml +++ b/ops_omgx/cloudformation/blockexplorer-blockscout.yaml @@ -150,7 +150,7 @@ Resources: BlockscoutLBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: - Port: 80 + Port: 4000 Protocol: HTTP VpcId: Fn::ImportValue: !Sub "${InfrastructureStackName}:VpcId" @@ -158,7 +158,7 @@ Resources: - Key: deregistration_delay.timeout_seconds Value: 30 HealthCheckIntervalSeconds: 20 - HealthCheckPath: /health + HealthCheckPath: / HealthCheckProtocol: HTTP # TODO Implement proper healthcheck HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 @@ -213,6 +213,8 @@ Resources: Value: ETH - Name: NETWORK Value: Boba + - Name: PORT + Value: 4000 - Name: SUBNETWORK Value: Rinkeby - Name: MIX_ENV @@ -223,14 +225,14 @@ Resources: Value: /images/boba_logo.svg - Name: SUPPORTED_CHAINS Value: '[{"title":"Boba Mainnet","url":"https://blockexplorer.boba.network","hide_in_dropdown?": false},{"title":"Boba Rinkeby","url":"https://blockexplorer.rinkeby.boba.network","test_net?":true},{"title":"Boba Rinkeby Integration","url":"https://blockexplorer.rinkeby-integration.boba.network","test_net?":true,"hide_in_dropdown?": true}]' - - Name: ETHEREUM_JSONRPC_HTTP_URL + - Name: ETHEREUM_JSONRPC_TRACE_URL Value: !Sub - - "http://${EndpointAddress}:8545/rpc" + - "http://${EndpointAddress}:8545/" - EndpointAddress: Fn::ImportValue: !Sub "${InfrastructureStackName}:LoadBalancerReplica:DNSName" - Name: ETHEREUM_JSONRPC_WS_URL Value: !Sub - - "ws://${EndpointAddress}:8545/ws" + - "ws://${EndpointAddress}:8545/ws/" - EndpointAddress: Fn::ImportValue: !Sub "${InfrastructureStackName}:LoadBalancerReplica:DNSName" - Name: BLOCKSCOUT_VERSION @@ -243,23 +245,6 @@ Resources: com.datadoghq.ad.logs: '[{"source": "blockscout", "service": "blockscout"}]' Essential: true Memory: "512" - - Image: 942431445534.dkr.ecr.us-east-1.amazonaws.com/omgx/nginx-eth-proxy:blockscout - Name: nginx-blockscout - PortMappings: - - ContainerPort: 80 - HostPort: 0 - Command: - - "nginx-debug" - - "-g" - - "daemon off;" - DockerLabels: - com.datadoghq.ad.check_names: '["nginx-blockscout"]' - com.datadoghq.ad.init_configs: '[{}]' - com.datadoghq.ad.logs: '[{"source": "nginx-blockscout", "service": "nginx-blockscout"}]' - Essential: true - Memory: "128" - Links: - - blockscout NetworkMode: bridge TaskRoleArn: !GetAtt TaskRole.Arn Family: !Sub "blockscout-${EnvironmentName}" @@ -270,8 +255,8 @@ Resources: Cluster: Fn::ImportValue: !Sub "${InfrastructureStackName}:EcsClusterReplica" LoadBalancers: - - ContainerName: nginx-blockscout - ContainerPort: 80 + - ContainerName: blockscout + ContainerPort: 4000 TargetGroupArn: !Ref BlockscoutLBTargetGroup DesiredCount: !Ref ServiceCount LaunchType: EC2 diff --git a/ops_omgx/cloudformation/replica-l2.yaml b/ops_omgx/cloudformation/replica-l2.yaml index a7e5ee4fbee3..7177cd6d0c32 100644 --- a/ops_omgx/cloudformation/replica-l2.yaml +++ b/ops_omgx/cloudformation/replica-l2.yaml @@ -136,6 +136,7 @@ Resources: ContainerDefinitions: - Image: !Sub "${ECRRegistry}/${DockerPrefix}/${ReplicaL2Image}:${ImageTag}" Name: geth_l2 + Hostname: geth-l2 PortMappings: - ContainerPort: 8545 HostPort: 0 @@ -175,7 +176,7 @@ Resources: - EndpointAddress: Fn::ImportValue: !Sub "${InfrastructureStackName}:DomainName" - Name: RPC_ADDR - Value: "0.0.0.0" + Value: "geth-l2" - Name: ROLLUP_ENABLE_L2_GAS_POLLING Value: true - Name: ROLLUP_ENFORCE_FEES diff --git a/ops_omgx/docker/blockexplorer-blockscout/entrypoint.sh b/ops_omgx/docker/blockexplorer-blockscout/entrypoint.sh index a9ef144804dd..548501ee65c6 100644 --- a/ops_omgx/docker/blockexplorer-blockscout/entrypoint.sh +++ b/ops_omgx/docker/blockexplorer-blockscout/entrypoint.sh @@ -5,5 +5,6 @@ DATABASE_USER=`/opt/secret2env -name $SECRETNAME|grep -w postgres_user|sed 's/po DATABASE_PASS=`/opt/secret2env -name $SECRETNAME|grep -w postgres_pass|sed 's/postgres_pass=//g'` DATABASE_HOST=`/opt/secret2env -name $SECRETNAME|grep -w postgres_host|sed 's/postgres_host=//g'` export DATABASE_URL="postgresql://${DATABASE_USER}:${DATABASE_PASS}@${DATABASE_HOST}:5432/${DATABASE_NAME}?ssl=false" - -mix do ecto.create, ecto.migrate; mix phx.server +printenv +mix do ecto.create, ecto.migrate +mix phx.server \ No newline at end of file diff --git a/ops_omgx/docker/l2geth/geth.sh b/ops_omgx/docker/l2geth/geth.sh index f196abd97491..6625122f1e73 100644 --- a/ops_omgx/docker/l2geth/geth.sh +++ b/ops_omgx/docker/l2geth/geth.sh @@ -63,5 +63,5 @@ curl \ --retry $RETRIES \ --retry-delay 1 \ $ROLLUP_CLIENT_HTTP - +rm -rf /root/.ethereum/geth/LOCK exec geth --verbosity="$VERBOSITY" "$@" diff --git a/ops_omgx/monitor/transaction-monitor/services/blockMonitor.js b/ops_omgx/monitor/transaction-monitor/services/blockMonitor.js index b8b19b01e5ad..1fcbaf7b2c05 100644 --- a/ops_omgx/monitor/transaction-monitor/services/blockMonitor.js +++ b/ops_omgx/monitor/transaction-monitor/services/blockMonitor.js @@ -368,11 +368,15 @@ class BlockMonitorService extends OptimismEnv { // gets list of addresses whose messages may finalize fast async getWhitelist(){ - let response = await fetch(this.filterEndpoint); - const filter = await response.json(); - const filterSelect = [ filter.Proxy__L1LiquidityPool, filter.L1Message ] - this.whitelist = filterSelect - this.logger.info('Found the filter', { filterSelect }) + try { + let response = await fetch(this.filterEndpoint); + const filter = await response.json(); + const filterSelect = [ filter.Proxy__L1LiquidityPool, filter.L1Message ] + this.whitelist = filterSelect + this.logger.info('Found the filter', { filterSelect }) + } catch { + this.logger.error('CRITICAL ERROR: Failed to fetch the Filter') + } } // checks to see if its time to look for L1 finalization diff --git a/ops_omgx/monitor/transaction-monitor/services/database.service.js b/ops_omgx/monitor/transaction-monitor/services/database.service.js index 8bb8347580be..ecf55b35448f 100644 --- a/ops_omgx/monitor/transaction-monitor/services/database.service.js +++ b/ops_omgx/monitor/transaction-monitor/services/database.service.js @@ -237,7 +237,7 @@ class DatabaseService extends OptimismEnv{ const crossDomainMessage = await query(`SELECT * FROM receipt WHERE crossDomainMessage=${true} AND crossDomainMessageFinalize=${false} - AND UNIX_TIMESTAMP() > crossDomainMessageEstimateFinalizedTime + AND ((UNIX_TIMESTAMP() > crossDomainMessageEstimateFinalizedTime AND fastRelay is null) OR fastRelay=true) `); con.end(); return crossDomainMessage; @@ -257,7 +257,6 @@ class DatabaseService extends OptimismEnv{ on depositL2.hash = l1Bridge.hash WHERE crossDomainMessage=${true} AND depositL2.status='pending' - AND UNIX_TIMESTAMP() > crossDomainMessageEstimateFinalizedTime `); con.end(); return crossDomainMessage; diff --git a/ops_omgx/monitor/transaction-monitor/services/utilities/optimismEnv.js b/ops_omgx/monitor/transaction-monitor/services/utilities/optimismEnv.js index 8f17cf486b52..7aeff0043966 100644 --- a/ops_omgx/monitor/transaction-monitor/services/utilities/optimismEnv.js +++ b/ops_omgx/monitor/transaction-monitor/services/utilities/optimismEnv.js @@ -67,8 +67,8 @@ const OVM_L2_CROSS_DOMAIN_MESSENGER = "0x420000000000000000000000000000000000000 class OptimismEnv { constructor() { - this.L1Provider = new ethers.providers.JsonRpcProvider(L1_NODE_WEB3_URL); - this.L2Provider = new ethers.providers.JsonRpcProvider(L2_NODE_WEB3_URL); + this.L1Provider = new ethers.providers.StaticJsonRpcProvider(L1_NODE_WEB3_URL); + this.L2Provider = new ethers.providers.StaticJsonRpcProvider(L2_NODE_WEB3_URL); this.MySQLHostURL = MYSQL_HOST_URL; this.MySQLPort = MYSQL_PORT; diff --git a/packages/batch-submitter/src/transaction-chain-contract.ts b/packages/batch-submitter/src/transaction-chain-contract.ts index a976c4ad3aa0..1caf496eac21 100644 --- a/packages/batch-submitter/src/transaction-chain-contract.ts +++ b/packages/batch-submitter/src/transaction-chain-contract.ts @@ -31,12 +31,12 @@ export class CanonicalTransactionChainContract extends Contract { from: await this.signer.getAddress(), data, }) - + const safeGasLimit = gasLimit.mul(ethers.BigNumber.from(11)).div(ethers.BigNumber.from(10)) return { nonce, to, data, - gasLimit, + gasLimit: safeGasLimit, } }, } diff --git a/packages/message-relayer/package.json b/packages/message-relayer/package.json index 2a4d8888dce5..8932fc61a06f 100644 --- a/packages/message-relayer/package.json +++ b/packages/message-relayer/package.json @@ -41,7 +41,6 @@ "bcfg": "^0.1.6", "dotenv": "^8.2.0", "ethers": "^5.4.5", - "lodash": "^4.17.21", "merkletreejs": "^0.2.18", "node-fetch": "^2.6.1", "rlp": "^2.2.6" diff --git a/packages/message-relayer/src/service.ts b/packages/message-relayer/src/service.ts index ce07da9a94f2..cd3c10588c79 100644 --- a/packages/message-relayer/src/service.ts +++ b/packages/message-relayer/src/service.ts @@ -3,7 +3,6 @@ import { Contract, ethers, Wallet, BigNumber, providers } from 'ethers' import * as rlp from 'rlp' import { MerkleTree } from 'merkletreejs' import fetch from 'node-fetch'; -import { isEqual } from 'lodash'; /* Imports: Internal */ import { fromHexString, sleep } from '@eth-optimism/core-utils' @@ -406,13 +405,6 @@ export class MessageRelayerService extends BaseService { selectedEvent.blockNumber, selectedEvent.blockNumber ) - // alert if two SCC events are not the same - if (!isEqual(selectedEvent, SCCEvent[0])) { - this.logger.warn('Found inconsistent SCC event', { - prevSCCEvent: selectedEvent, - newSCCEvent: SCCEvent - }) - } return SCCEvent[0] } @@ -737,12 +729,9 @@ export class MessageRelayerService extends BaseService { this.state.filter = filterSelect this.logger.info('Found the filter', { filterSelect }) } - } else { - this.state.filter = []; } } catch { - this.logger.info('Failed to fetch the filter') - this.state.filter = []; + this.logger.error('CRITICAL ERROR: Failed to fetch the Filter') } } } diff --git a/packages/omgx/contracts/deployment/mainnet/addressess.json b/packages/omgx/contracts/deployment/mainnet/addressess.json index 6657c710cbe6..8c75e9f37c6e 100644 --- a/packages/omgx/contracts/deployment/mainnet/addressess.json +++ b/packages/omgx/contracts/deployment/mainnet/addressess.json @@ -5,12 +5,12 @@ "L2": "0xeDB79B0FD84c81E870b2fCB1D3CcF366179bA6D2" } }, - "OVM_L1CrossDomainMessengerFast": "0x68ac1623ACf9eB9F88b65B5F229fE3e2c0d5789e", - "Proxy__OVM_L1CrossDomainMessengerFast": "0x841979bbC06Be7BFE28d9FadDac1A73e1Fb495C1", - "L2LiquidityPool": "0x9C133903F299f083F2ba4A7DAeb142643Fe1864D", - "L1LiquidityPool": "0x87b6C838486c836a1fb16716Df25D8E023fd541C", - "Proxy__L1LiquidityPool": "0x3256BD6Fc8b5fA48DB95914d0dF314465F3F7879", - "Proxy__L2LiquidityPool": "0x02fc14bC0dF6452FCC36496244eE2D043401582F", + "OVM_L1CrossDomainMessengerFast": "0xb7E757633857C2E6Ec7aab362c17E7a5913B4855", + "Proxy__OVM_L1CrossDomainMessengerFast": "0xD05b8fD53614e1569cAC01c6D8d41416d0a7257E", + "L2LiquidityPool": "0xB1a1B698E4c67c242441749C22575FA02B14D645", + "L1LiquidityPool": "0x3d95bE575576F813B9b18eE14ba041d3E013eC25", + "Proxy__L1LiquidityPool": "0x1A26ef6575B7BBB864d984D9255C069F6c361a14", + "Proxy__L2LiquidityPool": "0x3A92cA39476fF84Dc579C868D4D7dE125513B034", "L2ERC721": "0xe7dc303281a6B69D86578EB596741cA1B8EFcD93", "L2ERC721Reg": "0x967c403E64A316d0Cb04c97334F967a37d58d82f" } diff --git a/packages/omgx/gas-price-oracle/src/service.ts b/packages/omgx/gas-price-oracle/src/service.ts index 551749e91ea1..befa38522bb0 100644 --- a/packages/omgx/gas-price-oracle/src/service.ts +++ b/packages/omgx/gas-price-oracle/src/service.ts @@ -53,6 +53,7 @@ export class GasPriceOracleService extends BaseService { OVM_oETH: Contract L1ETHBalance: BigNumber L1ETHCostFee: BigNumber + L2ETHVaultBalance: BigNumber L2ETHCollectFee: BigNumber lastQueriedL1Block: number lastQueriedL2Block: number @@ -99,6 +100,7 @@ export class GasPriceOracleService extends BaseService { this.state.L1ETHBalance = BigNumber.from('0') this.state.L1ETHCostFee = BigNumber.from('0') this.state.L2ETHCollectFee = BigNumber.from('0') + this.state.L2ETHVaultBalance = BigNumber.from('0') this.state.lastQueriedL1Block = await this.options.l1RpcProvider.getBlockNumber() this.state.lastQueriedL2Block = await this.options.l2RpcProvider.getBlockNumber() @@ -108,6 +110,7 @@ export class GasPriceOracleService extends BaseService { // Load history await this._loadL1ETHFee(); + await this._loadL2ETHCost(); } protected async _start(): Promise { @@ -120,7 +123,7 @@ export class GasPriceOracleService extends BaseService { } private async _loadL1ETHFee(): Promise { - const dumpsPath = path.resolve(__dirname, '../data/history.json') + const dumpsPath = path.resolve(__dirname, '../data/l1History.json') if (fs.existsSync(dumpsPath)) { this.logger.warn('Loading L1 cost history...') const historyJsonRaw = await fsPromise.readFile(dumpsPath) @@ -136,13 +139,43 @@ export class GasPriceOracleService extends BaseService { } } + private async _loadL2ETHCost(): Promise { + const vaultBalance = + BigNumber.from((await this.state.OVM_oETH.balanceOf(this.options.OVM_SequencerFeeVault)).toString()) + // load data + const dumpsPath = path.resolve(__dirname, '../data/l2History.json') + if (fs.existsSync(dumpsPath)) { + this.logger.warn('Loading L2 cost history...') + const historyJsonRaw = await fsPromise.readFile(dumpsPath) + const historyJSON = JSON.parse(historyJsonRaw.toString()) + if (historyJSON.L2ETHCollectFee) { + this.state.L2ETHCollectFee = BigNumber.from(historyJSON.L2ETHCollectFee) + } else { + this.logger.warn('Invalid L2 cost history!') + this.state.L2ETHCollectFee = vaultBalance + } + } else { + this.logger.warn('No L2 cost history Found!') + this.state.L2ETHCollectFee = vaultBalance + } + // adjust the L2ETHCollectFee if it is not correct + if (this.state.L2ETHCollectFee.lt(vaultBalance)) { + this.state.L2ETHCollectFee = vaultBalance + } + this.state.L2ETHVaultBalance = vaultBalance + this.logger.info('Loaded L2 Cost Data', { + L2ETHVaultBalance: this.state.L2ETHVaultBalance.toString(), + L2ETHCollectFee: this.state.L2ETHCollectFee.toString() + }) + } + private async _writeL1ETHFee(): Promise { const dumpsPath = path.resolve(__dirname, '../data') if (!fs.existsSync(dumpsPath)) { fs.mkdirSync(dumpsPath) } try { - const addrsPath = path.resolve(dumpsPath, 'history.json') + const addrsPath = path.resolve(dumpsPath, 'l1History.json') await fsPromise.writeFile(addrsPath, JSON.stringify({ L1ETHBalance: this.state.L1ETHBalance.toString(), L1ETHCostFee: this.state.L1ETHCostFee.toString() @@ -153,6 +186,22 @@ export class GasPriceOracleService extends BaseService { } } + private async _writeL2ETHCost(): Promise { + const dumpsPath = path.resolve(__dirname, '../data') + if (!fs.existsSync(dumpsPath)) { + fs.mkdirSync(dumpsPath) + } + try { + const addrsPath = path.resolve(dumpsPath, 'l2History.json') + await fsPromise.writeFile(addrsPath, JSON.stringify({ + L2ETHCollectFee: this.state.L2ETHCollectFee.toString() + })) + } catch (error) { + console.log(error) + this.logger.error("Failed to write L1 cost history!") + } + } + private async _getL1Balance(): Promise { const balances = await Promise.all([ this.options.l1RpcProvider.getBalance(this.options.sequencerAddress), @@ -181,13 +230,14 @@ export class GasPriceOracleService extends BaseService { this.state.lastQueriedL1Block = await this.options.l2RpcProvider.getBlockNumber() // write history - this._writeL1ETHFee(); + this._writeL1ETHFee() this.logger.info("Got L1 ETH balances", { network: "L1", data: { L1ETHBalance: this.state.L1ETHBalance.toString(), - L1ETHCostFee: Number(utils.formatEther(this.state.L1ETHCostFee.toString()).slice(0, 8)), + L1ETHCostFee: Number(Number(utils.formatEther(this.state.L1ETHCostFee.toString())).toFixed(6)), + L1ETHCostFee10X: Number((Number(utils.formatEther(this.state.L1ETHCostFee.toString())) * 10).toFixed(6)), latestQueriedL1Block: this.state.lastQueriedL1Block, } }) @@ -212,15 +262,28 @@ export class GasPriceOracleService extends BaseService { }, [BigNumber.from('0'), BigNumber.from('0')]) // Get L2 ETH Fee from contract - this.state.L2ETHCollectFee = BigNumber.from((await this.state.OVM_oETH.balanceOf(this.options.OVM_SequencerFeeVault)).toString()) + const L2ETHCollectFee = + BigNumber.from((await this.state.OVM_oETH.balanceOf(this.options.OVM_SequencerFeeVault)).toString()) + // The oETH in OVM_SequencerFeeVault is zero after withdrawing it + let L2ETHCollectFeeIncreased = BigNumber.from('0') + if (L2ETHCollectFee.lt(this.state.L2ETHCollectFee)) { + this.state.L2ETHVaultBalance = L2ETHCollectFee + } else { + L2ETHCollectFeeIncreased = L2ETHCollectFee.sub(this.state.L2ETHVaultBalance) + this.state.L2ETHVaultBalance = L2ETHCollectFee + } + this.state.L2ETHCollectFee = this.state.L2ETHCollectFee.add(L2ETHCollectFeeIncreased); this.state.lastQueriedL2Block = latestQueriedL2Block this.state.avgL2GasLimitPerBlock = collectGasLimitAndFee[0].div(numberOfBlocksInterval) this.state.numberOfBlocksInterval = numberOfBlocksInterval + await this._writeL2ETHCost() + this.logger.info("Got L2 Gas Cost", { network: "L2", data: { - L2ETHCollectFee: Number(utils.formatEther(this.state.L2ETHCollectFee.toString()).slice(0, 8)), + L2ETHCollectFee: Number(Number(utils.formatEther(this.state.L2ETHCollectFee.toString())).toFixed(6)), + L2ETHCollectFee10X: Number((Number(utils.formatEther(this.state.L2ETHCollectFee.toString())) * 10).toFixed(6)), lastQueriedL2Block: this.state.lastQueriedL2Block, avgL2GasUsagePerBlock: this.state.avgL2GasLimitPerBlock.toString(), numberOfBlocksInterval: this.state.numberOfBlocksInterval, @@ -258,4 +321,4 @@ export class GasPriceOracleService extends BaseService { this.logger.info("No need to update L2 gas price", { gasPrice: gasPriceInt, targetGasPrice }) } } -} \ No newline at end of file +} diff --git a/packages/omgx/message-relayer-fast/package.json b/packages/omgx/message-relayer-fast/package.json index 22ccd5f55d84..e020f78ed548 100644 --- a/packages/omgx/message-relayer-fast/package.json +++ b/packages/omgx/message-relayer-fast/package.json @@ -67,7 +67,6 @@ "ganache-core": "^2.13.2", "glob": "^7.1.6", "google-spreadsheet": "^3.1.15", - "lodash": "^4.17.21", "merkletreejs": "^0.2.18", "patch-package": "^6.4.7", "rlp": "^2.2.6" diff --git a/packages/omgx/message-relayer-fast/src/service.ts b/packages/omgx/message-relayer-fast/src/service.ts index c6fbd63dfd9b..28ef69166f6e 100644 --- a/packages/omgx/message-relayer-fast/src/service.ts +++ b/packages/omgx/message-relayer-fast/src/service.ts @@ -3,7 +3,6 @@ import { Contract, ethers, Wallet, BigNumber, providers } from 'ethers' import * as rlp from 'rlp' import { MerkleTree } from 'merkletreejs' import fetch from 'node-fetch'; -import { isEqual } from 'lodash'; /* Imports: Internal */ import { fromHexString, sleep } from '@eth-optimism/core-utils' @@ -190,7 +189,7 @@ export class MessageRelayerService extends BaseService { protected async _start(): Promise { while (this.running) { await sleep(this.options.pollingInterval) - await this._getfilter(); + await this._getFilter(); try { // The message is relayed directly, no need to keep cache @@ -404,13 +403,6 @@ export class MessageRelayerService extends BaseService { selectedEvent.blockNumber, selectedEvent.blockNumber ) - // alert if two SCC events are not the same - if (!isEqual(selectedEvent, SCCEvent[0])) { - this.logger.warn('Found inconsistent SCC event', { - prevSCCEvent: selectedEvent, - newSCCEvent: SCCEvent - }) - } return SCCEvent[0] } @@ -710,7 +702,7 @@ export class MessageRelayerService extends BaseService { return receipt } - private async _getfilter(): Promise { + private async _getFilter(): Promise { try { if (this.options.filterEndpoint) { if (this.state.lastFilterPollingTimestamp === 0 || @@ -728,12 +720,9 @@ export class MessageRelayerService extends BaseService { this.state.filter = filterSelect this.logger.info('Found the filter', { filterSelect }) } - } else { - this.state.filter = []; } } catch { - this.logger.info('Failed to fetch the Filter') - this.state.filter = []; + this.logger.error('CRITICAL ERROR: Failed to fetch the Filter') } } } diff --git a/packages/omgx/wallet-frontend/src/actions/createAction.js b/packages/omgx/wallet-frontend/src/actions/createAction.js index 5cc14fe93044..fbbd84b676c2 100644 --- a/packages/omgx/wallet-frontend/src/actions/createAction.js +++ b/packages/omgx/wallet-frontend/src/actions/createAction.js @@ -23,6 +23,8 @@ export function createAction (key, asyncAction) { //deal with metamask errors if(response && response.hasOwnProperty('message') && response.hasOwnProperty('code')) { dispatch({ type: `UI/ERROR/UPDATE`, payload: response.message }) + // cancel request loading state + dispatch({ type: `${key}/ERROR` }) return false } dispatch({ type: `${key}/SUCCESS`, payload: response }); diff --git a/packages/omgx/wallet-frontend/src/actions/networkAction.js b/packages/omgx/wallet-frontend/src/actions/networkAction.js index 4f0cea4749d9..7caf206cdff4 100644 --- a/packages/omgx/wallet-frontend/src/actions/networkAction.js +++ b/packages/omgx/wallet-frontend/src/actions/networkAction.js @@ -46,12 +46,6 @@ export function exitBOBA(token, value) { ) } -export function processExits(maxExits, currency, gasPrice) { - return createAction('QUEUE/PROCESS', () => - networkService.processExits(maxExits, currency, gasPrice) - ) -} - //SWAP RELATED export function depositL1LP(currency, value, decimals) { return createAction('DEPOSIT/CREATE', () => @@ -67,16 +61,18 @@ export function depositL2LP(token, value) { } //DEPOSIT ETH -export function depositETHL2(value, gasLimit) { - return createAction('DEPOSIT/CREATE', () => - networkService.depositETHL2(value,gasLimit) +export function depositETHL2(value) { + return createAction('DEPOSIT/CREATE', () => { + return networkService.depositETHL2(value) + } ) } //DEPOSIT ERC20 -export function depositErc20(value, currency, gasPrice, currencyL2) { +export function depositErc20(value, currency, currencyL2) { + console.log("Depositing ERC20") return createAction('DEPOSIT/CREATE', () => - networkService.depositErc20(value, currency, gasPrice, currencyL2) + networkService.depositErc20(value, currency, currencyL2) ) } @@ -120,58 +116,12 @@ export function approveERC20_L1LP( ) } -// Never used? -// export function resetApprove( -// value, -// currency, -// approveContractAddress, -// contractABI -// ) { -// return createAction('APPROVE/RESET', () => -// networkService.resetApprove( -// value, -// currency, -// approveContractAddress, -// contractABI -// ) -// ) -// } - export function transfer(recipient, value, currency) { return createAction('TRANSFER/CREATE', () => networkService.transfer(recipient, value, currency) ) } -export function fetchGas (params) { - return createAction('GAS/GET', () => networkService.getGasPrice(params) - ) -} - -// export function fetchFees () { -// return async function (dispatch) { -// // only makes the call if fee fetch not successful before -// const state = store.getState(); -// if (Object.keys(state.fees).length) { -// return; -// } - -// dispatch({ type: 'FEE/GET/REQUEST' }); -// try { -// const fees = await networkService.fetchFees(); -// if (fees.length) { -// dispatch({ -// type: 'FEE/GET/SUCCESS', -// payload: fees -// }); -// } -// } catch (error) { -// console.warn('Couldnt fetch fees, retrying...'); -// return; -// } -// }; -// } - export function fetchLookUpPrice(params) { return createAction('PRICE/GET', () => networkService.fetchLookUpPrice(params)) diff --git a/packages/omgx/wallet-frontend/src/actions/tokenAction.js b/packages/omgx/wallet-frontend/src/actions/tokenAction.js index 05396b7decf7..6cd9d734cbb8 100644 --- a/packages/omgx/wallet-frontend/src/actions/tokenAction.js +++ b/packages/omgx/wallet-frontend/src/actions/tokenAction.js @@ -86,14 +86,13 @@ export async function addToken ( tokenContractAddressL1 ) { const decimals = _decimals ? Number(_decimals.toString()) : 'NOT ON ETHEREUM' const symbolL1 = _symbolL1 || 'NOT ON ETHEREUM' - let symbolL2 = _symbolL1 || 'NOT ON ETHEREUM' + const symbolL2 = _symbolL1 || 'NOT ON ETHEREUM' const name = _name || 'NOT ON ETHEREUM' //ETH is special as always let _tokenContractAddressL2 = null if(_tokenContractAddressL1 === ETHL1 ) { _tokenContractAddressL2 = ETHL2 - symbolL2 = 'oETH' } /********* DO WE HAVE L2 DATA?? *************/ diff --git a/packages/omgx/wallet-frontend/src/api/ethGasStationAxios.js b/packages/omgx/wallet-frontend/src/api/ethGasStationAxios.js deleted file mode 100644 index 017d64276cd6..000000000000 --- a/packages/omgx/wallet-frontend/src/api/ethGasStationAxios.js +++ /dev/null @@ -1,9 +0,0 @@ -import axios from 'axios' - -import { getBaseServices } from 'util/masterConfig' - -const _ethGasStationAxiosInstance = axios.create({ - baseURL: getBaseServices().ETH_GAS_STATION_URL, -}) - -export default _ethGasStationAxiosInstance diff --git a/packages/omgx/wallet-frontend/src/components/button/Button.js b/packages/omgx/wallet-frontend/src/components/button/Button.js index 92cf7f0db083..ccffcc80a253 100644 --- a/packages/omgx/wallet-frontend/src/components/button/Button.js +++ b/packages/omgx/wallet-frontend/src/components/button/Button.js @@ -13,9 +13,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import { CircularProgress } from '@material-ui/core'; -import { Button as ButtonMUI } from '@material-ui/core'; +import React from 'react' +import { CircularProgress, Tooltip } from '@material-ui/core' +import { Button as ButtonMUI } from '@material-ui/core' function Button ({ children, @@ -68,7 +68,8 @@ function Button ({ } return ( - + + {children} {(disabled || loading) && timeDefined && (waitTime > 3) &&
@@ -81,6 +82,7 @@ function Button ({
}
+
) } diff --git a/packages/omgx/wallet-frontend/src/components/button/Button.module.scss b/packages/omgx/wallet-frontend/src/components/button/Button.module.scss deleted file mode 100644 index 1157071fde95..000000000000 --- a/packages/omgx/wallet-frontend/src/components/button/Button.module.scss +++ /dev/null @@ -1,63 +0,0 @@ -@import 'index.scss'; - -.Button { - display: flex; - justify-content: center; - align-items: center; - color: $gray6; - padding: 15px; /*this is what makes the buttons so big*/ - flex: 1; - cursor: pointer; - transition: all 200ms ease-in-out; - /*max-width: $maxWidth;*/ - @include mobile { - min-width: 100px; - } -} - -.small { - padding: 7px; - min-width: 80px; -} - -.tiny { - padding: 2px; - min-width: 60px; - max-width: 300px; - justify-content: left; -} - -.primary { - background: linear-gradient(131.81deg, #4A6FEF 2.66%, #4251F0 124.21%);//$blue; -} - -.secondary { - background-color: $gray4; -} - -.outline { - border: 1.4px solid #506DFA;///2px solid $gray4; -} - -.pulsate { - background: blue; - animation: pulse-animation 2s infinite; -} - -@keyframes pulse-animation { - 0% { - background: $blue; - box-shadow: 0 0 0 0px $blue; - } - 100% { - background: blue; - box-shadow: 0 0 0 2px blue; - } -} - -/*disabled dark blue*/ -.disabled { - filter: brightness(50%); - cursor: initial; - pointer-events: none; -} diff --git a/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.js b/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.js deleted file mode 100644 index 1de3736281f2..000000000000 --- a/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.js +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2019-present OmiseGO Pte Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. */ - -import { Box, CardActionArea, Grid, Typography } from '@material-ui/core'; -import React, { useEffect } from 'react'; -import { useSelector } from 'react-redux'; - -import { selectGas } from 'selectors/gasSelector'; -import * as S from './GasPicker.styles' - -function GasPicker ({ selectedSpeed, setSelectedSpeed, setGasPrice }) { - const gas = useSelector(selectGas); - - useEffect(() => { - setGasPrice(gas[selectedSpeed]); - }, [ selectedSpeed, gas, setGasPrice ]); - - return ( - - - Gas Fee - - - - - - setSelectedSpeed('slow')}> - - Slow - {gas.slow / 1000000000} gwei - - - - - - - - setSelectedSpeed('normal')}> - - Normal - {gas.normal / 1000000000} gwei - - - - - - - - setSelectedSpeed('fast')}> - - Fast - {gas.fast / 1000000000} gwei - - - - - - - - ); -} - -export default React.memo(GasPicker); diff --git a/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.styles.js b/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.styles.js deleted file mode 100644 index 0724404e101e..000000000000 --- a/packages/omgx/wallet-frontend/src/components/gaspicker/GasPicker.styles.js +++ /dev/null @@ -1,15 +0,0 @@ -import { styled } from '@material-ui/system'; -import { Box, Card } from '@material-ui/core'; - -export const CardTag = styled(Card)` - border: ${(props) => props.selected ? '2px solid #F0A000' : '2px solid #3A3F51'}; - opacity: ${(props) => props.selected ? 1.0 : 0.4}; - background-color: ${(props) => props.theme.palette.background.secondary}; -`; - -export const WrapperItem = styled(Box)` - display: flex; - align-items: center; - justify-content: space-between; - padding: 18px 16px; -`; diff --git a/packages/omgx/wallet-frontend/src/components/icons/DAOIcon.js b/packages/omgx/wallet-frontend/src/components/icons/DAOIcon.js index 3869d44f7035..6e2272212c81 100644 --- a/packages/omgx/wallet-frontend/src/components/icons/DAOIcon.js +++ b/packages/omgx/wallet-frontend/src/components/icons/DAOIcon.js @@ -2,22 +2,22 @@ import * as React from "react"; function DAOIcon({ color }) { return ( - - - - - - - - - - - + + + + + + + + + + + ); } diff --git a/packages/omgx/wallet-frontend/src/components/input/Input.js b/packages/omgx/wallet-frontend/src/components/input/Input.js index cd45c5ad80cc..01968593e72f 100644 --- a/packages/omgx/wallet-frontend/src/components/input/Input.js +++ b/packages/omgx/wallet-frontend/src/components/input/Input.js @@ -17,6 +17,8 @@ import React from 'react' import BN from 'bignumber.js' import * as S from './Input.styles' +import Button from 'components/button/Button' + import { Box, Typography } from '@material-ui/core' import { useTheme } from '@emotion/react' import { getCoinImage } from 'util/coinImage' @@ -30,15 +32,15 @@ function Input({ unit, value, onChange, + onUseMax, sx, paste, - // className, maxValue, - // small, fullWidth, size, variant, newStyle = false, + allowUseAll = false, }) { async function handlePaste() { @@ -52,14 +54,18 @@ function Input({ } } - // function handleMaxClick() { - // onChange({ target: { value: maxValue } }) - // } + function handleClickMax() { + onUseMax() + } + const underZero = new BN(value).lt(new BN(0)) const overMax = new BN(value).gt(new BN(maxValue)) - const theme = useTheme() + //since ETH is the fee token, harder to use all b/c need to take + //operation-specific fees into account + allowUseAll = (unit === 'ETH') ? false : allowUseAll + return ( <> @@ -87,7 +93,7 @@ function Input({ fullWidth={fullWidth} size={size} variant={variant} - error={overMax} + error={underZero || overMax} sx={sx} newstyle={newStyle ? 1 : 0} /> @@ -96,16 +102,16 @@ function Input({ {unit && ( - Max Available: {Number(maxValue).toFixed(3)} + Max Amount: {Number(maxValue).toFixed(3)} - {/* maxValue && value !== maxValue && ( + {allowUseAll && ( - - )*/} + )} )} {paste && ( @@ -114,19 +120,19 @@ function Input({ )} - {value <= 0 && value !== '' ? + {value !== '' && underZero ? - The value must be greater than 0. + Value too small: the value must be greater than 0 : null } - {value !== '' && value > maxValue ? + {value !== '' && overMax ? - The value must be smaller than {Number(maxValue).toFixed(3)}. + Value too large: the value must be smaller than {Number(maxValue).toFixed(3)} : null} ) } -export default React.memo(Input) +export default React.memo(Input) \ No newline at end of file diff --git a/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.js b/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.js deleted file mode 100644 index eacaf5b7155e..000000000000 --- a/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.js +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2019-present OmiseGO Pte Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. */ - -import React from 'react' -import { KeyboardArrowDown } from '@material-ui/icons' -import Input from 'components/input/Input' - -import * as styles from './InputSelect.module.scss' - -function InputSelect({ - placeholder, - label, - value, - onChange, - selectOptions, - onSelect, - selectValue, - maxValue, - disabledSelect = false, - type = 'number', - paste = false, - variant, - newStyle, -}) { - const selected = selectOptions.find((i) => i.value === selectValue) - - const renderUnit = ( -
- -
-
-
{selected ? selected.title : ''}
-
- {selected ? selected.subTitle : ''} -
-
- {disabledSelect ? <> : } -
-
- ) - - return ( - - ) -} - -export default React.memo(InputSelect) diff --git a/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.module.scss b/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.module.scss deleted file mode 100644 index 0e169660d57c..000000000000 --- a/packages/omgx/wallet-frontend/src/components/inputselect/InputSelect.module.scss +++ /dev/null @@ -1,43 +0,0 @@ -@import 'index.scss'; - -.selectContainer { - height: 46px; - margin: -10px -10px -10px 0; - position: relative; - - .select { - border: none; - outline: none; - border-radius: 0; - padding-right: 10px; - -webkit-appearance: none; - -webkit-border-radius: 0px; - background-color: $gray3; - color: $gray3; - position: absolute; - right: 0; - top: 0; - bottom: 0; - opacity: 0; - } - - .selected { - flex: 1; - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: center; - height: 46px; - margin-right: 10px; - - .details { - text-align: right; - margin-right: 10px; - font-size: 0.9em; - .subTitle { - font-size: 0.7em; - white-space: nowrap; - } - } - } -} \ No newline at end of file diff --git a/packages/omgx/wallet-frontend/src/components/listAccount/listAccount.js b/packages/omgx/wallet-frontend/src/components/listAccount/listAccount.js index 08036cc79613..5e0186c9ba52 100644 --- a/packages/omgx/wallet-frontend/src/components/listAccount/listAccount.js +++ b/packages/omgx/wallet-frontend/src/components/listAccount/listAccount.js @@ -17,35 +17,56 @@ import { getCoinImage } from 'util/coinImage' class ListAccount extends React.Component { constructor(props) { + super(props) - const { token, chain, networkLayer, disabled } = this.props + + const { + token, + chain, + networkLayer, + disabled, + loading + } = this.props + this.state = { token, chain, dropDownBox: false, networkLayer, - disabled + disabled, + loading } + } componentDidUpdate(prevState) { - const { token, chain, networkLayer, disabled } = this.props; + const { + token, + chain, + networkLayer, + disabled, + loading + } = this.props if (!isEqual(prevState.token, token)) { - this.setState({ token }); + this.setState({ token }) } if (!isEqual(prevState.chain, chain)) { - this.setState({ chain }); + this.setState({ chain }) } if (!isEqual(prevState.networkLayer, networkLayer)) { - this.setState({ networkLayer }); + this.setState({ networkLayer }) } if (!isEqual(prevState.disabled, disabled)) { - this.setState({ disabled }); + this.setState({ disabled }) + } + + if (!isEqual(prevState.loading, loading)) { + this.setState({ loading }) } } @@ -62,7 +83,7 @@ class ListAccount extends React.Component { dropDownBox, networkLayer, disabled - } = this.state; + } = this.state const enabled = (networkLayer === chain) ? true : false const logo = getCoinImage(token.symbol) @@ -82,7 +103,7 @@ class ListAccount extends React.Component { - {`${logAmount(token.balance, 18, 2)}`} + {`${logAmount(token.balance, token.decimals, 2)}`} @@ -97,12 +118,12 @@ class ListAccount extends React.Component { > {chain === 'L1' && - Deposit + Bridge } {chain === 'L2' && - Transact + Bridge/Transfer } @@ -127,7 +148,7 @@ class ListAccount extends React.Component { }} > - You are on L2. To transact on L1, SWITCH LAYER to L1 + You are on L2. To use L1, click SWITCH LAYER @@ -144,7 +165,7 @@ class ListAccount extends React.Component { }} > - You are on L1. To transact on L2, SWITCH LAYER to L2 + You are on L1. To use L2, click SWITCH LAYER @@ -160,9 +181,10 @@ class ListAccount extends React.Component { color='neutral' variant="outlined" disabled={disabled} + tooltip="Classic Bridge to Boba L2. This option is always available but is generally more expensive than the swap-based system ('Fast Bridge')." fullWidth > - Deposit + Bridge to L2 } @@ -183,24 +206,27 @@ class ListAccount extends React.Component { onClick={()=>{this.handleModalClick('exitModal', token, false)}} variant="outlined" disabled={disabled} + tooltip="Classic Bridge to L1. This option is always available but has a 7 day delay before receiving your funds." fullWidth > - Standard Exit + Bridge to L1 : <> - {`${name}`} Staked + {`${symbol}`} Staked {logAmount(userInfo.amount, decimals)} diff --git a/packages/omgx/wallet-frontend/src/containers/modals/deposit/steps/InputStepFast.js b/packages/omgx/wallet-frontend/src/containers/modals/deposit/steps/InputStepFast.js index b3a29a8f1b66..c7152b05bd07 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/deposit/steps/InputStepFast.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/deposit/steps/InputStepFast.js @@ -14,12 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ import { useTheme } from '@emotion/react' + import { Typography, useMediaQuery } from '@material-ui/core' import { Box } from '@material-ui/system' import { depositL1LP, approveERC20 } from 'actions/networkAction' + import { openAlert, openError, setActiveHistoryTab1 } from 'actions/uiAction' + import Button from 'components/button/Button' import Input from 'components/input/Input' + import { WrapperActionsModal } from 'components/modal/Modal.styles' import React, { useEffect, useState } from 'react' @@ -30,34 +34,45 @@ import { selectLookupPrice } from 'selectors/lookupSelector' import { selectSignatureStatus_depositLP } from 'selectors/signatureSelector' import networkService from 'services/networkService' -import { powAmount, logAmount, amountToUsd } from 'util/amountConvert' +import { logAmount, amountToUsd, toWei_String } from 'util/amountConvert' + +import BN from 'bignumber.js' function InputStepFast({ handleClose, token }) { const dispatch = useDispatch() - const [value, setValue] = useState('') + const [ value, setValue ] = useState('') + const [ value_Wei_String, setValue_Wei_String ] = useState('0') //support for Use Max + const [LPBalance, setLPBalance] = useState(0) const [feeRate, setFeeRate] = useState(0) const [disabledSubmit, setDisabledSubmit] = useState(true) const depositLoading = useSelector(selectLoading(['DEPOSIT/CREATE'])) const approvalLoading = useSelector(selectLoading(['APPROVE/CREATE'])) + const lookupPrice = useSelector(selectLookupPrice) const signatureStatus = useSelector(selectSignatureStatus_depositLP) + const maxValue = logAmount(token.balance, token.decimals) - const valueIsValid = value > 0 && value <= maxValue function setAmount(value) { - if ( - Number(value) > 0 && - Number(value) < Number(LPBalance) && - Number(value) < Number(token.balance) - ) { - setDisabledSubmit(false) - } else { + + 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) { setDisabledSubmit(true) + } else { + setDisabledSubmit(false) } + setValue(value) } @@ -65,36 +80,38 @@ function InputStepFast({ handleClose, token }) { let res + console.log("Amount to bridge to L2:", value_Wei_String) + if(token.symbol === 'ETH') { - console.log("ETH Fast swap on") - - if (value > 0) { - res = await dispatch(depositL1LP(token.address, value, token.decimals)) - if (res) { - dispatch(setActiveHistoryTab1('Deposits')) - dispatch( - openAlert( - `ETH was deposited into the L1LP. You will receive - ${((Number(value) * (100 - Number(feeRate)))/100).toFixed(2)} - oETH on L2` - ) + console.log("ETH Fast Bridge") + + res = await dispatch(depositL1LP(token.address, value_Wei_String)) + + if (res) { + dispatch(setActiveHistoryTab1('Bridge to L2')) + dispatch( + openAlert( + `ETH was bridged. You will receive + ${((Number(value) * (100 - Number(feeRate)))/100).toFixed(3)} + ETH on L2` ) - handleClose() - return - } else { - dispatch(openError('Failed to deposit ETH')) - return - } + ) + handleClose() + return + } else { + dispatch(openError('Failed to bridge ETH')) + return } + } //at this point we know it's not ETH - console.log("ERC20 Fast swap on") + console.log("ERC20 Fast Bridge") res = await dispatch( approveERC20( - powAmount(value, token.decimals), + value_Wei_String, token.address, networkService.L1LPAddress ) @@ -105,32 +122,32 @@ function InputStepFast({ handleClose, token }) { } res = await dispatch( - depositL1LP(token.address, value) + depositL1LP(token.address, value_Wei_String) ) if (res) { - dispatch(setActiveHistoryTab1('Deposits')) + dispatch(setActiveHistoryTab1('Bridge to L2')) dispatch( openAlert( - `${token.symbol} was deposited to the L1LP. You will receive + `${token.symbol} was bridged to the L1LP. You will receive ${receivableAmount(value)} ${token.symbol} on L2` ) ) handleClose() } else { - dispatch(openError('Failed to deposit ERC20')) + dispatch(openError('Failed to bridge ERC20')) } } const receivableAmount = (value) => { - return (Number(value) * ((100 - Number(feeRate)) / 100)).toFixed(2) + return (Number(value) * ((100 - Number(feeRate)) / 100)).toFixed(3) } useEffect(() => { if (typeof(token) !== 'undefined') { - networkService.L2LPBalance(token.addressL2,token.decimals).then((res) => { - setLPBalance(Number(res).toFixed(2)) + networkService.L2LPBalance(token.addressL2).then((res) => { + setLPBalance(Number(logAmount(res, token.decimals)).toFixed(3)) }) networkService.getTotalFeeRate().then((feeRate) => { setFeeRate(feeRate) @@ -151,54 +168,74 @@ function InputStepFast({ handleClose, token }) { let buttonLabel_1 = 'CANCEL' if( depositLoading || approvalLoading ) buttonLabel_1 = 'CLOSE WINDOW' - let buttonLabel_2 = 'Deposit' + let buttonLabel_2 = 'Bridge' if(depositLoading) { - buttonLabel_2 = "Depositing..." + buttonLabel_2 = "Bridging..." } else if (approvalLoading) { buttonLabel_2 = "Approving..." } - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down('md')); + const theme = useTheme() + const isMobile = useMediaQuery(theme.breakpoints.down('md')) + + let valueIsValid = false + + if( !!value && + new BN(value).gt(new BN(0.0)) && + new BN(value).lte(new BN(maxValue)) + ) { + valueIsValid = true + } return ( <> - Fast Deposit + Fast Bridge {label} {setAmount(i.target.value)}} + onChange={(i)=>{ + 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} variant="standard" newStyle /> - {valueIsValid && token && token.symbol === 'ETH' && ( + {valueIsValid && token && ( - {value && `You will receive ${receivableAmount(value)} oETH ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} on L2.`} + {`You will receive ${receivableAmount(value)} ${token.symbol} ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} on L2.`} )} - {valueIsValid && token && token.symbol !== 'ETH' && ( + {!!token && token.symbol === 'OMG' && ( - {value && `You will receive ${receivableAmount(value)} ${token.symbol} ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} on L2.`} + NOTE: The OMG Token was minted in 2017 and it does not conform to the ERC20 token standard. + In some cases, three interactions with MetaMask are needed. If you are bridging out of a + new wallet, it starts out with a 0 approval, and therefore, only two interactions with + MetaMask will be needed. )} - {Number(LPBalance) < Number(value) && ( + {Number(value) > Number(LPBalance) && ( - The liquidity pool balance (of {LPBalance}) is too low to cover your fast deposit. Please - use the traditional deposit or reduce the amount. + The liquidity pool balance (of {LPBalance}) is too low to cover your fast bridge. Please + use the traditional bridge or reduce the amount. )} @@ -222,7 +259,7 @@ function InputStepFast({ handleClose, token }) { color='primary' variant="contained" loading={depositLoading || approvalLoading} - tooltip="Your deposit is still pending. Please wait for confirmation." + tooltip={depositLoading ? "Your transaction is still pending. Please wait for confirmation." : "Click here to bridge your funds to L2"} disabled={disabledSubmit} triggerTime={new Date()} size="large" diff --git a/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStep.js b/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStep.js index f491e5278051..082b9536b558 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStep.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/exit/steps/DoExitStep.js @@ -30,112 +30,129 @@ import { selectLoading } from 'selectors/loadingSelector' import { selectSignatureStatus_exitTRAD } from 'selectors/signatureSelector' import { selectLookupPrice } from 'selectors/lookupSelector' -import { amountToUsd, logAmount } from 'util/amountConvert' +import { amountToUsd, logAmount, toWei_String } from 'util/amountConvert' import { WrapperActionsModal } from 'components/modal/Modal.styles' import { Box } from '@material-ui/system' +import BN from 'bignumber.js' + function DoExitStep({ handleClose, token }) { const dispatch = useDispatch() - const [value, setValue] = useState('') + const [ value, setValue ] = useState('') + const [ value_Wei_String, setValue_Wei_String ] = useState('0') //support for Use Max + const [disabledSubmit, setDisabledSubmit] = useState(true) - const exitLoading = useSelector(selectLoading(['EXIT/CREATE'])) + const loading = useSelector(selectLoading(['EXIT/CREATE'])) + const signatureStatus = useSelector(selectSignatureStatus_exitTRAD) const lookupPrice = useSelector(selectLookupPrice) + const maxValue = logAmount(token.balance, token.decimals) - const valueIsValid = value > 0 && value <= maxValue - async function doExit() { + function setAmount(value) { + + console.log("setAmount") - let res = await dispatch(exitBOBA(token.address, value)) + 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) { + setDisabledSubmit(true) + } else { + setDisabledSubmit(false) + } + + setValue(value) + } + + async function doExit() { - //person will receive ETH on the L1, not oETH - let currencyL1 = token.symbol + console.log("Amount to exit:", value_Wei_String) - if (currencyL1 === 'oETH') - currencyL1 = 'ETH' + let res = await dispatch(exitBOBA(token.address, value_Wei_String)) if (res) { dispatch( openAlert( - `${token.symbol} was exited to L1. You will receive - ${Number(value).toFixed(2)} ${currencyL1} + `${token.symbol} was bridged to L1. You will receive + ${Number(value).toFixed(3)} ${token.symbol} on L1 in 7 days.` ) ) handleClose() } else { - dispatch(openError(`Failed to exit L2`)) + dispatch(openError(`Failed to bridge to L1`)) } } - function setExitAmount(value) { - if (Number(value) > 0 && Number(value) < Number(token.balance)) { - setDisabledSubmit(false) - } else { - setDisabledSubmit(true) - } - setValue(value) - } - const theme = useTheme() const isMobile = useMediaQuery(theme.breakpoints.down('md')) let buttonLabel = 'CANCEL' - if( exitLoading ) buttonLabel = 'CLOSE WINDOW' + if( loading ) buttonLabel = 'CLOSE WINDOW' useEffect(() => { - if (signatureStatus && exitLoading) { + if (signatureStatus && loading) { //we are all set - can close the window //transaction has been sent and signed handleClose() } - }, [ signatureStatus, exitLoading, handleClose ]) + }, [ signatureStatus, loading, handleClose ]) + + let valueIsValid = false + + if( !!value && + new BN(value).gt(new BN(0.0)) && + new BN(value).lte(new BN(maxValue)) + ) { + valueIsValid = true + } return ( <> - Standard Exit ({`${token ? token.symbol : ''}`}) + Classic Bridge to L1 ({`${token ? token.symbol : ''}`}) {setExitAmount(i.target.value)}} + onChange={(i)=>{ + 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} variant="standard" newStyle /> - {valueIsValid && token && token.symbol === 'oETH' && ( - - {value && - `You will receive ${Number(value).toFixed(2)} ETH - ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} - on L1. - Your funds will be available on L1 in 7 days.`} - - )} - - {valueIsValid && token && token.symbol !== 'oETH' && ( + {valueIsValid && token && ( {value && - `You will receive ${Number(value).toFixed(2)} ${token.symbol} - ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} - on L1. - Your funds will be available on L1 in 7 days.`} + `You will receive ${Number(value).toFixed(3)} ${token.symbol} + ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} + on L1. Your funds will be available on L1 in 7 days.`} )} - {exitLoading && ( + {loading && ( - This window will automatically close when your transaction has been signed and submitted. + This window will close when your transaction has been signed and submitted. )} @@ -153,14 +170,14 @@ function DoExitStep({ handleClose, token }) { onClick={doExit} color="primary" variant="contained" - loading={exitLoading} - tooltip="Your exit is still pending. Please wait for confirmation." + loading={loading} + tooltip={loading ? "Your transaction is still pending. Please wait for confirmation." : "Click here to bridge your funds to L1"} disabled={disabledSubmit} triggerTime={new Date()} fullWidth={isMobile} size="large" > - Exit + Bridge to L1 )} 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 c811b4451341..3eeb29c85838 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 @@ -27,7 +27,7 @@ import { selectLookupPrice } from 'selectors/lookupSelector' import Button from 'components/button/Button' import Input from 'components/input/Input' -import { amountToUsd, logAmount, powAmount } from 'util/amountConvert' +import { amountToUsd, logAmount, toWei_String } from 'util/amountConvert' import networkService from 'services/networkService' import { Typography, useMediaQuery } from '@material-ui/core' @@ -35,68 +35,78 @@ import { useTheme } from '@emotion/react' import { WrapperActionsModal } from 'components/modal/Modal.styles' import { Box } from '@material-ui/system' +import BN from 'bignumber.js' + function DoExitStepFast({ handleClose, token }) { const dispatch = useDispatch() - const [value, setValue] = useState('') + const [ value, setValue ] = useState('') + const [ value_Wei_String, setValue_Wei_String ] = useState('0') //support for Use Max + const [LPBalance, setLPBalance] = useState(0) const [feeRate, setFeeRate] = useState(0) const [disabledSubmit, setDisabledSubmit] = useState(true) - const exitLoading = useSelector(selectLoading(['EXIT/CREATE'])) + const loading = useSelector(selectLoading(['EXIT/CREATE'])) + const lookupPrice = useSelector(selectLookupPrice) const signatureStatus = useSelector(selectSignatureStatus_exitLP) + const maxValue = logAmount(token.balance, token.decimals) - const valueIsValid = value > 0 && value <= maxValue function setAmount(value) { - if ( - Number(value) > 0 && - Number(value) < Number(LPBalance) && - Number(value) < Number(token.balance) - ) { - setDisabledSubmit(false) - } else { + + 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) { setDisabledSubmit(true) + } else { + setDisabledSubmit(false) } + setValue(value) } const receivableAmount = (value) => { - return (Number(value) * ((100 - Number(feeRate)) / 100)).toFixed(2) + return (Number(value) * ((100 - Number(feeRate)) / 100)).toFixed(3) } async function doExit() { + console.log("Amount to exit:", value_Wei_String) + let res = await dispatch( depositL2LP( token.address, - powAmount(value, token.decimals) //take a value, convert to 18 decimals, generate string + value_Wei_String ) ) - let currencyL1 = token.symbol - - //person will receive ETH on the L1, not oETH - if (currencyL1 === 'oETH') { - currencyL1 = 'ETH' - } - if (res) { - dispatch(openAlert(`${token.symbol} was deposited into the L2 liquidity pool. - You will receive ${receivableAmount(value)} ${currencyL1} on L1.`)) + dispatch( + openAlert( + `${token.symbol} was bridged. You will receive + ${receivableAmount(value)} ${token.symbol} on L1.` + ) + ) handleClose() } else { - dispatch(openError(`Failed to fast exit funds from L2`)); + dispatch(openError(`Failed to fast bridge funds to L1`)) } } useEffect(() => { if (typeof(token) !== 'undefined') { - networkService.L1LPBalance(token.addressL1, token.decimals).then((res) => { - setLPBalance(Number(res).toFixed(2)) + networkService.L1LPBalance(token.addressL1).then((res) => { + setLPBalance(Number(logAmount(res, token.decimals)).toFixed(3)) }) networkService.getTotalFeeRate().then((feeRate) => { setFeeRate(feeRate) @@ -105,60 +115,66 @@ function DoExitStepFast({ handleClose, token }) { // to clean up state and fix the // error in console for max state update. return ()=>{ - setLPBalance(0); - setFeeRate(0); + setLPBalance(0) + setFeeRate(0) } }, [ token ]) useEffect(() => { - if (signatureStatus && exitLoading) { + if (signatureStatus && loading) { //we are all set - can close the window //transaction has been sent and signed handleClose() } - }, [ signatureStatus, exitLoading, handleClose ]) + }, [ signatureStatus, loading, handleClose ]) + + const feeLabel = 'There is a ' + feeRate + '% fee.' - const label = 'There is a ' + feeRate + '% fee.' const theme = useTheme() const isMobile = useMediaQuery(theme.breakpoints.down('md')) + let valueIsValid = false + + if( !!value && + new BN(value).gt(new BN(0.0)) && + new BN(value).lte(new BN(maxValue)) + ) { + valueIsValid = true + } + let buttonLabel = 'CANCEL' - if( exitLoading ) buttonLabel = 'CLOSE WINDOW' + if( loading ) buttonLabel = 'CLOSE WINDOW' return ( <> - Fast Exit + Fast Bridge to L1 - {label} + {feeLabel} {setAmount(i.target.value)}} + onChange={(i)=>{ + 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" /> - {valueIsValid && token && token.symbol === 'oETH' && ( - - {value && - `You will receive - ${receivableAmount(value)} - ETH - ${!!amountToUsd(value, lookupPrice, token) ? `($${amountToUsd(value, lookupPrice, token).toFixed(2)})`: ''} - on L1.` - } - - )} - - {valueIsValid && token && token.symbol !== 'oETH' && ( + {valueIsValid && token && ( {value && `You will receive @@ -172,12 +188,12 @@ function DoExitStepFast({ handleClose, token }) { {Number(LPBalance) < Number(value) && ( - The liquidity pool balance (of {LPBalance}) is too low to cover your exit - please - use the traditional exit or reduce the amount to exit. + The liquidity pool balance (of {LPBalance}) is too low to cover your bridge - please + use the classic bridge or reduce the amount. )} - {exitLoading && ( + {loading && ( This window will automatically close when your transaction has been signed and submitted. @@ -196,14 +212,14 @@ function DoExitStepFast({ handleClose, token }) { onClick={doExit} color='primary' variant='contained' - loading={exitLoading} - tooltip='Your exit is still pending. Please wait for confirmation.' + loading={loading} + tooltip={loading ? "Your transaction is still pending. Please wait for confirmation." : "Click here to bridge your funds to L1"} disabled={disabledSubmit} triggerTime={new Date()} fullWidth={isMobile} size='large' > - Exit L2 + Bridge to L1 diff --git a/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmDepositModal.js b/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmDepositModal.js index b66f69598835..97830a337b52 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmDepositModal.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmDepositModal.js @@ -9,7 +9,7 @@ import { getFarmInfo } from 'actions/farmAction'; import Button from 'components/button/Button'; import Modal from 'components/modal/Modal'; import Input from 'components/input/Input'; -import { logAmount, powAmount } from 'util/amountConvert'; +import { logAmount, powAmount, toWei_String } from 'util/amountConvert'; import networkService from 'services/networkService'; @@ -28,11 +28,11 @@ class FarmDepositModal extends React.Component { this.state = { open, stakeToken, - stakeValue: null, + stakeValue: '', stakeValueValid: false, - //stakeValueBadEntry: false, + value_Wei_String: '', // allowance - approvedAllowance: 0, + approvedAllowance: '', // loading loading: false, } @@ -56,7 +56,9 @@ class FarmDepositModal extends React.Component { stakeToken.currency, stakeToken.LPAddress ) + approvedAllowance = approvedAllowance.toString() } + this.setState({ approvedAllowance, stakeToken }) } @@ -64,11 +66,6 @@ class FarmDepositModal extends React.Component { getMaxTransferValue () { const { stakeToken } = this.state - // const transferingBalanceObject = (stakeToken.L1orL2Pool === 'L1LP' ? layer1Balance : layer2Balance) - // .find(i => i.currency === stakeToken.currency); - // if (!transferingBalanceObject) { - // return; - // } return logAmount(stakeToken.balance, stakeToken.decimals) } @@ -78,27 +75,29 @@ class FarmDepositModal extends React.Component { handleStakeValue(value) { + const { stakeToken } = this.state + if( value && - Number(value) > 0 && - Number(value) < Number(this.getMaxTransferValue()) + Number(value) > 0.0 && + Number(value) <= Number(this.getMaxTransferValue()) ) { this.setState({ stakeValue: value, stakeValueValid: true, - //stakeValueBadEntry: false, + value_Wei_String: toWei_String(value, stakeToken.decimals) }) } else { this.setState({ - stakeValue: null, + stakeValue: value, stakeValueValid: false, - //stakeValueBadEntry: true, + value_Wei_String: '' }) } } async handleApprove() { - const { stakeToken, stakeValue } = this.state + const { stakeToken, value_Wei_String } = this.state this.setState({ loading: true }) @@ -106,13 +105,13 @@ class FarmDepositModal extends React.Component { if (stakeToken.L1orL2Pool === 'L2LP') { approveTX = await networkService.approveERC20_L2LP( - powAmount(stakeValue, stakeToken.decimals), + value_Wei_String, stakeToken.currency, ) } else if (stakeToken.L1orL2Pool === 'L1LP') { approveTX = await networkService.approveERC20_L1LP( - powAmount(stakeValue, stakeToken.decimals), + value_Wei_String, stakeToken.currency, ) } @@ -126,6 +125,7 @@ class FarmDepositModal extends React.Component { stakeToken.currency, stakeToken.LPAddress ) + approvedAllowance = approvedAllowance.toString() } this.setState({ approvedAllowance, loading: false }) @@ -137,25 +137,25 @@ class FarmDepositModal extends React.Component { async handleConfirm() { - const { stakeToken, stakeValue } = this.state + const { stakeToken, value_Wei_String } = this.state this.setState({ loading: true }) const addLiquidityTX = await networkService.addLiquidity( stakeToken.currency, - stakeValue, + value_Wei_String, stakeToken.L1orL2Pool, - stakeToken.decimals ) if (addLiquidityTX) { this.props.dispatch(openAlert("Your liquidity was added")) this.props.dispatch(getFarmInfo()) - this.setState({ loading: false, stakeValue: '' }) + this.setState({ loading: false, stakeValue: '', value_Wei_String: ''}) this.props.dispatch(closeModal("farmDepositModal")) } else { this.props.dispatch(openError("Failed to add liquidity")) - this.setState({ loading: false, stakeValue: '' }) + this.setState({ loading: false, stakeValue: '', value_Wei_String: ''}) + this.props.dispatch(closeModal("farmDepositModal")) } } @@ -174,9 +174,9 @@ class FarmDepositModal extends React.Component { let allowanceGTstake = false - if ( approvedAllowance > 0 && - Number(stakeValue) > 0 && - new BN(approvedAllowance).gte(powAmount(stakeValue, stakeToken.decimals)) + if ( Number(approvedAllowance) > 0 && + Number(stakeValue) > 0 && + new BN(approvedAllowance).gte(powAmount(stakeValue, stakeToken.decimals)) ) { allowanceGTstake = true } @@ -197,9 +197,11 @@ class FarmDepositModal extends React.Component { placeholder={`Amount to stake`} value={stakeValue} type="number" - onChange={i=>{this.handleStakeValue(i.target.value)}} unit={stakeToken.symbol} maxValue={this.getMaxTransferValue()} + onChange={i=>{this.handleStakeValue(i.target.value)}} + onUseMax={i=>{this.handleStakeValue(this.getMaxTransferValue())}} + allowUseAll={true} newStyle variant="standard" /> @@ -236,7 +238,6 @@ class FarmDepositModal extends React.Component { } - {(stakeValueValid && allowanceGTstake) && <> diff --git a/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmWithdrawModal.js b/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmWithdrawModal.js index 9d8039b71f98..3f193249313d 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmWithdrawModal.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/farm/FarmWithdrawModal.js @@ -1,163 +1,232 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { isEqual } from 'lodash'; +import React from 'react' +import { connect } from 'react-redux' +import { isEqual } from 'lodash' -import { closeModal, openAlert, openError } from 'actions/uiAction'; -import { getFarmInfo } from 'actions/farmAction'; +import { closeModal, openAlert, openError } from 'actions/uiAction' +import { getFarmInfo } from 'actions/farmAction' -import Button from 'components/button/Button'; -import Modal from 'components/modal/Modal'; -import InputSelect from 'components/inputselect/InputSelect'; -import { logAmount } from 'util/amountConvert'; +import Button from 'components/button/Button' +import Modal from 'components/modal/Modal' +import Input from 'components/input/Input' +import { logAmount, toWei_String } from 'util/amountConvert' -import networkService from 'services/networkService'; +import networkService from 'services/networkService' -import { Typography } from '@material-ui/core'; -import { WrapperActionsModal } from 'components/modal/Modal.styles'; +import { Typography } from '@material-ui/core' +import { WrapperActionsModal } from 'components/modal/Modal.styles' + +import BN from 'bignumber.js' class FarmWithdrawModal extends React.Component { + constructor(props) { - super(props); + super(props) - const { open, balance } = this.props; - const { withdrawToken, userInfo } = this.props.farm; + const { + open + } = this.props + + const { + withdrawToken, + userInfo + } = this.props.farm this.state = { open, withdrawToken, - withdrawValue: '', - // balance + disableSubmit: true, userInfo, - layer1Balance: balance.layer1, - layer2Balance: balance.layer2, - LPBalance: 0, - // loading loading: false, + //each value has an approximate version and a precise version + value: 0, + value_Wei_String: '', + maxValue: 0, + maxValue_Wei_String: '', + LPBalance: 0, + LPBalance_Wei_String: '', } } + async componentDidMount() { + + const { withdrawToken } = this.props.farm + + let LPBalance_Wei_String = '' + + if (withdrawToken.L1orL2Pool === 'L1LP') { + LPBalance_Wei_String = await networkService.L1LPBalance(withdrawToken.currency) + } else { + LPBalance_Wei_String = await networkService.L2LPBalance(withdrawToken.currency) + } + + //console.log("LPBalance current", LPBalance_Wei_String) + + this.setState({ + LPBalance: logAmount(LPBalance_Wei_String, withdrawToken.decimals), + LPBalance_Wei_String + }) + + this.setMaxTransferValue() + + } + async componentDidUpdate(prevState) { - const { open, balance } = this.props; - const { withdrawToken, userInfo } = this.props.farm; + + const { open } = this.props + + const { withdrawToken, userInfo } = this.props.farm if (prevState.open !== open) { - this.setState({ open }); + this.setState({ open }) } if (!isEqual(prevState.farm.withdrawToken, withdrawToken)) { - let LPBalance = 0; - if (withdrawToken.L1orL2Pool === 'L1LP') { - LPBalance = await networkService.L1LPBalance(withdrawToken.currency); - } else { - LPBalance = await networkService.L2LPBalance(withdrawToken.currency); - } - this.setState({ withdrawToken, LPBalance }); + this.setState({ withdrawToken }) } if (!isEqual(prevState.farm.userInfo, userInfo)) { - this.setState({ userInfo }); + this.setState({ userInfo }) } - if (!isEqual(prevState.balance, balance)) { - this.setState({ - layer1Balance: balance.layer1, - layer2Balance: balance.layer2 - }); + } + + setAmount(value, value_Wei_String) { + + const { maxValue } = this.state + + const tooSmall = new BN(value).lte(new BN(0.0)) + const tooBig = new BN(value).gt(new BN(maxValue)) + + if (tooSmall || tooBig) { + this.setState({ + value : 0, + value_Wei_String: '', + disableSubmit: true + }) + } else { + this.setState({ + value, + value_Wei_String, + disableSubmit: false + }) } + } - getMaxTransferValue () { - const { userInfo, withdrawToken } = this.state; - let transferingBalance = 0 + setMaxTransferValue() { + + const { userInfo, withdrawToken, LPBalance_Wei_String } = this.state + + let balance_Wei_String = '' + if (typeof userInfo[withdrawToken.L1orL2Pool][withdrawToken.currency] !== 'undefined') { - transferingBalance = userInfo[withdrawToken.L1orL2Pool][withdrawToken.currency].amount + balance_Wei_String = userInfo[withdrawToken.L1orL2Pool][withdrawToken.currency].amount } - return logAmount(transferingBalance, withdrawToken.decimals); + + //BUT, if the current balance is lower than what you staked, can only withdraw the balance + const poolTooSmall = new BN(LPBalance_Wei_String).lt(new BN(balance_Wei_String)) + + if (poolTooSmall) { + console.log("pool smaller than stake",balance_Wei_String) + this.setState({ + maxValue: logAmount(LPBalance_Wei_String, withdrawToken.decimals), + maxValue_Wei_String: LPBalance_Wei_String + }) + } else { + //pool big enough to cover entire withdrawal + console.log("pool large enough",LPBalance_Wei_String) + this.setState({ + maxValue: logAmount(balance_Wei_String, withdrawToken.decimals), + maxValue_Wei_String: balance_Wei_String + }) + } + } handleClose() { - this.props.dispatch(closeModal("farmWithdrawModal")); + this.props.dispatch(closeModal("farmWithdrawModal")) } async handleConfirm() { - const { withdrawToken, withdrawValue } = this.state; - this.setState({ loading: true }); + const { withdrawToken, value_Wei_String } = this.state; + + this.setState({ loading: true }) const withdrawLiquidityTX = await networkService.withdrawLiquidity( withdrawToken.currency, - withdrawValue, + value_Wei_String, withdrawToken.L1orL2Pool, - withdrawToken.decimals, - ); + ) + if (withdrawLiquidityTX) { - this.props.dispatch(openAlert("Your liquidity was withdrawn.")); - this.props.dispatch(getFarmInfo()); - this.setState({ loading: false, withdrawValue: '' }); - this.props.dispatch(closeModal("farmWithdrawModal")); + this.props.dispatch(openAlert("Your liquidity was withdrawn.")) + this.props.dispatch(getFarmInfo()) + this.setState({ + loading: false, + value: '', + value_Wei_String: '' + }) + this.props.dispatch(closeModal("farmWithdrawModal")) } else { - this.props.dispatch(openError("Failed to withdraw liquidity.")); - this.setState({ loading: false, withdrawValue: '' }); + this.props.dispatch(openError("Failed to withdraw liquidity.")) + this.setState({ + loading: false, + value: '', + value_Wei_String: '' + }) + this.props.dispatch(closeModal("farmWithdrawModal")) } } render() { + const { open, - withdrawToken, withdrawValue, - userInfo, - layer1Balance, layer2Balance, + withdrawToken, + value, LPBalance, loading, - } = this.state; - - - const selectOptions = (withdrawToken.L1orL2Pool === 'L1LP' ? layer1Balance : layer2Balance) - .reduce((acc, cur) => { - if (cur.currency.toLowerCase() === withdrawToken.currency.toLowerCase()) { - acc.push({ - title: cur.symbol, - value: cur.currency, - subTitle: `Balance: ${logAmount(userInfo[withdrawToken.L1orL2Pool][withdrawToken.currency].amount, cur.decimals)}` - }) - } - return acc; - }, []); + disableSubmit, + maxValue, + maxValue_Wei_String + } = this.state return ( - {this.handleClose()}}> + + {this.handleClose()}} + > + Withdraw {`${withdrawToken.symbol}`} - { - this.setState({withdrawValue: i.target.value}); - }} - onSelect={i => {}} - selectOptions={selectOptions} - selectValue={withdrawToken.currency} unit={withdrawToken.symbol} - maxValue={this.getMaxTransferValue()} + maxValue={maxValue} + onChange={(i)=>{ + this.setAmount(i.target.value, toWei_String(i.target.value, withdrawToken.decimals)) + }} + allowUseAll={true} + onUseMax={(i)=>{ + this.setAmount(maxValue, maxValue_Wei_String) + }} disabledSelect={true} variant="standard" newStyle /> - {Number(withdrawValue) > Number(this.getMaxTransferValue()) && - - You don't have enough {withdrawToken.symbol} to withdraw. - - } - {Number(withdrawValue) > Number(LPBalance) && + {Number(value) > Number(LPBalance) && - We don't have enough {withdrawToken.symbol} in the {' '} - {withdrawToken.L1orL2Pool === 'L1LP' ? 'L1' : 'L2'} liquidity pool. - Please contact us. + Note: There is currently insufficient {withdrawToken.symbol} in the {' '} + {withdrawToken.L1orL2Pool === 'L1LP' ? 'L1' : 'L2'} liquidity pool + to withdraw your full stake. At this time, you can only withdraw up to + {Number(LPBalance).toFixed(2)} {withdrawToken.symbol}. } @@ -174,12 +243,7 @@ class FarmWithdrawModal extends React.Component { color='primary' size="large" variant="contained" - disabled={ - Number(this.getMaxTransferValue()) < Number(withdrawValue) || - Number(withdrawValue) > Number(LPBalance) || - withdrawValue === '' || - !withdrawValue - } + disabled={!!disableSubmit} loading={loading} > CONFIRM @@ -196,4 +260,4 @@ const mapStateToProps = state => ({ balance: state.balance, }); -export default connect(mapStateToProps)(FarmWithdrawModal); +export default connect(mapStateToProps)(FarmWithdrawModal) diff --git a/packages/omgx/wallet-frontend/src/containers/modals/transfer/TransferModal.js b/packages/omgx/wallet-frontend/src/containers/modals/transfer/TransferModal.js index 38f28b56a371..ba068aa74be7 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/transfer/TransferModal.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/transfer/TransferModal.js @@ -21,11 +21,11 @@ import { transfer } from 'actions/networkAction'; import { closeModal, openAlert } from 'actions/uiAction'; import { selectLoading } from 'selectors/loadingSelector'; -import Button from 'components/button/Button'; -import Modal from 'components/modal/Modal'; +import Button from 'components/button/Button' +import Modal from 'components/modal/Modal' -import { amountToUsd, logAmount } from 'util/amountConvert' -import networkService from 'services/networkService'; +import { amountToUsd, logAmount, toWei_String } from 'util/amountConvert' +import networkService from 'services/networkService' import Input from 'components/input/Input'; import { selectLookupPrice } from 'selectors/lookupSelector'; @@ -33,31 +33,63 @@ import { Box, Typography, useMediaQuery } from '@material-ui/core'; import { useTheme } from '@emotion/react'; import { WrapperActionsModal } from 'components/modal/Modal.styles'; +import BN from 'bignumber.js' + function TransferModal ({ open, token, minHeight }) { + const dispatch = useDispatch() const [ value, setValue ] = useState('') + const [ value_Wei_String, setValue_Wei_String ] = useState('0') //support for Use Max + const [ recipient, setRecipient ] = useState('') - const loading = useSelector(selectLoading([ 'TRANSFER/CREATE' ])); + const [ disabledSubmit, setDisabledSubmit ] = useState(true) + + const loading = useSelector(selectLoading([ 'TRANSFER/CREATE' ])) const wAddress = networkService.account ? networkService.account : '' - const lookupPrice = useSelector(selectLookupPrice); + const lookupPrice = useSelector(selectLookupPrice) + + const theme = useTheme() + const isMobile = useMediaQuery(theme.breakpoints.down('md')) + + let maxValue = '0' + + if(token) { + maxValue = logAmount(token.balance, token.decimals) + } + + function setAmount(value) { + + console.log("setAmount") - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down('md')); + 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) { + setDisabledSubmit(true) + } else { + setDisabledSubmit(false) + } + + setValue(value) + } async function submit () { - if ( - value > 0 && - token.address && - recipient - ) { + if ( token.address && recipient ) + { try { - const transferResponseGood = await dispatch(transfer(recipient, value, token.address)); + console.log("Amount to transfer:", value_Wei_String) + const transferResponseGood = await dispatch( + transfer(recipient, value_Wei_String, token.address) + ) if (transferResponseGood) { - dispatch(openAlert('Transaction submitted')); - handleClose(); + dispatch(openAlert('Transaction submitted')) + handleClose() } else { //error handled elsewhere handleClose() @@ -70,13 +102,21 @@ function TransferModal ({ open, token, minHeight }) { function handleClose () { setValue('') + setValue_Wei_String('0') setRecipient('') dispatch(closeModal('transferModal')) } - const disabledTransfer = value <= 0 || - !token.address || - !recipient + //checked + let convertToUSD = false + if( Object.keys(lookupPrice) && + !!value && + new BN(value).gt(new BN(0.0)) && + new BN(value).lte(new BN(maxValue)) && + !!amountToUsd(value, lookupPrice, token) + ) { + convertToUSD = true + } if(typeof(token) === 'undefined') return @@ -107,20 +147,28 @@ function TransferModal ({ open, token, minHeight }) { {setValue(i.target.value)}} + onChange={(i)=>{ + 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={logAmount(token.balance, token.decimals)} + maxValue={maxValue} variant="standard" newStyle /> - {Object.keys(lookupPrice) && !!value && !!amountToUsd(value, lookupPrice, token) && ( + {convertToUSD && ( - {`Transfer value in USD: $${amountToUsd(value, lookupPrice, token).toFixed(2)}`} + {`Value in USD: $${amountToUsd(value, lookupPrice, token).toFixed(2)}`} )} @@ -139,8 +187,8 @@ function TransferModal ({ open, token, minHeight }) { color='primary' variant="contained" loading={loading} - tooltip='Your transfer is still pending. Please wait for confirmation.' - disabled={disabledTransfer} + tooltip={loading ? "Your transaction is still pending. Please wait for confirmation." : "Click here to bridge your funds to L1"} + disabled={disabledSubmit} triggerTime={new Date()} fullWidth={isMobile} size="large" diff --git a/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.js b/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.js index 71e8341eb8d6..e52c13fba3df 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.js +++ b/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.js @@ -15,7 +15,10 @@ limitations under the License. */ import React from 'react'; import { useDispatch } from 'react-redux' + +import Button from 'components/button/Button' import Modal from 'components/modal/Modal' + import { closeModal } from 'actions/uiAction' import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward' @@ -26,8 +29,11 @@ import { ReactComponent as Fox } from './../../../images/icons/fox-icon.svg' import { ReactComponent as Account } from './../../../images/icons/mm-account.svg' import { getAllNetworks } from 'util/masterConfig' + import store from 'store' +import networkService from 'services/networkService' + import * as styles from './WrongNetworkModal.module.scss' import { useTheme } from '@emotion/react' @@ -37,6 +43,19 @@ function WrongNetworkModal ({ open, onClose }) { const nw = getAllNetworks() const masterConfig = store.getState().setup.masterConfig + const networkLayer = store.getState().setup.netLayer + + /* + This is fired if the internal setting of the gateway does not match the + MetaMask configuration. There are multiple networks (e.g. mainent and rinkeby), + and multiple layers, e.g. L1 and L2 + */ + + console.log("WNM masterConfig",masterConfig) + console.log("WNM networkLayer",networkLayer) + + //Next figure out the right labels and targets + const textLabel = nw[masterConfig].MM_Label const iconLabel = nw[masterConfig].MM_Label @@ -48,6 +67,10 @@ function WrongNetworkModal ({ open, onClose }) { dispatch(closeModal('wrongNetworkModal')) } + async function correctChain() { + await networkService.correctChain( networkLayer ) + } + return ( - Please Change Network + Incorrect Network - - To use "{textLabel}", please switch MetaMask to that network. + + To use {textLabel}, please change network. - + + + + Or, you can change manually, by going to MetaMask and + clicking in the top bar. + + +
@@ -74,8 +113,9 @@ function WrongNetworkModal ({ open, onClose }) {
+ ); } -export default React.memo(WrongNetworkModal); +export default React.memo(WrongNetworkModal) diff --git a/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.module.scss b/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.module.scss index 735d45a44b3e..f5f9fe0ce71c 100644 --- a/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.module.scss +++ b/packages/omgx/wallet-frontend/src/containers/modals/wrongnetwork/WrongNetworkModal.module.scss @@ -3,8 +3,8 @@ .metamask { background: #F2F3F4; border: 1px solid #A9A9A9; - width: 350px; - height: 55px; + width: 300px; + height: 45px; border-radius: 2px; display: flex; flex-direction: row; diff --git a/packages/omgx/wallet-frontend/src/containers/nft/Nft.js b/packages/omgx/wallet-frontend/src/containers/nft/Nft.js index 41de1cdff3f8..5ee8facc73d7 100644 --- a/packages/omgx/wallet-frontend/src/containers/nft/Nft.js +++ b/packages/omgx/wallet-frontend/src/containers/nft/Nft.js @@ -109,6 +109,8 @@ class Nft extends React.Component { const numberOfContracts = Object.keys(contracts).length const layer = networkService.L1orL2 + const mintDisabled = numberOfContracts > 0 ? false : true + if(layer === 'L1') { return
@@ -171,7 +173,12 @@ class Nft extends React.Component { sx={{mt: 1, mb: 5}} > - + diff --git a/packages/omgx/wallet-frontend/src/containers/transactions/Deposits.js b/packages/omgx/wallet-frontend/src/containers/transactions/Deposits.js index 4025d38bf55a..459e626414a7 100644 --- a/packages/omgx/wallet-frontend/src/containers/transactions/Deposits.js +++ b/packages/omgx/wallet-frontend/src/containers/transactions/Deposits.js @@ -19,6 +19,9 @@ import { useSelector } from 'react-redux' import moment from 'moment' import { selectLoading } from 'selectors/loadingSelector' +import { selectTokens } from 'selectors/tokenSelector' + +import { logAmount } from 'util/amountConvert' import Pager from 'components/pager/Pager' import Transaction from 'components/transaction/Transaction' @@ -35,6 +38,7 @@ function Deposits({ searchHistory, transactions }) { const [page, setPage] = useState(1); const loading = useSelector(selectLoading(['TRANSACTION/GETALL'])); + const tokenList = useSelector(selectTokens); useEffect(() => { setPage(1); @@ -80,11 +84,29 @@ function Deposits({ searchHistory, transactions }) {
Loading deposits...
)} {paginatedDeposits.map((i, index) => { - const metaData = typeof (i.typeTX) === 'undefined' ? '' : i.typeTX + + if(i.depositL2 === false) { + return null + } + + const typeTX = typeof(i.typeTX) === 'undefined' ? '' : i.typeTX + const activity = typeof(i.activity) === 'undefined' ? '' : ' (' + i.activity + ')' + let metaData = typeTX + ' ' + activity + const chain = (i.chain === 'L1pending') ? 'L1' : i.chain let details = null + let amountTx = null; + if (i.action && i.action.token) { + const token = tokenList[i.action.token.toLowerCase()]; + if (!!token) { + let amount = logAmount(i.action.amount, token.decimals, 3); + let symbol = token[`symbol${chain}`]; + amountTx = `${amount} ${symbol}`; + } + } + if( i.crossDomainMessage && i.crossDomainMessage.l2BlockHash ) { details = { blockHash: i.crossDomainMessage.l2BlockHash, @@ -101,11 +123,12 @@ function Deposits({ searchHistory, transactions }) { title={`Hash: ${i.hash}`} time={moment.unix(i.timeStamp).format('lll')} blockNumber={`Block ${i.blockNumber}`} - chain={`L1->L2 Deposit`} + chain={`Bridge to L2`} typeTX={`TX Type: ${metaData}`} detail={details} oriChain={chain} oriHash={i.hash} + amountTx={amountTx} /> ) })} diff --git a/packages/omgx/wallet-frontend/src/containers/transactions/Exits.js b/packages/omgx/wallet-frontend/src/containers/transactions/Exits.js index 06bc0b146720..921ae74ee5aa 100644 --- a/packages/omgx/wallet-frontend/src/containers/transactions/Exits.js +++ b/packages/omgx/wallet-frontend/src/containers/transactions/Exits.js @@ -19,6 +19,10 @@ import moment from 'moment' import { useSelector } from 'react-redux' import { selectLoading } from 'selectors/loadingSelector' +import { selectTokens } from 'selectors/tokenSelector' + +import { logAmount } from 'util/amountConvert' + import Transaction from 'components/transaction/Transaction' import Pager from 'components/pager/Pager' @@ -36,23 +40,31 @@ function Exits({ searchHistory, transactions, chainLink }) { const [page, setPage] = useState(1); - const loading = useSelector(selectLoading(['EXIT/GETALL'])); + const loading = useSelector(selectLoading(['EXIT/GETALL'])) + + const tokenList = useSelector(selectTokens) const _exits = transactions.filter(i => { return i.hash.includes(searchHistory) && ( i.to !== null && ( i.to.toLowerCase() === networkService.L2LPAddress.toLowerCase() || - //i.to.toLowerCase() === networkService.L2_ETH_Address.toLowerCase() || i.to.toLowerCase() === networkService.L2StandardBridgeAddress.toLowerCase() ) ) }) const renderExits = _exits.map((i, index) => { + + //these are other types of transactions like approvals + if(i.exitL2 === false) { + return null + } - const metaData = typeof (i.typeTX) === 'undefined' ? '' : i.typeTX const chain = (i.chain === 'L1pending') ? 'L1' : i.chain + const typeTX = typeof(i.typeTX) === 'undefined' ? '' : i.typeTX + const activity = typeof(i.activity) === 'undefined' ? '' : ' (' + i.activity + ')' + let metaData = typeTX + ' ' + activity let isExitable = false let details = null @@ -61,10 +73,20 @@ function Exits({ searchHistory, transactions, chainLink }) { const to = i.to.toLowerCase() + let amountTx = null; + + if (i.action && i.action.token) { + const token = Object.values(tokenList).find(t => t.addressL2.toLowerCase() === i.action.token.toLowerCase()); + if (!!token) { + let amount = logAmount(i.action.amount, token.decimals, 3); + let symbol = token[`symbol${chain}`]; + amountTx = `${amount} ${symbol}`; + } + } + //are we dealing with a traditional exit? if (to === networkService.L2StandardBridgeAddress.toLowerCase()) { - isExitable = moment().isAfter(moment.unix(i.crossDomainMessage.crossDomainMessageEstimateFinalizedTime)) if (isExitable) { @@ -92,7 +114,7 @@ function Exits({ searchHistory, transactions, chainLink }) { return ( ) }) diff --git a/packages/omgx/wallet-frontend/src/containers/transactions/History.js b/packages/omgx/wallet-frontend/src/containers/transactions/History.js index bd6cd2a6e2b0..2d8320360446 100644 --- a/packages/omgx/wallet-frontend/src/containers/transactions/History.js +++ b/packages/omgx/wallet-frontend/src/containers/transactions/History.js @@ -50,8 +50,8 @@ function History() { const isMobile = useMediaQuery(theme.breakpoints.down('md')); const dispatch = useDispatch() - const [startDate, setStartDate] = useState(null) - const [endDate, setEndDate] = useState(null) + const [startDate, setStartDate] = useState(new Date()) + const [endDate, setEndDate] = useState(new Date()) const [searchHistory, setSearchHistory] = useState('') @@ -61,7 +61,6 @@ function History() { //sort transactions by timeStamp const orderedTransactions = orderBy(unorderedTransactions, i => i.timeStamp, 'desc') - //'desc' or 'asc' const transactions = orderedTransactions.filter((i) => { if (startDate && endDate) { @@ -76,6 +75,9 @@ function History() { }); }, POLL_INTERVAL * 2); + console.log(startDate) + console.log(endDate) + return ( <> @@ -101,8 +103,8 @@ function History() { selected={startDate} onChange={(date) => setStartDate(date)} selectsStart - startDate={startDate} - endDate={endDate} + endDate={new Date(endDate)} + maxDate={new Date(endDate)} calendarClassName={theme.palette.mode} placeholderText={isMobile ? "From" : ""} popperClassName={styles.popperStyle} @@ -115,9 +117,8 @@ function History() { selected={endDate} onChange={(date) => setEndDate(date)} selectsEnd - startDate={startDate} - endDate={endDate} - minDate={startDate} + startDate={new Date(startDate)} + minDate={new Date(startDate)} calendarClassName={theme.palette.mode} placeholderText={isMobile ? "To" : ""} popperClassName={styles.popperStyle} @@ -129,7 +130,7 @@ function History() { {dispatch(setActiveHistoryTab1(tab))}} activeTab={activeTab1} - tabs={['All', 'Deposits', 'Exits']} + tabs={['All', 'Bridge to L2', 'Bridge to L1']} /> {activeTab1 === 'All' && ( @@ -139,14 +140,14 @@ function History() { /> )} - {activeTab1 === 'Deposits' && + {activeTab1 === 'Bridge to L2' && } - {activeTab1 === 'Exits' && + {activeTab1 === 'Bridge to L1' && { setPage(1); @@ -72,10 +76,27 @@ function Transactions({ searchHistory, transactions }) {
Loading...
)} {paginatedTransactions.map((i, index) => { - const metaData = typeof (i.typeTX) === 'undefined' ? '' : i.typeTX + + const typeTX = typeof(i.typeTX) === 'undefined' ? '' : i.typeTX + const activity = typeof(i.activity) === 'undefined' ? '' : ' (' + i.activity + ')' + let metaData = typeTX + ' ' + activity + const time = moment.unix(i.timeStamp).format('lll') let details = null const chain = (i.chain === 'L1pending') ? 'L1' : i.chain + + let amountTx = null + if (i.action && i.action.token) { + let token = tokenList[i.action.token.toLowerCase()]; + if (chain === 'L2') { + token = Object.values(tokenList).find(t => t.addressL2.toLowerCase() === i.action.token.toLowerCase()); + } + if (!!token) { + let amount = logAmount(i.action.amount, token.decimals, 3); + let symbol = token[`symbol${chain}`]; + amountTx = `${amount} ${symbol}`; + } + } if( i.crossDomainMessage && i.crossDomainMessage.l1BlockHash ) { details = { @@ -108,6 +129,7 @@ function Transactions({ searchHistory, transactions }) { detail={details} oriChain={chain} oriHash={i.hash} + amountTx={amountTx} /> ) })} diff --git a/packages/omgx/wallet-frontend/src/deployment/contracts/OMG/OMG.json b/packages/omgx/wallet-frontend/src/deployment/contracts/OMG/OMG.json new file mode 100644 index 000000000000..a3582a412e91 --- /dev/null +++ b/packages/omgx/wallet-frontend/src/deployment/contracts/OMG/OMG.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}] \ No newline at end of file diff --git a/packages/omgx/wallet-frontend/src/deployment/mainnet/addresses.json b/packages/omgx/wallet-frontend/src/deployment/mainnet/addresses.json index 69637198458f..d0e2b94a82ad 100644 --- a/packages/omgx/wallet-frontend/src/deployment/mainnet/addresses.json +++ b/packages/omgx/wallet-frontend/src/deployment/mainnet/addresses.json @@ -24,7 +24,7 @@ "L1": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", "L2": "0xdc0486f8bf31DF57a952bcd3c1d3e166e3d9eC8b" }, - "REP": { + "REPV2": { "L1": "0x221657776846890989a759ba2973e427dff5c9bb", "L2": "0x8b5B1E971862015bc058234FC11ce6C4a4c536dD" }, @@ -57,12 +57,12 @@ "L2": "0xeDB79B0FD84c81E870b2fCB1D3CcF366179bA6D2" } }, - "L2LiquidityPool": "0x9C133903F299f083F2ba4A7DAeb142643Fe1864D", - "L1LiquidityPool": "0x87b6C838486c836a1fb16716Df25D8E023fd541C", - "Proxy__L1LiquidityPool": "0x3256BD6Fc8b5fA48DB95914d0dF314465F3F7879", - "Proxy__L2LiquidityPool": "0x02fc14bC0dF6452FCC36496244eE2D043401582F", - "OVM_L1CrossDomainMessengerFast": "0x68ac1623ACf9eB9F88b65B5F229fE3e2c0d5789e", - "Proxy__OVM_L1CrossDomainMessengerFast": "0x841979bbC06Be7BFE28d9FadDac1A73e1Fb495C1", + "L2LiquidityPool": "0xB1a1B698E4c67c242441749C22575FA02B14D645", + "L1LiquidityPool": "0x3d95bE575576F813B9b18eE14ba041d3E013eC25", + "Proxy__L1LiquidityPool": "0x1A26ef6575B7BBB864d984D9255C069F6c361a14", + "Proxy__L2LiquidityPool": "0x3A92cA39476fF84Dc579C868D4D7dE125513B034", + "OVM_L1CrossDomainMessengerFast": "0xb7E757633857C2E6Ec7aab362c17E7a5913B4855", + "Proxy__OVM_L1CrossDomainMessengerFast": "0xD05b8fD53614e1569cAC01c6D8d41416d0a7257E", "L2TokenPool": "0x82B178EE692572e21D73d5F1ebC1c7c438Fc52DD", "AtomicSwap": "0xfCc9525fDDbafbD3393821F7dAf96F68Bba93294", "L1Message": "0x1E7C2Ed00FaaFeD62afC9DD630ACB8C8c6C16D52", diff --git a/packages/omgx/wallet-frontend/src/index.scss b/packages/omgx/wallet-frontend/src/index.scss index 23c8b84754f8..ffc4e741d335 100644 --- a/packages/omgx/wallet-frontend/src/index.scss +++ b/packages/omgx/wallet-frontend/src/index.scss @@ -233,6 +233,17 @@ $white500: rgba(255, 255, 255, 0.5); color: #FFFFFF !important; } + .react-datepicker__day--disabled { + opacity: 0.4 + } + .react-datepicker__day { + &:hover { + background-color: transparent; + color: #fff; + border-radius: 50%; + border: 0.2px solid #CCFF00; + } + } .react-datepicker__day--keyboard-selected, .react-datepicker__month-text--keyboard-selected, .react-datepicker__quarter-text--keyboard-selected, diff --git a/packages/omgx/wallet-frontend/src/pages/history/index.js b/packages/omgx/wallet-frontend/src/pages/history/index.js index d0c874da4155..9390d31ad12b 100644 --- a/packages/omgx/wallet-frontend/src/pages/history/index.js +++ b/packages/omgx/wallet-frontend/src/pages/history/index.js @@ -15,34 +15,39 @@ limitations under the License. */ import { Box, Grid } from '@material-ui/core'; import { fetchTransactions } from 'actions/networkAction'; + import PageHeader from 'components/pageHeader/PageHeader'; import StyledTabs from 'components/tabs'; import Deposits from 'containers/history/deposits'; import Exits from 'containers/history/exits'; import Transactions from 'containers/history/transactions'; + import { isEqual, orderBy } from 'lodash'; import moment from 'moment'; import React, { useState } from 'react'; + import DatePicker from 'react-datepicker'; import "react-datepicker/dist/react-datepicker.css"; + import { batch, useDispatch, useSelector } from 'react-redux'; import { selectNetwork } from 'selectors/setupSelector'; import { selectTransactions } from 'selectors/transactionSelector'; import { POLL_INTERVAL } from 'util/constant'; import { getAllNetworks } from 'util/masterConfig'; import useInterval from 'util/useInterval'; -import { - PageContent -} from '../page.style'; + +import { PageContent } from '../page.style'; function HistoryPage() { + const dispatch = useDispatch(); - const [selectedTab, setSelectedTab] = useState(0); - const [startDate, setStartDate] = useState(null); - const [endDate, setEndDate] = useState(null); - const [searchTerm, setSearchTerm] = useState(''); + + const [selectedTab, setSelectedTab] = useState(0) + const [startDate, setStartDate] = useState(null) + const [endDate, setEndDate] = useState(null) + const [searchTerm, setSearchTerm] = useState('') - const tabList = ['All', 'Deposits', 'Exits'] + const tabList = ['All', 'Bridge to L2', 'Bridge to L1'] const unorderedTransactions = useSelector(selectTransactions, isEqual); const orderedTransactions = orderBy(unorderedTransactions, i => i.timeStamp, 'desc'); @@ -69,13 +74,13 @@ function HistoryPage() { useInterval(() => { batch(() => { - dispatch(fetchTransactions()); - }); - }, POLL_INTERVAL * 2); + dispatch(fetchTransactions()) + }) + }, POLL_INTERVAL * 2) console.log(['transactions', transactions]); - const onTabChagne = (event, newValue) => { + const onTabChange = (event, newValue) => { console.log([event, newValue]); setSelectedTab(newValue); } @@ -89,7 +94,7 @@ function HistoryPage() { > @@ -126,13 +131,13 @@ function HistoryPage() { chainLink={chainLink} /> : null } - {tabList[selectedTab] === 'Deposits' ? + {tabList[selectedTab] === 'Bridge to L2' ? : null } - {tabList[selectedTab] === 'Exits' ? + {tabList[selectedTab] === 'Bridge to L1' ? props.open ? 'rotate(-90deg)' : 'rotate(90deg)'}; transition: all 200ms ease-in-out; diff --git a/packages/omgx/wallet-frontend/src/reducers/setupReducer.js b/packages/omgx/wallet-frontend/src/reducers/setupReducer.js index bc784ba7b5b3..8c6622d7d1ae 100644 --- a/packages/omgx/wallet-frontend/src/reducers/setupReducer.js +++ b/packages/omgx/wallet-frontend/src/reducers/setupReducer.js @@ -35,7 +35,7 @@ const initialState = { etherscan: '', minter: false, netLayer: netLayerCache ? netLayerCache : 'L1' -}; +} function setupReducer (state = initialState, action) { switch (action.type) { diff --git a/packages/omgx/wallet-frontend/src/reducers/tokenReducer.js b/packages/omgx/wallet-frontend/src/reducers/tokenReducer.js index 8f77213bb96a..6cb75c16101d 100644 --- a/packages/omgx/wallet-frontend/src/reducers/tokenReducer.js +++ b/packages/omgx/wallet-frontend/src/reducers/tokenReducer.js @@ -22,9 +22,9 @@ const initialState = { addressL1: L1ETH, addressL2: L2ETH, symbolL1: 'ETH', - symbolL2: 'oETH', - decimals: 18, - name: 'Ethereum', + symbolL2: 'ETH', + decimals: 18, + name: 'Ethereum', redalert: false, }, } diff --git a/packages/omgx/wallet-frontend/src/reducers/uiReducer.js b/packages/omgx/wallet-frontend/src/reducers/uiReducer.js index 585632924ab0..d1ccf1d13018 100644 --- a/packages/omgx/wallet-frontend/src/reducers/uiReducer.js +++ b/packages/omgx/wallet-frontend/src/reducers/uiReducer.js @@ -41,7 +41,7 @@ const initialState = { alert: null, error: null, activeHistoryTab1: 'All', - activeHistoryTab2: 'Exits', + activeHistoryTab2: 'Bridge to L1', }; function uiReducer (state = initialState, action) { diff --git a/packages/omgx/wallet-frontend/src/services/networkService.js b/packages/omgx/wallet-frontend/src/services/networkService.js index 6ac9b3d33197..aeaa93b403ce 100644 --- a/packages/omgx/wallet-frontend/src/services/networkService.js +++ b/packages/omgx/wallet-frontend/src/services/networkService.js @@ -14,11 +14,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { parseUnits, parseEther, formatEther } from '@ethersproject/units' +import { parseEther, formatEther } from '@ethersproject/units' import { Watcher } from '@eth-optimism/watcher' import { ethers, BigNumber, utils, ContractFactory } from 'ethers' + import store from 'store' import { orderBy } from 'lodash' @@ -54,6 +55,8 @@ import L2LPJson from '../deployment/artifacts-ovm/contracts/LP/L2LiquidityPool.s import L1ERC20Json from '../deployment/artifacts/contracts/L1ERC20.sol/L1ERC20.json' import L2ERC20Json from '../deployment/artifacts-ovm/optimistic-ethereum/libraries/standards/L2StandardERC20.sol/L2StandardERC20.json' +import OMGJson from '../deployment/contracts/OMG/OMG.json' + //OMGX L2 Contracts import L2ERC721Json from '../deployment/artifacts-ovm/contracts/ERC721Genesis.sol/ERC721Genesis.json' import L2ERC721RegJson from '../deployment/artifacts-ovm/contracts/ERC721Registry.sol/ERC721Registry.json' @@ -67,9 +70,9 @@ import GovernorBravoDelegate from "../deployment/rinkeby/json/GovernorBravoDeleg import GovernorBravoDelegator from "../deployment/rinkeby/json/GovernorBravoDelegator.json" import Timelock from "../deployment/rinkeby/json/Timelock.json" -import { powAmount, logAmount } from 'util/amountConvert' + import { accDiv, accMul } from 'util/calculation' -import {getNftImageUrl} from 'util/nftImage' +import { getNftImageUrl } from 'util/nftImage' import { getAllNetworks } from 'util/masterConfig' import etherScanInstance from 'api/etherScanAxios' @@ -77,7 +80,6 @@ import omgxWatcherAxiosInstance from 'api/omgxWatcherAxios' import addressAxiosInstance from 'api/addressAxios' import addressOMGXAxiosInstance from 'api/addressOMGXAxios' import coinGeckoAxiosInstance from 'api/coinGeckoAxios' -import ethGasStationAxiosInstance from 'api/ethGasStationAxios' //All the current addresses for fallback purposes, or live network const localAddresses = require(`../deployment/local/addresses.json`) @@ -121,6 +123,8 @@ class NetworkService { this.L1_TEST_Contract = null this.L2_TEST_Contract = null + this.L1_OMG_Contract = null + this.L1LPAddress = null this.L2LPAddress = null @@ -486,6 +490,14 @@ class NetworkService { ) console.log('L1_TEST_Contract:', this.L1_TEST_Contract.address) + /*The test token*/ + this.L1_OMG_Contract = new ethers.Contract( + addresses.TOKENS.OMG.L1, + OMGJson, + this.provider.getSigner() + ) + console.log('L1_TEST_Contract:', this.L1_TEST_Contract.address) + this.L2_TEST_Contract = new ethers.Contract( addresses.TOKENS.TEST.L2, L2ERC20Json.abi, @@ -524,22 +536,6 @@ class NetworkService { this.provider.getSigner() ) - //this one is always there... - //await addNFTContract(this.ERC721Contract.address) - - //yes, this looks weird, but think before you change it... - //there may be some in the cache, and this makes sure we get them all, and if not, - //we at least have the basic one - //const NFTcontracts = Object.values(await getNFTContracts()) - - //Add factories based on cached contract addresses - //this information is also used for the balance lookup - //for(var i = 0; i < NFTcontracts.length; i++) { - // const address = NFTcontracts[i] - // console.log("Adding NFT contract:",address) - // this.addNFTFactoryNS( address ) - //} - this.watcher = new Watcher({ l1: { provider: this.L1Provider, @@ -590,13 +586,6 @@ class NetworkService { } -/* - this.comp = null - this.delegate = null - this.delegator = null - this.timelock = null -*/ - this.bindProviderListeners() return 'enabled' @@ -606,48 +595,21 @@ class NetworkService { } } - // async checkStatus() { - // return { - // connection: true, - // byzantine: false, - // watcherSynced: true, - // lastSeenBlock: 0, - // } - // } - async addL2Network() { + console.log("MetaMask: Adding network to MetaMask") + const nw = getAllNetworks() - const masterConfig = store.getState().setup.masterConfig; - let chainParam = {} + const masterConfig = store.getState().setup.masterConfig - if (masterConfig === 'mainnet') { - chainParam = { - chainId: '0x' + nw.mainnet.L2.chainId.toString(16), - chainName: nw.mainnet.L2.name, - rpcUrls: [nw.mainnet.L2.rpcUrl], - } - } else if (masterConfig === 'rinkeby') { - chainParam = { - chainId: '0x' + nw.rinkeby.L2.chainId.toString(16), - chainName: nw.rinkeby.L2.name, - rpcUrls: [nw.rinkeby.L2.rpcUrl], - } - } else if (masterConfig === 'rinkeby_integration') { - chainParam = { - chainId: '0x' + nw.rinkeby_integration.L2.chainId.toString(16), - chainName: nw.rinkeby_integration.L2.name, - rpcUrls: [nw.rinkeby_integration.L2.rpcUrl], - } - } else if (masterConfig === 'local') { - chainParam = { - chainId: '0x' + nw.local.L2.chainId.toString(16), - chainName: nw.local.L2.name, - rpcUrls: [nw.local.L2.rpcUrl], - } + const chainParam = { + chainId: '0x' + nw[masterConfig].L2.chainId.toString(16), + chainName: nw[masterConfig].L2.name, + rpcUrls: [nw[masterConfig].L2.rpcUrl], + blockExplorerUrls: [nw[masterConfig].L2.blockExplorer.slice(0, -1)], } - - console.log("MetaMask: Trying to add ", chainParam) + + console.log("MetaMask: Adding ", chainParam) // connect to the wallet this.provider = new ethers.providers.Web3Provider(window.ethereum) @@ -661,6 +623,114 @@ class NetworkService { } + /* Yes, this almost complete dupicates async switchChain( layer ) + but that's safest for now */ + async correctChain( targetLayer ) { + + const nw = getAllNetworks() + const masterConfig = store.getState().setup.masterConfig + + //the chainParams are only needed for the L2's + const chainParam = { + chainId: '0x' + nw[masterConfig].L2.chainId.toString(16), + chainName: nw[masterConfig].L2.name, + rpcUrls: [nw[masterConfig].L2.rpcUrl], + blockExplorerUrls: [nw[masterConfig].L2.blockExplorer.slice(0, -1)], + } + + // connect to the wallet + this.provider = new ethers.providers.Web3Provider(window.ethereum) + + /********************* Switch to Mainnet L2 ****************/ + if (masterConfig === 'mainnet' && targetLayer === 'L2') { + //ok, so then, we want to switch to 'mainnet' && 'L2' + try { + await this.provider.send('wallet_switchEthereumChain', [{ chainId: '0x120' }]) //ChainID 288 + } catch (error) { + // This error code indicates that the chain has not been added to MetaMask. + if (error.code === 4902) { + try { + await this.provider.send('wallet_addEthereumChain', [chainParam, this.account]) + } catch (addError) { + console.log("MetaMask - Error adding new RPC: ", addError) + // handle "add" error via alert message + } + } else { //some other error code + console.log("MetaMask - Switch Error: ", error.code) + } + } + } else if ( masterConfig === 'mainnet' && targetLayer === 'L1') { + //ok, so then, we want to switch to 'mainnet' && 'L1' - no need to add + //if(fail) since mainnet L1 is always there unless the planet + //has been vaporized by space aliens with a blaster ray + try { + await this.provider.send('wallet_switchEthereumChain',[{ chainId: '0x1' }]) //ChainID 1 + } catch (switchError) { + console.log("MetaMask - could not switch to Ethereum Mainchain. Needless to say, this should never happen.") + } + } else if (masterConfig === 'rinkeby' && targetLayer === 'L2') { + //ok, so then, we want to switch to 'rinkeby' && 'L2' + try { + await this.provider.send('wallet_switchEthereumChain', [{ chainId: '0x1C' }]) //ChainID 28 + } catch (error) { + if (error.code === 4902) { + try { + await this.provider.send('wallet_addEthereumChain', [chainParam, this.account]) + } catch (addError) { + console.log("MetaMask - Error adding new RPC: ", addError) + // handle "add" error via alert message + } + } else { //some other error code + console.log("MetaMask - Switch Error: ", error.code) + } + } + } else if (masterConfig === 'rinkeby_integration' && targetLayer === 'L2') { + //ok, so then, we want to switch to 'rinkeby_integration' && 'L2' + try { + await this.provider.send('wallet_switchEthereumChain', [{ chainId: '0x1D' }]) //ChainID 29 + } catch (error) { + if (error.code === 4902) { + try { + await this.provider.send('wallet_addEthereumChain', [chainParam, this.account]) + } catch (addError) { + console.log("MetaMask - Error adding new RPC: ", addError) + // handle "add" error via alert message + } + } else { //some other error code + console.log("MetaMask - Switch Error: ", error.code) + } + } + } else if ((masterConfig === 'rinkeby' || masterConfig === 'rinkeby_integration') && targetLayer === 'L1') { + try { + await this.provider.send('wallet_switchEthereumChain',[{ chainId: '0x4' }]) //ChainID 4 + } catch (switchError) { + console.log("MetaMask - could not switch to Rinkeby. Needless to say, this should never happen.") + } + } else if (masterConfig === 'local' && targetLayer === 'L2') { + //ok, so then, we want to switch to 'local' && 'L2' + try { + await this.provider.send('wallet_switchEthereumChain', [{ chainId: '0x7A6A' }]) //ChainID 31338 + } catch (error) { + if (error.code === 4902) { + try { + await this.provider.send('wallet_addEthereumChain', [chainParam, this.account]) + } catch (addError) { + console.log("MetaMask - Error adding new RPC: ", addError) + // handle "add" error via alert message + } + } else { //some other error code + console.log("MetaMask - Switch Error: ", error.code) + } + } + } else if (masterConfig === 'local' && targetLayer === 'L1') { + try { + await this.provider.send('wallet_switchEthereumChain',[{ chainId: '0x7A69' }]) //ChainID 31337 + } catch (switchError) { + console.log("MetaMask - could not switch to Local L1") + } + } + } + async switchChain( layer ) { if(this.L1orL2 === layer) { @@ -675,6 +745,7 @@ class NetworkService { chainId: '0x' + nw[masterConfig].L2.chainId.toString(16), chainName: nw[masterConfig].L2.name, rpcUrls: [nw[masterConfig].L2.rpcUrl], + blockExplorerUrls: [nw[masterConfig].L2.blockExplorer.slice(0, -1)], } // connect to the wallet @@ -865,17 +936,17 @@ class NetworkService { if (to === this.L2LPAddress.toLowerCase()) { //console.log("L2->L1 Swap Off") - return Object.assign({}, item, { typeTX: 'Fast Offramp' }) + return Object.assign({}, item, { typeTX: 'Fast Bridge to L1' }) } if (to === this.L1LPAddress.toLowerCase()) { //console.log("L1->L2 Swap On") - return Object.assign({}, item, { typeTX: 'Fast Onramp' }) + return Object.assign({}, item, { typeTX: 'Fast Bridge to L2' }) } if (to === this.L1StandardBridgeAddress.toLowerCase()) { //console.log("L1->L2 Traditional Deposit") - return Object.assign({}, item, { typeTX: 'Traditional' }) + return Object.assign({}, item, { typeTX: 'Classic Bridge to L2' }) } if (to === this.L1_TEST_Address.toLowerCase()) { @@ -885,7 +956,7 @@ class NetworkService { if (to === this.L2StandardBridgeAddress.toLowerCase()) { //console.log("L2 Standard Bridge") - return Object.assign({}, item, { typeTX: 'L2 Standard Bridge' }) + return Object.assign({}, item, { typeTX: 'Classic Bridge to L1' }) } if (to === this.L1Message.toLowerCase()) { @@ -928,7 +999,7 @@ class NetworkService { } } - return Object.assign({}, item, { typeTX: to }) + return Object.assign({}, item, { typeTX: 'Approval/Other (' + to + ')' }) }) //map @@ -1101,10 +1172,10 @@ class NetworkService { const UUID = address.substring(1, 6) + '_' + tokenID.toString() + '_' + this.account.substring(1, 6) - const { url , attributes = []} = await getNftImageUrl(meta[1]); + const { url , attributes = []} = await getNftImageUrl(meta[1]) + // Uncomment Just to test locally // const { url , attributes = []} = await getNftImageUrl('https://boredapeyachtclub.com/api/mutants/111'); - // const { url , attributes = []} = await getNftImageUrl('ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/6190'); const NFT = { @@ -1136,7 +1207,8 @@ class NetworkService { async getBalances() { try { - // Always check ETH and oETH + + // Always check ETH const layer1Balance = await this.L1Provider.getBalance(this.account) const layer2Balance = await this.L2Provider.getBalance(this.account) @@ -1156,7 +1228,7 @@ class NetworkService { address: this.L2_ETH_Address, addressL1: this.L1_ETH_Address, currency: this.L1_ETH_Address, - symbol: 'oETH', + symbol: 'ETH', decimals: 18, balance: new BN(layer2Balance.toString()), }, @@ -1211,7 +1283,7 @@ class NetworkService { } //Move ETH from L1 to L2 using the standard deposit system - depositETHL2 = async (value = '1', gasPrice) => { + depositETHL2 = async (value_Wei_String) => { updateSignatureStatus_depositTRAD(false) @@ -1220,8 +1292,7 @@ class NetworkService { this.L2GasLimit, utils.formatBytes32String(new Date().getTime().toString()), { - value: parseEther(value), - gasPrice: ethers.utils.parseUnits(`${gasPrice}`, 'wei'), + value: value_Wei_String } ) @@ -1243,18 +1314,20 @@ class NetworkService { return l2Receipt } catch(error) { - console.log(error) - return false + //console.log(error) + //return false + console.log("NS: depositETHL2 error:",error) + throw new Error(error.message) } } //Transfer funds from one account to another, on the L2 - async transfer(address, value, currency) { + async transfer(address, value_Wei_String, currency) { try { - //any old ERC20 json will do.... + //any ERC20 json will do.... const tx = await this.L2_TEST_Contract.attach(currency).transfer( address, - parseEther(value.toString()) + value_Wei_String ) await tx.wait() return tx @@ -1287,7 +1360,7 @@ class NetworkService { this.account, targetContract ) - return allowance.toString() + return allowance //.toString() } catch (error) { console.log("NS: checkAllowance error:", error) throw new WebWalletError({ @@ -1301,7 +1374,7 @@ class NetworkService { /*Used when people want to fast exit - they have to deposit funds into the L2LP*/ async approveERC20_L2LP( - depositAmount_string, + value_Wei_String, currencyAddress ) { @@ -1318,12 +1391,12 @@ class NetworkService { this.L2LPAddress ) - let depositAmount_BN = new BN(depositAmount_string) + let depositAmount_BN = new BN(value_Wei_String) if (depositAmount_BN.gt(allowance_BN)) { const approveStatus = await L2ERC20Contract.approve( this.L2LPAddress, - depositAmount_string + value_Wei_String ) await approveStatus.wait() } @@ -1336,25 +1409,59 @@ class NetworkService { } async approveERC20_L1LP( - depositAmount_string, - currencyAddress + value_Wei_String, + currency ) { - try { + console.log("approveERC20_L1LP") + const approveContractAddress = this.L1LPAddress - console.log("approveERC20_L1LP") + try { const ERC20Contract = new ethers.Contract( - currencyAddress, + currency, L1ERC20Json.abi, this.provider.getSigner() ) - const approveStatus = await ERC20Contract.approve( - this.L1LPAddress, - depositAmount_string + let allowance_BN = await ERC20Contract.allowance( + this.account, + approveContractAddress + ) + console.log("Initial allowance:",allowance_BN) + + /* OMG IS A SPECIAL CASE - allowance needs to be + set to zero, and then set to actual amount */ + if( allowance_BN.gt(BigNumber.from(0)) && + (currency.toLowerCase() === this["L1_OMG_Address"].toLowerCase()) + ) + { + console.log("OMG Token allowance reset") + const approveOMG = await ERC20Contract.approve( + approveContractAddress, + ethers.utils.parseEther("0") + ) + await approveOMG.wait() + console.log("OMG Token allowance set to 0:",approveOMG) + } + + //recheck the allowance + allowance_BN = await ERC20Contract.allowance( + this.account, + approveContractAddress ) - await approveStatus.wait() + + const allowed = allowance_BN.gte(BigNumber.from(value_Wei_String)) + + if(!allowed) { + //and now, the normal allowance transaction + const approveStatus = await ERC20Contract.approve( + approveContractAddress, + value_Wei_String + ) + await approveStatus.wait() + console.log("ERC 20 L1 BRIDGE ops approved:",approveStatus) + } return true } catch (error) { @@ -1364,7 +1471,7 @@ class NetworkService { } async approveERC20( - value, + value_Wei_String, currency, approveContractAddress = this.L1StandardBridgeAddress, contractABI = L1ERC20Json.abi @@ -1378,12 +1485,46 @@ class NetworkService { this.provider.getSigner() ) - const approveStatus = await ERC20Contract.approve( - approveContractAddress, - value + /***********************/ + + let allowance_BN = await ERC20Contract.allowance( + this.account, + approveContractAddress + ) + console.log("Allowance:",allowance_BN) + + /* OMG IS A SPECIAL CASE - allowance needs to be + set to zero, and then set to actual amount */ + if( allowance_BN.gt(BigNumber.from(0)) && + (currency.toLowerCase() === this["L1_OMG_Address"].toLowerCase()) + ) + { + console.log("OMG Token allowance reset") + const approveOMG = await ERC20Contract.approve( + approveContractAddress, + ethers.utils.parseEther("0") + ) + await approveOMG.wait() + console.log("OMG Token allowance set to 0:",approveOMG) + } + + //recheck the allowance + allowance_BN = await ERC20Contract.allowance( + this.account, + approveContractAddress ) + + const allowed = allowance_BN.gte(BigNumber.from(value_Wei_String)) - await approveStatus.wait() + if(!allowed) { + //and now, the normal allowance transaction + const approveStatus = await ERC20Contract.approve( + approveContractAddress, + value_Wei_String + ) + await approveStatus.wait() + console.log("ERC 20 L1 SWAP ops approved:",approveStatus) + } return true } catch (error) { @@ -1393,27 +1534,63 @@ class NetworkService { } //Used to move ERC20 Tokens from L1 to L2 - async depositErc20(value, currency, gasPrice, currencyL2) { + async depositErc20(value_Wei_String, currency, currencyL2) { updateSignatureStatus_depositTRAD(false) + //console.log("Depositing ERC20") + + const L1_TEST_Contract = this.L1_TEST_Contract.attach(currency) + + let allowance_BN = await L1_TEST_Contract.allowance( + this.account, + this.L1StandardBridgeAddress + ) + //console.log("Allowance:",allowance_BN) + try { - //could use any ERC20 here... - const L1_TEST_Contract = this.L1_TEST_Contract.attach(currency) + /* OMG IS A SPECIAL CASE - allowance needs to be + set to zero, and then set to actual amount */ + if( allowance_BN.gt(BigNumber.from(0)) && + (currency.toLowerCase() === this["L1_OMG_Address"].toLowerCase()) + ) + { + console.log("OMG Token allowance reset") + const approveOMG = await L1_TEST_Contract.approve( + this.L1StandardBridgeAddress, + ethers.utils.parseEther("0") + ) + await approveOMG.wait() + console.log("OMG Token allowance set to 0:",approveOMG) + } - const approveStatus = await L1_TEST_Contract.approve( - this.L1StandardBridgeAddress, //this is the spender - value + //recheck the allowance + allowance_BN = await L1_TEST_Contract.allowance( + this.account, + this.L1StandardBridgeAddress ) - await approveStatus.wait() + + const allowed = allowance_BN.gte(BigNumber.from(value_Wei_String)) + + if(!allowed) { + //and now, the normal allowance transaction + const approveStatus = await L1_TEST_Contract.approve( + this.L1StandardBridgeAddress, + value_Wei_String + ) + await approveStatus.wait() + console.log("ERC 20 L1 ops approved:",approveStatus) + } const depositTxStatus = await this.L1StandardBridgeContract.depositERC20( currency, currencyL2, - value, + value_Wei_String, this.L2GasLimit, utils.formatBytes32String(new Date().getTime().toString()) ) + + console.log("depositTxStatus:",depositTxStatus) //at this point the tx has been submitted, and we are waiting... await depositTxStatus.wait() @@ -1446,26 +1623,21 @@ class NetworkService { } //Standard 7 day exit from BOBA - async exitBOBA(currencyAddress, value) { + async exitBOBA(currencyAddress, value_Wei_String) { updateSignatureStatus_exitTRAD(false) + //now coming in as a value_Wei_String + const value = BigNumber.from(value_Wei_String) + const allowance = await this.checkAllowance( currencyAddress, this.L2StandardBridgeAddress ) - const L2_ERC20_Contract = new ethers.Contract( - currencyAddress, - L2ERC20Json.abi, - this.provider.getSigner() - ) - const decimals = await L2_ERC20_Contract.decimals() - // need the frontend updates - if (BigNumber.from(allowance).lt(parseUnits(value, decimals))) { + + if ( allowance.lt(value) ) { const res = await this.approveERC20( - // take caution while using parseEther() with erc20 - // l2 erc20 can be customised to have non 18 decimals - parseUnits(value, decimals), + value_Wei_String, currencyAddress, this.L2StandardBridgeAddress ) @@ -1474,7 +1646,7 @@ class NetworkService { const tx = await this.L2StandardBridgeContract.withdraw( currencyAddress, - parseUnits(value, decimals), + value_Wei_String, this.L1GasLimit, utils.formatBytes32String(new Date().getTime().toString()) ) @@ -1493,10 +1665,10 @@ class NetworkService { /***********************************************/ /***** Fee *****/ - /***** Fees are reported as integers, - * where every int - * represent 0.1% - *********/ + /***** Fees are reported as integers, *****/ + /***** where every int *****/ + /***** represents 0.1% *****/ + /***********************************************/ // Total exit fee async getTotalFeeRate() { @@ -1532,7 +1704,7 @@ class NetworkService { async getL1LPInfo() { const tokenAddressList = Object.keys(this.addresses.TOKENS).reduce((acc, cur) => { - acc.push(this["L1_" + cur + "_Address"]); + acc.push(this["L1_" + cur + "_Address"].toLowerCase()); return acc; }, [this.L1_ETH_Address]); @@ -1566,19 +1738,19 @@ class NetworkService { } const poolTokenInfo = await L1LPContract.poolInfo(tokenAddress) const userTokenInfo = await L1LPContract.userInfo(tokenAddress, this.account) - return { tokenAddress, tokenBalance, tokenSymbol, tokenName, poolTokenInfo, userTokenInfo,decimals } + return { tokenAddress, tokenBalance, tokenSymbol, tokenName, poolTokenInfo, userTokenInfo, decimals } } tokenAddressList.forEach((tokenAddress) => L1LPInfoPromise.push(getL1LPInfoPromise(tokenAddress))) const L1LPInfo = await Promise.all(L1LPInfoPromise); L1LPInfo.forEach((token) => { - poolInfo[token.tokenAddress] = { + poolInfo[token.tokenAddress.toLowerCase()] = { symbol: token.tokenSymbol, name: token.tokenName, decimals: token.decimals, - l1TokenAddress: token.poolTokenInfo.l1TokenAddress, - l2TokenAddress: token.poolTokenInfo.l2TokenAddress, + l1TokenAddress: token.poolTokenInfo.l1TokenAddress.toLowerCase(), + l2TokenAddress: token.poolTokenInfo.l2TokenAddress.toLowerCase(), accUserReward: token.poolTokenInfo.accUserReward.toString(), accUserRewardPerShare: token.poolTokenInfo.accUserRewardPerShare.toString(), userDepositAmount: token.poolTokenInfo.userDepositAmount.toString(), @@ -1603,7 +1775,7 @@ class NetworkService { tokenBalance: token.tokenBalance.toString() } userInfo[token.tokenAddress] = { - l1TokenAddress: token.tokenAddress, + l1TokenAddress: token.tokenAddress.toLowerCase(), amount: token.userTokenInfo.amount.toString(), pendingReward: token.userTokenInfo.pendingReward.toString(), rewardDebt: token.userTokenInfo.rewardDebt.toString() @@ -1616,8 +1788,8 @@ class NetworkService { const tokenAddressList = Object.keys(this.addresses.TOKENS).reduce((acc, cur) => { acc.push({ - L1: this["L1_" + cur + "_Address"], - L2: this["L2_" + cur + "_Address"] + L1: this["L1_" + cur + "_Address"].toLowerCase(), + L2: this["L2_" + cur + "_Address"].toLowerCase() }); return acc; }, [{ @@ -1637,6 +1809,7 @@ class NetworkService { const L2LPInfoPromise = []; const getL2LPInfoPromise = async(tokenAddress, tokenAddressL1 ) => { + let tokenBalance let tokenSymbol let tokenName @@ -1644,9 +1817,9 @@ class NetworkService { if (tokenAddress === this.L2_ETH_Address) { tokenBalance = await this.L2Provider.getBalance(this.L2LPAddress) - tokenSymbol = 'oETH' + tokenSymbol = 'ETH' tokenName = 'Ethereum' - decimals = 18; + decimals = 18 } else { tokenBalance = await this.L2_TEST_Contract.attach(tokenAddress).connect(this.L2Provider).balanceOf(this.L2LPAddress) tokenSymbol = await this.L2_TEST_Contract.attach(tokenAddress).connect(this.L2Provider).symbol() @@ -1660,14 +1833,15 @@ class NetworkService { tokenAddressList.forEach(({L1, L2}) => L2LPInfoPromise.push(getL2LPInfoPromise(L2, L1))) - const L2LPInfo = await Promise.all(L2LPInfoPromise); + const L2LPInfo = await Promise.all(L2LPInfoPromise) + L2LPInfo.forEach((token) => { - poolInfo[token.tokenAddress] = { + poolInfo[token.tokenAddress.toLowerCase()] = { symbol: token.tokenSymbol, name: token.tokenName, decimals: token.decimals, - l1TokenAddress: token.poolTokenInfo.l1TokenAddress, - l2TokenAddress: token.poolTokenInfo.l2TokenAddress, + l1TokenAddress: token.poolTokenInfo.l1TokenAddress.toLowerCase(), + l2TokenAddress: token.poolTokenInfo.l2TokenAddress.toLowerCase(), accUserReward: token.poolTokenInfo.accUserReward.toString(), accUserRewardPerShare: token.poolTokenInfo.accUserRewardPerShare.toString(), userDepositAmount: token.poolTokenInfo.userDepositAmount.toString(), @@ -1691,8 +1865,8 @@ class NetworkService { ), // ( accUserReward - userDepositAmount ) / timeDuration tokenBalance: token.tokenBalance.toString() } - userInfo[token.tokenAddress] = { - l2TokenAddress: token.tokenAddress, + userInfo[token.tokenAddress.toLowerCase()] = { + l2TokenAddress: token.tokenAddress.toLowerCase(), amount: token.userTokenInfo.amount.toString(), pendingReward: token.userTokenInfo.pendingReward.toString(), rewardDebt: token.userTokenInfo.rewardDebt.toString() @@ -1705,9 +1879,9 @@ class NetworkService { /***********************************************/ /***** Add Liquidity *****/ /***********************************************/ - async addLiquidity(currency, value, L1orL2Pool, decimals) { + async addLiquidity(currency, value_Wei_String, L1orL2Pool) { - let depositAmount = powAmount(value, decimals) + //let depositAmount = powAmount(value, decimals) try { // Deposit @@ -1715,9 +1889,9 @@ class NetworkService { ? this.L1LPContract : this.L2LPContract ).addLiquidity( - depositAmount, + value_Wei_String, currency, - currency === this.L1_ETH_Address ? { value: depositAmount } : {} + currency === this.L1_ETH_Address ? { value: value_Wei_String } : {} ) await addLiquidityTX.wait() return true @@ -1730,11 +1904,11 @@ class NetworkService { /***********************************************/ /***** Get Reward L1 *****/ /***********************************************/ - async getRewardL1(currencyL1Address, userReward_BN) { + async getRewardL1(currencyL1Address, value_Wei_String) { try { const withdrawRewardTX = await this.L1LPContract.withdrawReward( - userReward_BN, + value_Wei_String, currencyL1Address, this.account ) @@ -1748,11 +1922,11 @@ class NetworkService { /***********************************************/ /***** Get Reward L2 *****/ /***********************************************/ - async getRewardL2(currencyL2Address, userReward_BN) { + async getRewardL2(currencyL2Address, value_Wei_String) { try { const withdrawRewardTX = await this.L2LPContract.withdrawReward( - userReward_BN, + value_Wei_String, currencyL2Address, this.account ) @@ -1766,16 +1940,14 @@ class NetworkService { /***********************************************/ /***** Withdraw Liquidity *****/ /***********************************************/ - async withdrawLiquidity(currency, value, L1orL2Pool, decimals) { + async withdrawLiquidity(currency, value_Wei_String, L1orL2Pool) { - let withdrawAmount = powAmount(value, decimals) try { - // Deposit const withdrawLiquidityTX = await (L1orL2Pool === 'L1LP' ? this.L1LPContract : this.L2LPContract ).withdrawLiquidity( - withdrawAmount, + value_Wei_String, currency, this.account ) @@ -1789,15 +1961,14 @@ class NetworkService { /***********************************************************/ /***** SWAP ON to BOBA by depositing funds to the L1LP *****/ /***********************************************************/ - async depositL1LP(currency, value, decimals) { + async depositL1LP(currency, value_Wei_String) { updateSignatureStatus_depositLP(false) - let depositAmount = powAmount(value, decimals) const depositTX = await this.L1LPContract.clientDepositL1( - depositAmount.toString(), + value_Wei_String, currency, - currency === this.L1_ETH_Address ? { value: depositAmount } : {} + currency === this.L1_ETH_Address ? { value: value_Wei_String } : {} ) //at this point the tx has been submitted, and we are waiting... @@ -1810,6 +1981,7 @@ class NetworkService { depositTX.hash ) console.log(' got L1->L2 message hash', l1ToL2msgHash) + const l2Receipt = await this.watcher.getL2TransactionReceipt(l1ToL2msgHash) console.log(' completed swap-on ! L2 tx hash:', l2Receipt.transactionHash) @@ -1819,9 +1991,11 @@ class NetworkService { /***************************************/ /************ L1LP Pool size ***********/ /***************************************/ - async L1LPBalance(tokenAddress, decimals) { + async L1LPBalance(tokenAddress) { + let balance let tokenAddressLC = tokenAddress.toLowerCase() + if ( tokenAddressLC === this.L2_ETH_Address || tokenAddressLC === this.L1_ETH_Address @@ -1833,20 +2007,18 @@ class NetworkService { ) } - if(typeof(balance) === 'undefined') { - return logAmount('0', decimals) - } else { - return logAmount(balance.toString(), decimals) - } + return balance.toString() } /***************************************/ /************ L2LP Pool size ***********/ /***************************************/ - async L2LPBalance(tokenAddress, decimals) { + async L2LPBalance(tokenAddress) { + let balance let tokenAddressLC = tokenAddress.toLowerCase() + if ( tokenAddressLC === this.L2_ETH_Address || tokenAddressLC === this.L1_ETH_Address @@ -1861,18 +2033,13 @@ class NetworkService { ) } - if(typeof(balance) === 'undefined') { - return logAmount('0', decimals) - } else { - return logAmount(balance.toString(), decimals) - } - + return balance.toString() } /**************************************************************/ /***** SWAP OFF from BOBA by depositing funds to the L2LP *****/ /**************************************************************/ - async depositL2LP(currencyAddress, depositAmount_string) { + async depositL2LP(currencyAddress, value_Wei_String) { updateSignatureStatus_exitLP(false) @@ -1887,19 +2054,19 @@ class NetworkService { this.L2LPAddress ) - let depositAmount_BN = new BN(depositAmount_string) + let depositAmount_BN = new BN(value_Wei_String) if (depositAmount_BN.gt(allowance_BN)) { const approveStatus = await L2ERC20Contract.approve( this.L2LPAddress, - depositAmount_string + value_Wei_String ) await approveStatus.wait() if (!approveStatus) return false } const depositTX = await this.L2LPContract.clientDepositL2( - depositAmount_string, + value_Wei_String, currencyAddress ) @@ -1935,41 +2102,6 @@ class NetworkService { } } - async getGasPrice({ - network, networkLayer - }) { - if(network === 'mainnet' && networkLayer === 'L1') { - try { - const { data: { safeLow, average, fast } } = await ethGasStationAxiosInstance.get('json/ethgasAPI.json'); - return { - slow: safeLow * 100000000, - normal: average * 100000000, - fast: fast * 100000000 - }; - } catch (error) { - // - } - // if not web3 oracle - try { - const _medianEstimate = await this.web3.eth.getGasPrice(); - const medianEstimate = Number(_medianEstimate); - return { - slow: Math.max(medianEstimate / 2, 1000000000), - normal: medianEstimate, - fast: medianEstimate * 5 - }; - } catch (error) { - // - } - } - - return { - slow: 1000000000, - normal: 2000000000, - fast: 10000000000 - } - } - /***********************************************/ /***** DAO Functions *****/ /***********************************************/ @@ -2171,7 +2303,8 @@ class NetworkService { try { const delegateCheck = await this.delegate.attach(this.delegator.address); - let res = delegateCheck.castVote(id, userVote //, + let res = delegateCheck.castVote(id, userVote + //, //{ // gasPrice: 15000000, // gasLimit: 8000000 diff --git a/packages/omgx/wallet-frontend/src/util/amountConvert.js b/packages/omgx/wallet-frontend/src/util/amountConvert.js index db1af3c09d71..2ab0306fabb1 100644 --- a/packages/omgx/wallet-frontend/src/util/amountConvert.js +++ b/packages/omgx/wallet-frontend/src/util/amountConvert.js @@ -29,16 +29,35 @@ export function logAmount (amount, power, truncate = 0) { return calculated.toFixed(); } -export function powAmount (amount, power) { - const x = new BigNumber(amount); - const exp = new BigNumber(10).pow(power); +/*Takes a value such as 3.92 and converts it into +a BigNumber in wei + +Duplicates + +ethers.utils.parseUnits( valueString , decimalsOrUnitName ) => BigNumber +*/ + +export function powAmount (amount, decimals) { + + const x = new BigNumber(amount) + const exp = new BigNumber(10).pow(decimals) + + const calculated = x.multipliedBy(exp) + return calculated.toFixed(0) +} + +/* more clearly named version of this */ +export function toWei_String(amount, decimals) { + + const x = new BigNumber(amount) + const exp = new BigNumber(10).pow(decimals) - const calculated = x.multipliedBy(exp); - return calculated.toFixed(0); + const calculated = x.multipliedBy(exp) + return calculated.toFixed(0) } export function amountToUsd(amount, lookupPrice, token) { - if (['ETH', 'oETH'].includes(token.symbol) && !!lookupPrice['ethereum']) { + if (token.symbol === 'ETH' && !!lookupPrice['ethereum']) { return amount * lookupPrice['ethereum'].usd } else if (token.symbol === 'OMG' && !!lookupPrice['omisego']) { return amount * lookupPrice['omisego'].usd diff --git a/packages/omgx/wallet-frontend/src/util/coinImage.js b/packages/omgx/wallet-frontend/src/util/coinImage.js index 8f03f4313f0f..de863675b9ca 100644 --- a/packages/omgx/wallet-frontend/src/util/coinImage.js +++ b/packages/omgx/wallet-frontend/src/util/coinImage.js @@ -14,7 +14,8 @@ import uniLogo from 'images/uni.png'; import omgLogo from 'images/omg.png'; export const getCoinImage = (symbol) => { - let logo = null; + + let logo = null switch (symbol) { case "TEST": @@ -56,9 +57,6 @@ export const getCoinImage = (symbol) => { case "ETH": logo = ethLogo; break; - case "oETH": - logo = ethLogo; - break; case "JLKN": logo = TESTLogo; break; diff --git a/packages/omgx/wallet-frontend/src/util/masterConfig.js b/packages/omgx/wallet-frontend/src/util/masterConfig.js index 0942c6f82d35..4e5b4e7d9afd 100644 --- a/packages/omgx/wallet-frontend/src/util/masterConfig.js +++ b/packages/omgx/wallet-frontend/src/util/masterConfig.js @@ -23,7 +23,7 @@ NETWORKS = { addressUrl: `https://rinkeby.boba.network:8080/addresses.json`, addressOMGXUrl: `https://rinkeby.boba.network:8078/addresses.json`, OMGX_WATCHER_URL: `https://api-watcher.rinkeby.boba.network/`, - MM_Label: `Rinkeby Test Network`, + MM_Label: `Rinkeby`, L1: { name: "Rinkeby", chainId: 4, @@ -43,7 +43,7 @@ NETWORKS = { addressUrl: `https://mainnet.boba.network:8080/addresses.json`, addressOMGXUrl: `https://mainnet.boba.network:8078/addresses.json`, OMGX_WATCHER_URL: `https://api-watcher.mainnet.boba.network/`, - MM_Label: `Ethereum Mainnet`, + MM_Label: `Mainnet`, L1: { name: "Mainnet", chainId: 1, @@ -67,7 +67,7 @@ if (env === 'dev') { addressUrl: `http://${window.location.hostname}:8080/addresses.json`, addressOMGXUrl: `http://${window.location.hostname}:8078/addresses.json`, OMGX_WATCHER_URL: null, //Does not exist on local - MM_Label: `Local Network`, + MM_Label: `Local`, L1: { name: "Local L1", chainId: 31337, @@ -85,7 +85,7 @@ if (env === 'dev') { addressUrl: `https://rinkeby-integration.boba.network:8081/addresses.json`, addressOMGXUrl: `https://rinkeby-integration.boba.network:8081/omgx-addr.json`, OMGX_WATCHER_URL: `https://api-watcher.rinkeby-integration.boba.network/`, - MM_Label: `Rinkeby Int Test Network`, + MM_Label: `Rinkeby Int Test`, L1: { name: "Rinkeby", chainId: 4,