diff --git a/config/config.js b/config/config.js index 1b2d8eb..9a9fd4d 100644 --- a/config/config.js +++ b/config/config.js @@ -210,7 +210,6 @@ const Config = { GAS: process.env.GAS, STAKING: process.env.STAKING, BLOCK_EXPLORER: process.env.BLOCK_EXPLORER, - MESSAGE_TYPE_URL: '/gravity.v1.MsgSendToEth', }, ORCHESTRATOR: { ERC20_CONTRACT_ADDRESS: process.env.ERC20_CONTRACT_ADDRESS, diff --git a/src/frontend/resources/common/css/components-popups/loading-modal.css b/src/frontend/resources/common/css/components-popups/loading-modal.css index 9afbab3..fc96e96 100644 --- a/src/frontend/resources/common/css/components-popups/loading-modal.css +++ b/src/frontend/resources/common/css/components-popups/loading-modal.css @@ -27,6 +27,7 @@ .LoadingForm .Wrapper { display: flex; + flex-direction: column; justify-content: center; align-items: center; } @@ -47,6 +48,17 @@ margin-top: 20px; } +.LoadingForm .AdditionalText { + font-family: Poppins, sans-serif; + margin-bottom: 5px; + font-size: 12px; + font-weight: 600; + text-align: center; + margin-top: 20px; + margin-left: 20px; + margin-right: 20px; +} + /*Loading dots animation */ @keyframes blink { diff --git a/src/frontend/resources/common/css/components-popups/summary-modal.css b/src/frontend/resources/common/css/components-popups/summary-modal.css index 0bd445f..276eb6a 100644 --- a/src/frontend/resources/common/css/components-popups/summary-modal.css +++ b/src/frontend/resources/common/css/components-popups/summary-modal.css @@ -118,9 +118,10 @@ } .ModalContent .SummaryForm .AttentionIcon { - width: 55px; + width: 40px; height: 20px; margin-right: 7px; + padding-right: 7px; align-self: center; } diff --git a/src/frontend/resources/common/js/components-inc/Button.tsx b/src/frontend/resources/common/js/components-inc/Button.tsx index 4d8d312..b357e7f 100644 --- a/src/frontend/resources/common/js/components-inc/Button.tsx +++ b/src/frontend/resources/common/js/components-inc/Button.tsx @@ -1,14 +1,13 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import { createMuiTheme } from '@material-ui/core/styles'; +import { createTheme } from '@material-ui/core/styles'; import { ThemeProvider } from '@material-ui/styles'; import MuiButton from '@material-ui/core/Button'; import './../../css/components-inc/button.css'; import S from '../utilities/Main'; -const theme01 = createMuiTheme({ +const theme01 = createTheme({ palette: { action: { disabledBackground: 'rgba(54, 62, 89, 1)', @@ -25,7 +24,7 @@ const theme01 = createMuiTheme({ }, }); -const theme02 = createMuiTheme({ +const theme02 = createTheme({ palette: { action: { disabledBackground: 'rgba(99, 109, 143, 0.3)', diff --git a/src/frontend/resources/common/js/components-popups/LoadingModal.tsx b/src/frontend/resources/common/js/components-popups/LoadingModal.tsx index d0dd23a..3bb5abf 100644 --- a/src/frontend/resources/common/js/components-popups/LoadingModal.tsx +++ b/src/frontend/resources/common/js/components-popups/LoadingModal.tsx @@ -7,10 +7,12 @@ import '../../css/components-popups/loading-modal.css'; const LoadingModal = ({ closeModal, isOpen, + additionalText, } : { closeModal: Function isOpen: boolean + additionalText: string }) => { const cudosMainLogo = '../../../../resources/common/img/favicon/cudos-80x80.svg'; @@ -32,6 +34,9 @@ const LoadingModal = ({ . . +
+ {additionalText} +
diff --git a/src/frontend/resources/common/js/components-popups/SummaryModal.tsx b/src/frontend/resources/common/js/components-popups/SummaryModal.tsx index 87580bb..9bef982 100644 --- a/src/frontend/resources/common/js/components-popups/SummaryModal.tsx +++ b/src/frontend/resources/common/js/components-popups/SummaryModal.tsx @@ -31,7 +31,7 @@ const SummaryModal = ({ }) => { const CUDOS_SUCCESS_MESSAGE = `Your bridge transaction was successfully submitted to ${ProjectUtils.CUDOS_NETWORK_TEXT}. It is awaiting to be included in a batch and can take up to 120 ${ProjectUtils.CUDOS_NETWORK_TEXT} blocks to be fully executed on ${ProjectUtils.ETHEREUM_NETWORK_TEXT}.`; - const ETHEREUM_SUCCESS_MESSAGE = `Your bridge transaction was successfully submitted to ${ProjectUtils.ETHEREUM_NETWORK_TEXT} and will be fully executed on ${ProjectUtils.CUDOS_NETWORK_TEXT} in roughly 6 minutes.`; + const ETHEREUM_SUCCESS_MESSAGE = `Your bridge transaction was successfully submitted to ${ProjectUtils.ETHEREUM_NETWORK_TEXT} and ${ProjectUtils.CUDOS_NETWORK_TEXT}.`; const cudosLogoSmall = '../../../../resources/common/img/favicon/cudos-18x18.svg'; const ethLogoSmall = '../../../../resources/common/img/favicon/eth-18x18.svg'; diff --git a/src/frontend/resources/common/js/models/ledgers/CosmosNetworkH.ts b/src/frontend/resources/common/js/models/ledgers/CosmosNetworkH.ts index 5860661..95ed8e9 100644 --- a/src/frontend/resources/common/js/models/ledgers/CosmosNetworkH.ts +++ b/src/frontend/resources/common/js/models/ledgers/CosmosNetworkH.ts @@ -17,4 +17,5 @@ export default class CosmosNetworkH { static BECH32_PREFIX_CONS_PUB = 'cudosvalconspub'; static BECH32_ACC_ADDR_LENGTH = 44; + static MESSAGE_TYPE_URL = '/gravity.v1.MsgSendToEth'; } diff --git a/src/frontend/resources/common/js/models/ledgers/KeplrLedger.ts b/src/frontend/resources/common/js/models/ledgers/KeplrLedger.ts index 2062f26..d954ab5 100644 --- a/src/frontend/resources/common/js/models/ledgers/KeplrLedger.ts +++ b/src/frontend/resources/common/js/models/ledgers/KeplrLedger.ts @@ -114,7 +114,6 @@ export default class KeplrLedger implements Ledger { }, }); } catch (ex) { - console.log(ex); this.walletError = 'Failed to suggest the chain' } @@ -169,7 +168,7 @@ export default class KeplrLedger implements Ledger { const offlineSigner = window.getOfflineSigner(this.chainID); const myRegistry = new Registry([ ...defaultRegistryTypes, - [Config.CUDOS_NETWORK.MESSAGE_TYPE_URL, MsgSendToEth], + [CosmosNetworkH.MESSAGE_TYPE_URL, MsgSendToEth], ]); const client = await SigningStargateClient.connectWithSigner(this.rpcEndpoint, offlineSigner, { registry: myRegistry, @@ -184,7 +183,7 @@ export default class KeplrLedger implements Ledger { const [client, account] = await this.GetKeplrClientAndAccount(); const msgSend = [{ - typeUrl: Config.CUDOS_NETWORK.MESSAGE_TYPE_URL, + typeUrl: CosmosNetworkH.MESSAGE_TYPE_URL, value: { sender: account.address, ethDest: destiantionAddress, @@ -203,76 +202,23 @@ export default class KeplrLedger implements Ledger { this.walletError = null; const msgFee = await this.EstimateFee( client, - GasPrice.fromString(Config.CUDOS_NETWORK.FEE+'acudos'), - account.address, - msgSend, - 'Fee Estimation Message' - ); - - const result = await client.signAndBroadcast( + GasPrice.fromString(`${Config.CUDOS_NETWORK.GAS_PRICE}acudos`), account.address, msgSend, - msgFee, - 'Sent with CUDOS Gravity Bridge' + 'Fee Estimation Message', ); - this.txHash = result.transactionHash; - assertIsDeliverTxSuccess(result); - } catch (e) { - console.log(e); - throw new Error(this.walletError = 'Failed to send transaction!'); - } - } - - async requestBatch() { - const proposalTypePath = '/gravity.v1.MsgRequestBatch' - - const chainId = Config.CUDOS_NETWORK.CHAIN_ID; - await window.keplr.enable(chainId); - const offlineSigner = window.getOfflineSigner(chainId); - - const account = (await offlineSigner.getAccounts())[0]; - - const msgSend = [{ - typeUrl: proposalTypePath, - value: { - sender: account.address, - denom: CosmosNetworkH.CURRENCY_DENOM, - }, - - }]; - - const msgFee = { - amount: [{ - denom: CosmosNetworkH.CURRENCY_DENOM, - amount: Config.CUDOS_NETWORK.FEE, - }], - gas: Config.CUDOS_NETWORK.GAS, - } - - try { - this.walletError = null; - const myRegistry = new Registry([ - ...defaultRegistryTypes, - [proposalTypePath, MsgRequestBatch], - ]) - - const rpcEndpoint = Config.CUDOS_NETWORK.RPC; - const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, offlineSigner, { - registry: myRegistry, - }); - const result = await client.signAndBroadcast( account.address, msgSend, msgFee, + 'Sent with CUDOS Gravity Bridge', ); - assertIsBroadcastTxSuccess(result); + this.txHash = result.transactionHash; + assertIsDeliverTxSuccess(result); } catch (e) { - console.log(e); - this.walletError = 'Failed to send transaction!' - throw new Error('Failed to send transaction!'); + throw new Error(this.walletError = 'Failed to send transaction!'); } } @@ -287,7 +233,6 @@ export default class KeplrLedger implements Ledger { return new BigNumber(amount).div(CosmosNetworkH.CURRENCY_1_CUDO); } catch (e) { - console.log(e); this.walletError = 'Failed to get balance!' } } diff --git a/src/frontend/resources/common/js/models/ledgers/Ledger.ts b/src/frontend/resources/common/js/models/ledgers/Ledger.ts index 92d2714..69d0897 100644 --- a/src/frontend/resources/common/js/models/ledgers/Ledger.ts +++ b/src/frontend/resources/common/js/models/ledgers/Ledger.ts @@ -8,7 +8,7 @@ export default interface Ledger { account: string, walletError: string, txHash: string, - txNonce: Number, + txNonce: string, connect: () => Promise, disconnect: () => Promise, send: (amount: BigNumber, destination: string) => Promise, @@ -17,7 +17,6 @@ export default interface Ledger { gas: string; }>, GetKeplrClientAndAccount: () => Promise, - requestBatch: () => Promise < void >, isAddressValid: (address: string) => boolean, getBalance(): Promise, } diff --git a/src/frontend/resources/common/js/models/ledgers/MetamaskLedger.ts b/src/frontend/resources/common/js/models/ledgers/MetamaskLedger.ts index a8c62df..9307dd0 100644 --- a/src/frontend/resources/common/js/models/ledgers/MetamaskLedger.ts +++ b/src/frontend/resources/common/js/models/ledgers/MetamaskLedger.ts @@ -17,7 +17,7 @@ export default class MetamaskLedger implements Ledger { @observable account: string; @observable walletError: string; @observable txHash: string; - @observable txNonce: Number; + @observable txNonce: string; erc20Instance: any; gas: string; @@ -61,7 +61,6 @@ export default class MetamaskLedger implements Ledger { async disconnect(): Promise { return new Promise < void >((resolve, reject) => { - console.log('disconnecting...'); resolve(); }); } @@ -111,12 +110,6 @@ export default class MetamaskLedger implements Ledger { } - async requestBatch(): Promise { - return new Promise < void >((resolve, reject) => { - resolve(); - }); - } - async getBalance(): Promise { this.walletError = null; try { diff --git a/src/frontend/resources/general/js/components-pages/CudosBridgePageComponent.tsx b/src/frontend/resources/general/js/components-pages/CudosBridgePageComponent.tsx index c3d0d15..c39dd1e 100644 --- a/src/frontend/resources/general/js/components-pages/CudosBridgePageComponent.tsx +++ b/src/frontend/resources/general/js/components-pages/CudosBridgePageComponent.tsx @@ -62,6 +62,7 @@ interface State { minBridgeFeeAmount: BigNumber; estimatedGasFees: BigNumber; validAmount: Boolean; + loadingModalAdditionalText: string; } const cudosMainLogo = '../../../../resources/common/img/favicon/cudos-40x40.svg' @@ -117,6 +118,7 @@ export default class CudosBridgeComponent extends ContextPageComponent { clearTimeout(this.inputTimeouts.amount); - const bigAmount = new BigNumber(amount); + let bigAmount = new BigNumber(amount); const fromNetwork = this.state.selectedFromNetwork; let validAmount = false; let amountError = S.INT_TRUE; let simulatedCost = new BigNumber(0); - this.setState({ amount: bigAmount, displayAmount: amount, }); - let minBridgeFeeAmount = new BigNumber(0); - - if (this.isFromCosmos(fromNetwork)) { - minBridgeFeeAmount = this.state.minBridgeFeeAmount; - } - if (!bigAmount.isNaN() && !bigAmount.isLessThan(new BigNumber(1).dividedBy(CosmosNetworkH.CURRENCY_1_CUDO)) && this.validCudosNumber(amount) - && !bigAmount.isGreaterThan(BigNumber.minimum(this.state.walletBalance, this.state.contractBalance).minus(minBridgeFeeAmount).absoluteValue()) ) { - - let maximumAmount = this.state.walletBalance.minus(minBridgeFeeAmount).minus(amount); - this.inputTimeouts.amount = setTimeout(async () => { + let minBridgeFeeAmount = new BigNumber(0); + if (this.isFromCosmos(fromNetwork)) { + minBridgeFeeAmount = this.state.minBridgeFeeAmount; simulatedCost = await this.simulatedMsgsCost(amount); - maximumAmount = maximumAmount.minus(simulatedCost); } - if (maximumAmount.isGreaterThanOrEqualTo(0) && maximumAmount.isLessThan(this.state.contractBalance)) { + bigAmount = bigAmount.plus(minBridgeFeeAmount).plus(simulatedCost); + + if ( + bigAmount.isLessThanOrEqualTo(this.state.walletBalance) + && (!this.isFromCosmos(fromNetwork) || bigAmount.isLessThanOrEqualTo(this.state.contractBalance)) + ) { + validAmount = true amountError = S.INT_FALSE } @@ -474,16 +470,17 @@ export default class CudosBridgeComponent extends ContextPageComponent => { + getCosmosGravityTxByNonce = async (nonce: string): Promise => { let result = ''; const heightRes = await (await fetch(Config.CUDOS_NETWORK.RPC + BLOCK_HEIGHT__RPC_ENDPOINT)).json(); - let height = heightRes.result.response.last_block_height; + let height = Number(heightRes.result.response.last_block_height); while (result === '') { const txData = await (await fetch(Config.CUDOS_NETWORK.RPC + GRAVITY_TXS_RPC_ENDPOINT)).json(); - const txHashes: string[] = txData.result.txs.filter((tx) => tx.height > height).map((tx) => tx.hash); - height = txData.result.txs.reduce((a, b) => { - return a.height > b.height ? a : b; - }).height; + const filteredTxs = txData.result.txs.filter((tx) => Number(tx.height) > height); + if (filteredTxs.length > 0) { + const txHashes: string[] = filteredTxs.map((tx) => tx.hash); - for (let i=0; i < txHashes.length; i++) { - const hash = txHashes[i]; - let res = await (await fetch(Config.CUDOS_NETWORK.API + GRAVITY_TX_BY_HASH_REST_ENDPOINT + hash)).json(); - const txEventNonce = res.tx.body.messages[0].event_nonce; + height = filteredTxs.reduce((a, b) => { + return Number(a.height) > Number(b.height) ? a : b; + }, { height: 0 }).height; - if (nonce === txEventNonce) { - result = hash; - return result; + for (let i=0; i < txHashes.length; i++) { + const hash = txHashes[i]; + + let res = await (await fetch(Config.CUDOS_NETWORK.API + GRAVITY_TX_BY_HASH_REST_ENDPOINT + hash)).json(); + const txEventNonce = res.tx.body.messages[0].event_nonce; + + if (nonce === txEventNonce) { + result = hash; + return result; + } } } - - await new Promise((resolve) => setTimeout(resolve, 10000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); } return ''; @@ -791,6 +791,7 @@ export default class CudosBridgeComponent extends ContextPageComponent this.setState({ isTransactionFail: false, isOpen: false })} + additionalText={ this.state.loadingModalAdditionalText } /> { await connectWallet(KEPLR_WALLET); await onChangeAccount(KEPLR_WALLET) - console.log('reconnect Keplr...'); }); }, []); @@ -66,7 +65,6 @@ const TransferForm = ({ localStorage.setItem('manualAccountChange', 'true') await connectWallet(METAMASK_WALLET); await onChangeAccount(METAMASK_WALLET); - console.log('reconnect Metamask...'); }); } }, []);