Add support for STAKE token ERC677-to-ERC677 through AMB mode in Bridge UI (#328)

This commit is contained in:
Gerardo Nardelli 2020-05-18 17:36:52 -03:00 committed by GitHub
parent 10f67168a7
commit 62f9a080c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 529 additions and 186 deletions

@ -7,13 +7,17 @@ const FOREIGN_ERC_TO_NATIVE_ABI = require('../contracts/build/contracts/ForeignB
const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi const ERC20_ABI = require('../contracts/build/contracts/ERC20').abi
const ERC677_ABI = require('../contracts/build/contracts/ERC677').abi const ERC677_ABI = require('../contracts/build/contracts/ERC677').abi
const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677BridgeToken').abi const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677BridgeToken').abi
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/IBlockReward').abi const BLOCK_REWARD_ABI = require('../contracts/build/contracts/BlockReward').abi
const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi
const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
const BOX_ABI = require('../contracts/build/contracts/Box').abi const BOX_ABI = require('../contracts/build/contracts/Box').abi
const SAI_TOP = require('../contracts/build/contracts/SaiTopMock').abi const SAI_TOP = require('../contracts/build/contracts/SaiTopMock').abi
const HOME_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeAMBErc677ToErc677').abi
const FOREIGN_AMB_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignAMBErc677ToErc677').abi
const HOME_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/HomeStakeTokenMediator').abi
const FOREIGN_STAKE_ERC_TO_ERC_ABI = require('../contracts/build/contracts/ForeignStakeTokenMediator').abi
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis') const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
const { BRIDGE_MODES } = require('./constants') const { BRIDGE_MODES } = require('./constants')
@ -67,6 +71,12 @@ function getBridgeABIs(bridgeMode) {
} else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) { } else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
HOME_ABI = HOME_AMB_ABI HOME_ABI = HOME_AMB_ABI
FOREIGN_ABI = FOREIGN_AMB_ABI FOREIGN_ABI = FOREIGN_AMB_ABI
} else if (bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC) {
HOME_ABI = HOME_AMB_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_AMB_ERC_TO_ERC_ABI
} else if (bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
HOME_ABI = HOME_STAKE_ERC_TO_ERC_ABI
FOREIGN_ABI = FOREIGN_STAKE_ERC_TO_ERC_ABI
} else { } else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`) throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
} }
@ -94,5 +104,7 @@ module.exports = {
HOME_AMB_ABI, HOME_AMB_ABI,
FOREIGN_AMB_ABI, FOREIGN_AMB_ABI,
BOX_ABI, BOX_ABI,
SAI_TOP SAI_TOP,
HOME_STAKE_ERC_TO_ERC_ABI,
FOREIGN_STAKE_ERC_TO_ERC_ABI
} }

@ -3,7 +3,9 @@ const BRIDGE_MODES = {
ERC_TO_ERC: 'ERC_TO_ERC', ERC_TO_ERC: 'ERC_TO_ERC',
ERC_TO_NATIVE: 'ERC_TO_NATIVE', ERC_TO_NATIVE: 'ERC_TO_NATIVE',
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1', NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1',
ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE' ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE',
AMB_ERC_TO_ERC: 'AMB_ERC_TO_ERC',
STAKE_AMB_ERC_TO_ERC: 'STAKE_AMB_ERC_TO_ERC'
} }
const ERC_TYPES = { const ERC_TYPES = {
@ -14,6 +16,7 @@ const ERC_TYPES = {
const FEE_MANAGER_MODE = { const FEE_MANAGER_MODE = {
ONE_DIRECTION: 'ONE_DIRECTION', ONE_DIRECTION: 'ONE_DIRECTION',
BOTH_DIRECTIONS: 'BOTH_DIRECTIONS', BOTH_DIRECTIONS: 'BOTH_DIRECTIONS',
ONE_DIRECTION_STAKE: 'ONE_DIRECTION_STAKE',
UNDEFINED: 'UNDEFINED' UNDEFINED: 'UNDEFINED'
} }

@ -3,7 +3,7 @@ const { BRIDGE_MODES, ERC_TYPES } = require('../constants')
describe('constants', () => { describe('constants', () => {
it('should contain correct number of bridge types', () => { it('should contain correct number of bridge types', () => {
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(5) expect(Object.keys(BRIDGE_MODES).length).to.be.equal(7)
}) })
it('should contain correct number of erc types', () => { it('should contain correct number of erc types', () => {

@ -61,4 +61,99 @@ describe('getTokenType', () => {
// Then // Then
expect(type).to.equal(ERC_TYPES.ERC20) expect(type).to.equal(ERC_TYPES.ERC20)
}) })
it('should return ERC20 if bridgeContract and isBridge are not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.reject()
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
it('should return ERC677 if isBridge returns true', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.resolve(true)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC677 if isBridge returns true and bridgeContract not present', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
isBridge: () => {
return {
call: () => Promise.resolve(true)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC677)
})
it('should return ERC20 if isBridge returns false', async () => {
// Given
const bridgeAddress = '0xCecBE80Ed3548dE11D7d2D922a36576eA40C4c26'
const contract = {
methods: {
bridgeContract: () => {
return {
call: () => Promise.reject()
}
},
isBridge: () => {
return {
call: () => Promise.resolve(false)
}
}
}
}
// When
const type = await getTokenType(contract, bridgeAddress)
// Then
expect(type).to.equal(ERC_TYPES.ERC20)
})
}) })

@ -12,6 +12,10 @@ function decodeBridgeMode(bridgeModeHash) {
return BRIDGE_MODES.ERC_TO_NATIVE return BRIDGE_MODES.ERC_TO_NATIVE
case '0x2544fbb9': case '0x2544fbb9':
return BRIDGE_MODES.ARBITRARY_MESSAGE return BRIDGE_MODES.ARBITRARY_MESSAGE
case '0x16ea01e9':
return BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
case '0x76595b56':
return BRIDGE_MODES.AMB_ERC_TO_ERC
default: default:
throw new Error(`Unrecognized bridge mode hash: '${bridgeModeHash}'`) throw new Error(`Unrecognized bridge mode hash: '${bridgeModeHash}'`)
} }
@ -46,10 +50,31 @@ const getTokenType = async (bridgeTokenContract, bridgeAddress) => {
return ERC_TYPES.ERC20 return ERC_TYPES.ERC20
} }
} catch (e) { } catch (e) {
return ERC_TYPES.ERC20 try {
const isBridge = await bridgeTokenContract.methods.isBridge(bridgeAddress).call()
if (isBridge) {
return ERC_TYPES.ERC677
} else {
return ERC_TYPES.ERC20
}
} catch (e) {
return ERC_TYPES.ERC20
}
} }
} }
const isErcToErcMode = bridgeMode => {
return (
bridgeMode === BRIDGE_MODES.ERC_TO_ERC ||
bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC ||
bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
)
}
const isMediatorMode = bridgeMode => {
return bridgeMode === BRIDGE_MODES.AMB_ERC_TO_ERC || bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC
}
const getUnit = bridgeMode => { const getUnit = bridgeMode => {
let unitHome = null let unitHome = null
let unitForeign = null let unitForeign = null
@ -62,6 +87,9 @@ const getUnit = bridgeMode => {
} else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) { } else if (bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
unitHome = 'Native coins' unitHome = 'Native coins'
unitForeign = 'Tokens' unitForeign = 'Tokens'
} else if (bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
unitHome = 'Tokens'
unitForeign = 'Tokens'
} else { } else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`) throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
} }
@ -260,5 +288,7 @@ module.exports = {
normalizeGasPrice, normalizeGasPrice,
gasPriceFromSupplier, gasPriceFromSupplier,
gasPriceFromContract, gasPriceFromContract,
gasPriceWithinLimits gasPriceWithinLimits,
isErcToErcMode,
isMediatorMode
} }

@ -1 +1 @@
Subproject commit a7ce4441ab77e1c3e4d01017d862c53516933645 Subproject commit e550067c7680d416f40de95fc4c8e5b073279ee6

@ -4,7 +4,7 @@ import { toHex } from 'web3-utils'
import foreignLogoPurple from '../assets/images/logos/logo-poa-20-purple@2x.png' import foreignLogoPurple from '../assets/images/logos/logo-poa-20-purple@2x.png'
import homeLogoPurple from '../assets/images/logos/logo-poa-sokol-purple@2x.png' import homeLogoPurple from '../assets/images/logos/logo-poa-sokol-purple@2x.png'
import swal from 'sweetalert' import swal from 'sweetalert'
import { BRIDGE_MODES, ERC_TYPES } from '../../../commons' import { BRIDGE_MODES, ERC_TYPES, isErcToErcMode } from '../../../commons'
import { BridgeAddress } from './index' import { BridgeAddress } from './index'
import { BridgeForm } from './index' import { BridgeForm } from './index'
import { BridgeNetwork } from './index' import { BridgeNetwork } from './index'
@ -63,7 +63,6 @@ export class Bridge extends React.Component {
async _sendToHome(amount) { async _sendToHome(amount) {
const { web3Store, homeStore, alertStore, txStore, bridgeMode } = this.props.RootStore const { web3Store, homeStore, alertStore, txStore, bridgeMode } = this.props.RootStore
const isErcToErcMode = bridgeMode === BRIDGE_MODES.ERC_TO_ERC
const { isLessThan, isGreaterThan } = this const { isLessThan, isGreaterThan } = this
if (web3Store.metamaskNet.id.toString() !== web3Store.homeNet.id.toString()) { if (web3Store.metamaskNet.id.toString() !== web3Store.homeNet.id.toString()) {
swal('Error', `Please switch wallet to ${web3Store.homeNet.name} network`, 'error') swal('Error', `Please switch wallet to ${web3Store.homeNet.name} network`, 'error')
@ -98,7 +97,7 @@ export class Bridge extends React.Component {
} else { } else {
try { try {
alertStore.setLoading(true) alertStore.setLoading(true)
if (isErcToErcMode) { if (isErcToErcMode(bridgeMode)) {
return txStore.erc677transferAndCall({ return txStore.erc677transferAndCall({
to: homeStore.COMMON_HOME_BRIDGE_ADDRESS, to: homeStore.COMMON_HOME_BRIDGE_ADDRESS,
from: web3Store.defaultAccount.address, from: web3Store.defaultAccount.address,
@ -259,7 +258,6 @@ export class Bridge extends React.Component {
loadHomeDetails = () => { loadHomeDetails = () => {
const { web3Store, homeStore, bridgeMode } = this.props.RootStore const { web3Store, homeStore, bridgeMode } = this.props.RootStore
const isErcToErcMode = bridgeMode === BRIDGE_MODES.ERC_TO_ERC
const isExternalErc20 = bridgeMode === BRIDGE_MODES.ERC_TO_ERC || bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE const isExternalErc20 = bridgeMode === BRIDGE_MODES.ERC_TO_ERC || bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE
const modalData = { const modalData = {
@ -274,7 +272,7 @@ export class Bridge extends React.Component {
minPerTx: homeStore.minPerTx, minPerTx: homeStore.minPerTx,
totalBalance: homeStore.balance, totalBalance: homeStore.balance,
balance: homeStore.getDisplayedBalance(), balance: homeStore.getDisplayedBalance(),
displayTokenAddress: isErcToErcMode, displayTokenAddress: isErcToErcMode(bridgeMode),
tokenAddress: homeStore.tokenAddress, tokenAddress: homeStore.tokenAddress,
tokenName: homeStore.tokenName, tokenName: homeStore.tokenName,
displayBridgeLimits: true, displayBridgeLimits: true,

@ -9,7 +9,8 @@ export const BridgeStatistics = ({
homeNativeSupplyTitle, homeNativeSupplyTitle,
foreignSupply, foreignSupply,
homeSymbol, homeSymbol,
foreignSymbol foreignSymbol,
displayNetworkTokenSupply
}) => ( }) => (
<div className="statistics-bridge-data"> <div className="statistics-bridge-data">
<DataBlock description="Users" value={numeral(users).format('0,0')} type="" /> <DataBlock description="Users" value={numeral(users).format('0,0')} type="" />
@ -21,7 +22,13 @@ export const BridgeStatistics = ({
/> />
<div className="separator" /> <div className="separator" />
<DataBlock <DataBlock
description={homeNativeSupplyTitle ? `Native Coins Amount` : `Totally minted by the bridge`} description={
displayNetworkTokenSupply
? `${homeSymbol} Tokens Amount`
: homeNativeSupplyTitle
? `Native Coins Amount`
: `Totally minted by the bridge`
}
value={numeral(homeBalance).format('0.00 a', Math.floor)} value={numeral(homeBalance).format('0.00 a', Math.floor)}
type={homeSymbol} type={homeSymbol}
/> />

@ -10,7 +10,7 @@ export const FeeStatistics = ({ depositFeeCollected, withdrawFeeCollected }) =>
<div className="statistics-fee-data" data-testid="fee-statistics-data"> <div className="statistics-fee-data" data-testid="fee-statistics-data">
{depositFeeCollected.shouldDisplay && ( {depositFeeCollected.shouldDisplay && (
<DataBlock <DataBlock
description="Deposit Fees" description={depositFeeCollected.title ? depositFeeCollected.title : 'Deposit Fees'}
value={numeral(depositFeeCollected.value).format('0,0.00 a', Math.floor)} value={numeral(depositFeeCollected.value).format('0,0.00 a', Math.floor)}
type={depositFeeCollected.type} type={depositFeeCollected.type}
dataTestid="deposit-fees-block" dataTestid="deposit-fees-block"
@ -19,7 +19,7 @@ export const FeeStatistics = ({ depositFeeCollected, withdrawFeeCollected }) =>
{depositFeeCollected.shouldDisplay && withdrawFeeCollected.shouldDisplay && <div className="separator" />} {depositFeeCollected.shouldDisplay && withdrawFeeCollected.shouldDisplay && <div className="separator" />}
{withdrawFeeCollected.shouldDisplay && ( {withdrawFeeCollected.shouldDisplay && (
<DataBlock <DataBlock
description="Withdrawal Fees" description={withdrawFeeCollected.title ? withdrawFeeCollected.title : 'Withdrawal Fees'}
value={numeral(withdrawFeeCollected.value).format('0,0.00 a', Math.floor)} value={numeral(withdrawFeeCollected.value).format('0,0.00 a', Math.floor)}
type={withdrawFeeCollected.type} type={withdrawFeeCollected.type}
dataTestid="withdrawal-fees-block" dataTestid="withdrawal-fees-block"

@ -25,11 +25,12 @@ export const NetworkDetails = ({
}) => { }) => {
const networkTitle = isHome ? 'Bridge Home' : 'Bridge Foreign' const networkTitle = isHome ? 'Bridge Home' : 'Bridge Foreign'
const logoClass = isHome ? 'home-logo home-logo-modal' : 'foreign-logo foreign-logo-modal' const logoClass = isHome ? 'home-logo home-logo-modal' : 'foreign-logo foreign-logo-modal'
const totalTitle = isHome const totalTitle =
? nativeSupplyTitle isHome && !displayTokenAddress
? `Native Coins Amount` ? nativeSupplyTitle
: `Totally minted by the bridge` ? `Native Coins Amount`
: `${currency} Tokens Amount` : `Totally minted by the bridge`
: `${currency} Tokens Amount`
const totalAmount = isHome ? totalBalance : totalSupply const totalAmount = isHome ? totalBalance : totalSupply
const formattedBalance = isNaN(numeral(balance).format('0.00', Math.floor)) const formattedBalance = isNaN(numeral(balance).format('0.00', Math.floor))
? numeral(0).format('0,0.00', Math.floor) ? numeral(0).format('0,0.00', Math.floor)

@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import yn from './utils/yn' import yn from './utils/yn'
import { BRIDGE_MODES } from '../../../commons' import { BRIDGE_MODES, isErcToErcMode } from '../../../commons'
import { BridgeStatistics } from './index' import { BridgeStatistics } from './index'
import { Redirect } from 'react-router' import { Redirect } from 'react-router'
import { TransactionsStatistics } from './TransactionsStatistics' import { TransactionsStatistics } from './TransactionsStatistics'
@ -12,9 +12,10 @@ import { FeeStatistics } from './FeeStatistics'
export class StatisticsPage extends React.Component { export class StatisticsPage extends React.Component {
render() { render() {
const { homeStore, foreignStore, bridgeMode, web3Store } = this.props.RootStore const { homeStore, foreignStore, bridgeMode, web3Store } = this.props.RootStore
const statisticsReady = homeStore.statistics.finished && foreignStore.statistics.finished
const isNativeToErc = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC const isNativeToErc = bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC
const leftTitle = isNativeToErc ? 'Deposits' : 'Withdraws' const leftTitle = isNativeToErc ? 'Deposits' : 'Withdrawals'
const rightTitle = isNativeToErc ? 'Withdraws' : 'Deposits' const rightTitle = isNativeToErc ? 'Withdrawals' : 'Deposits'
const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env
const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN) const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN)
@ -27,13 +28,14 @@ export class StatisticsPage extends React.Component {
<div className="statistics-bridge-container"> <div className="statistics-bridge-container">
<span className="statistics-bridge-title statistics-title">Bridge Statistics</span> <span className="statistics-bridge-title statistics-title">Bridge Statistics</span>
<BridgeStatistics <BridgeStatistics
users={homeStore.statistics.finished ? homeStore.statistics.users.size : ''} users={statisticsReady ? homeStore.statistics.users.size : ''}
totalBridged={homeStore.statistics.finished ? homeStore.statistics.totalBridged.toString() : ''} totalBridged={statisticsReady ? homeStore.statistics.totalBridged.toString() : ''}
homeBalance={homeStore.balance} homeBalance={homeStore.balance}
homeSymbol={homeStore.symbol} homeSymbol={homeStore.symbol}
homeNativeSupplyTitle={isNativeToErc} homeNativeSupplyTitle={isNativeToErc}
foreignSymbol={foreignStore.symbol} foreignSymbol={foreignStore.symbol}
foreignSupply={foreignStore.totalSupply} foreignSupply={foreignStore.totalSupply}
displayNetworkTokenSupply={isErcToErcMode(bridgeMode)}
/> />
</div> </div>
{homeStore.depositFeeCollected.finished && {homeStore.depositFeeCollected.finished &&
@ -48,17 +50,17 @@ export class StatisticsPage extends React.Component {
<div className="statistics-deposit-container"> <div className="statistics-deposit-container">
<span className="statistics-deposit-title statistics-title">Tokens {leftTitle}</span> <span className="statistics-deposit-title statistics-title">Tokens {leftTitle}</span>
<TransactionsStatistics <TransactionsStatistics
txNumber={homeStore.statistics.finished ? homeStore.statistics.deposits : ''} txNumber={statisticsReady ? homeStore.statistics.deposits : ''}
type={foreignStore.symbol} type={foreignStore.symbol}
value={homeStore.statistics.finished ? homeStore.statistics.depositsValue : ''} value={statisticsReady ? homeStore.statistics.depositsValue : ''}
/> />
</div> </div>
<div className="statistics-withdraw-container"> <div className="statistics-withdraw-container">
<span className="statistics-withdraw-title statistics-title">Tokens {rightTitle}</span> <span className="statistics-withdraw-title statistics-title">Tokens {rightTitle}</span>
<TransactionsStatistics <TransactionsStatistics
txNumber={homeStore.statistics.finished ? homeStore.statistics.withdraws : ''} txNumber={statisticsReady ? homeStore.statistics.withdrawals : ''}
type={foreignStore.symbol} type={foreignStore.symbol}
value={homeStore.statistics.finished ? homeStore.statistics.withdrawsValue : ''} value={statisticsReady ? homeStore.statistics.withdrawalsValue : ''}
/> />
</div> </div>
</div> </div>

@ -10,7 +10,9 @@ import {
getBridgeABIs, getBridgeABIs,
getTokenType, getTokenType,
ERC20_BYTES32_ABI, ERC20_BYTES32_ABI,
getDeployedAtBlock getDeployedAtBlock,
isMediatorMode,
HOME_V1_ABI
} from '../../../commons' } from '../../../commons'
import { import {
getMaxPerTxLimit, getMaxPerTxLimit,
@ -103,6 +105,11 @@ class ForeignStore {
@observable @observable
tokenType = '' tokenType = ''
@observable
statistics = {
finished: false
}
feeManager = { feeManager = {
totalFeeDistributedFromSignatures: BN(0), totalFeeDistributedFromSignatures: BN(0),
totalFeeDistributedFromAffirmation: BN(0) totalFeeDistributedFromAffirmation: BN(0)
@ -142,6 +149,7 @@ class ForeignStore {
this.getCurrentLimit() this.getCurrentLimit()
this.getFee() this.getFee()
this.getValidators() this.getValidators()
this.getStatistics()
this.getFeeEvents() this.getFeeEvents()
setInterval(() => { setInterval(() => {
this.getBlockNumber() this.getBlockNumber()
@ -239,58 +247,62 @@ class ForeignStore {
@action @action
async getEvents(fromBlock, toBlock) { async getEvents(fromBlock, toBlock) {
try { fromBlock = fromBlock || this.filteredBlockNumber || this.latestBlockNumber - 50
fromBlock = fromBlock || this.filteredBlockNumber || this.latestBlockNumber - 50 toBlock = toBlock || this.filteredBlockNumber || 'latest'
toBlock = toBlock || this.filteredBlockNumber || 'latest'
if (fromBlock < 0) { if (fromBlock < 0) {
fromBlock = 0 fromBlock = 0
} }
let foreignEvents = await getPastEvents(this.foreignBridge, fromBlock, toBlock).catch(e => { if (!isMediatorMode(this.rootStore.bridgeMode)) {
console.error("Couldn't get events", e) try {
return [] let foreignEvents = await getPastEvents(this.foreignBridge, fromBlock, toBlock).catch(e => {
}) console.error("Couldn't get events", e)
return []
if (!this.filter) {
this.events = foreignEvents
}
if (this.waitingForConfirmation.size) {
const confirmationEvents = foreignEvents.filter(
event =>
event.event === 'RelayedMessage' && this.waitingForConfirmation.has(event.returnValues.transactionHash)
)
confirmationEvents.forEach(async event => {
const TxReceipt = await this.getTxReceipt(event.transactionHash)
if (TxReceipt && TxReceipt.logs && TxReceipt.logs.length > 1 && this.waitingForConfirmation.size) {
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitForeign
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.FOREIGN_TRANSFER_SUCCESS
)
}, 2000)
this.waitingForConfirmation.delete(event.returnValues.transactionHash)
}
}) })
if (confirmationEvents.length) { if (!this.filter) {
removePendingTransaction() this.events = foreignEvents
} }
}
return foreignEvents if (this.waitingForConfirmation.size) {
} catch (e) { const confirmationEvents = foreignEvents.filter(
this.alertStore.pushError( event =>
`Cannot establish connection to Foreign Network.\n event.event === 'RelayedMessage' && this.waitingForConfirmation.has(event.returnValues.transactionHash)
)
confirmationEvents.forEach(async event => {
const TxReceipt = await this.getTxReceipt(event.transactionHash)
if (TxReceipt && TxReceipt.logs && TxReceipt.logs.length > 1 && this.waitingForConfirmation.size) {
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitForeign
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.FOREIGN_TRANSFER_SUCCESS
)
}, 2000)
this.waitingForConfirmation.delete(event.returnValues.transactionHash)
}
})
if (confirmationEvents.length) {
removePendingTransaction()
}
}
return foreignEvents
} catch (e) {
this.alertStore.pushError(
`Cannot establish connection to Foreign Network.\n
Please make sure you have set it up in env variables`, Please make sure you have set it up in env variables`,
this.alertStore.FOREIGN_CONNECTION_ERROR this.alertStore.FOREIGN_CONNECTION_ERROR
) )
}
} else {
this.detectMediatorTransferFinished(fromBlock, toBlock)
} }
} }
@ -379,30 +391,68 @@ class ForeignStore {
@action @action
async getValidators() { async getValidators() {
try { if (!isMediatorMode(this.rootStore.bridgeMode)) {
const foreignValidatorsAddress = await getValidatorContract(this.foreignBridge) try {
this.foreignBridgeValidators = new this.foreignWeb3.eth.Contract(BRIDGE_VALIDATORS_ABI, foreignValidatorsAddress) const foreignValidatorsAddress = await getValidatorContract(this.foreignBridge)
this.foreignBridgeValidators = new this.foreignWeb3.eth.Contract(
BRIDGE_VALIDATORS_ABI,
foreignValidatorsAddress
)
this.requiredSignatures = await getRequiredSignatures(this.foreignBridgeValidators) this.requiredSignatures = await getRequiredSignatures(this.foreignBridgeValidators)
this.validatorsCount = await getValidatorCount(this.foreignBridgeValidators) this.validatorsCount = await getValidatorCount(this.foreignBridgeValidators)
this.validators = await getValidatorList(foreignValidatorsAddress, this.foreignWeb3.eth) this.validators = await getValidatorList(foreignValidatorsAddress, this.foreignWeb3.eth)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
}
} }
} }
async getFeeEvents() { async getStatistics() {
try { try {
const deployedAtBlock = await getDeployedAtBlock(this.foreignBridge) if (isMediatorMode(this.rootStore.bridgeMode)) {
const events = await getPastEvents(this.foreignBridge, deployedAtBlock, 'latest') const events = await getPastEvents(this.foreignBridge, 0, 'latest', 'TokensBridged')
processLargeArrayAsync(events, this.processMediatorEvent, () => {
processLargeArrayAsync(events, this.processEvent, () => { this.statistics.finished = true
this.feeEventsFinished = true this.rootStore.homeStore.statistics.totalBridged = this.rootStore.homeStore.statistics.totalBridged.plus(
}) this.rootStore.homeStore.statistics.withdrawalsValue
)
})
} else {
this.statistics.finished = true
}
} catch (e) { } catch (e) {
console.error(e) console.error(e)
this.getFeeEvents() this.getStatistics()
}
}
processMediatorEvent = event => {
if (event.returnValues && event.returnValues.recipient) {
this.rootStore.homeStore.statistics.users.add(event.returnValues.recipient)
}
this.rootStore.homeStore.statistics.withdrawals++
this.rootStore.homeStore.statistics.withdrawalsValue = this.rootStore.homeStore.statistics.withdrawalsValue.plus(
BN(fromDecimals(event.returnValues.value, this.tokenDecimals))
)
}
async getFeeEvents() {
if (!isMediatorMode(this.rootStore.bridgeMode)) {
try {
const deployedAtBlock = await getDeployedAtBlock(this.foreignBridge)
const events = await getPastEvents(this.foreignBridge, deployedAtBlock, 'latest')
processLargeArrayAsync(events, this.processEvent, () => {
this.feeEventsFinished = true
})
} catch (e) {
console.error(e)
this.getFeeEvents()
}
} else {
this.feeEventsFinished = true
} }
} }
@ -417,6 +467,33 @@ class ForeignStore {
) )
} }
} }
async detectMediatorTransferFinished(fromBlock, toBlock) {
if (this.waitingForConfirmation.size > 0) {
try {
const events = await getPastEvents(this.foreignBridge, fromBlock, toBlock, 'TokensBridged')
const confirmationEvents = events.filter(event => this.waitingForConfirmation.has(event.returnValues.messageId))
if (confirmationEvents.length > 0) {
const event = confirmationEvents[0]
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitForeign
this.waitingForConfirmation.delete(event.returnValues.messageId)
removePendingTransaction()
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.FOREIGN_TRANSFER_SUCCESS
)
}, 2000)
}
} catch (e) {
console.log(e)
}
}
}
} }
export default ForeignStore export default ForeignStore

@ -12,7 +12,9 @@ import {
getBridgeABIs, getBridgeABIs,
HOME_V1_ABI, HOME_V1_ABI,
ERC20_BYTES32_ABI, ERC20_BYTES32_ABI,
getDeployedAtBlock getDeployedAtBlock,
isErcToErcMode,
isMediatorMode
} from '../../../commons' } from '../../../commons'
import { import {
getMaxPerTxLimit, getMaxPerTxLimit,
@ -37,7 +39,8 @@ import {
getBlockRewardContract, getBlockRewardContract,
getValidatorContract, getValidatorContract,
getRequiredSignatures, getRequiredSignatures,
getValidatorCount getValidatorCount,
getFee
} from './utils/contract' } from './utils/contract'
import { balanceLoaded, removePendingTransaction } from './utils/testUtils' import { balanceLoaded, removePendingTransaction } from './utils/testUtils'
import sleep from './utils/sleep' import sleep from './utils/sleep'
@ -113,19 +116,23 @@ class HomeStore {
statistics = { statistics = {
deposits: 0, deposits: 0,
depositsValue: BN(0), depositsValue: BN(0),
withdraws: 0, withdrawals: 0,
withdrawsValue: BN(0), withdrawalsValue: BN(0),
totalBridged: BN(0), totalBridged: BN(0),
users: new Set(), users: new Set(),
finished: false finished: false
} }
@observable
feeEventsFinished = false
@observable @observable
depositFeeCollected = { depositFeeCollected = {
value: BN(0), value: BN(0),
type: '', type: '',
shouldDisplay: false, shouldDisplay: false,
finished: false finished: false,
title: ''
} }
@observable @observable
@ -133,7 +140,8 @@ class HomeStore {
value: BN(0), value: BN(0),
type: '', type: '',
shouldDisplay: false, shouldDisplay: false,
finished: false finished: false,
title: ''
} }
feeManager = { feeManager = {
@ -166,7 +174,7 @@ class HomeStore {
} }
const { HOME_ABI } = getBridgeABIs(this.rootStore.bridgeMode) const { HOME_ABI } = getBridgeABIs(this.rootStore.bridgeMode)
this.homeBridge = new this.homeWeb3.eth.Contract(HOME_ABI, this.COMMON_HOME_BRIDGE_ADDRESS) this.homeBridge = new this.homeWeb3.eth.Contract(HOME_ABI, this.COMMON_HOME_BRIDGE_ADDRESS)
if (this.rootStore.bridgeMode === BRIDGE_MODES.ERC_TO_ERC) { if (isErcToErcMode(this.rootStore.bridgeMode)) {
await this.getTokenInfo() await this.getTokenInfo()
} else if (this.rootStore.bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) { } else if (this.rootStore.bridgeMode === BRIDGE_MODES.ERC_TO_NATIVE) {
await this.getBlockRewardContract() await this.getBlockRewardContract()
@ -180,6 +188,7 @@ class HomeStore {
this.getFee() this.getFee()
this.getValidators() this.getValidators()
this.getStatistics() this.getStatistics()
this.getFeeEvents()
this.calculateCollectedFees() this.calculateCollectedFees()
setInterval(() => { setInterval(() => {
this.getEvents() this.getEvents()
@ -194,8 +203,6 @@ class HomeStore {
try { try {
this.tokenAddress = await getErc677TokenAddress(this.homeBridge) this.tokenAddress = await getErc677TokenAddress(this.homeBridge)
this.tokenContract = new this.homeWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, this.tokenAddress) this.tokenContract = new this.homeWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, this.tokenAddress)
this.symbol = await getSymbol(this.tokenContract)
this.tokenName = await getName(this.tokenContract)
const alternativeContract = new this.homeWeb3.eth.Contract(ERC20_BYTES32_ABI, this.tokenAddress) const alternativeContract = new this.homeWeb3.eth.Contract(ERC20_BYTES32_ABI, this.tokenAddress)
try { try {
this.symbol = await getSymbol(this.tokenContract) this.symbol = await getSymbol(this.tokenContract)
@ -243,7 +250,7 @@ class HomeStore {
@action @action
async getBalance() { async getBalance() {
try { try {
if (this.rootStore.bridgeMode === BRIDGE_MODES.ERC_TO_ERC) { if (isErcToErcMode(this.rootStore.bridgeMode)) {
this.balance = await getTotalSupply(this.tokenContract) this.balance = await getTotalSupply(this.tokenContract)
this.web3Store.getWeb3Promise.then(async () => { this.web3Store.getWeb3Promise.then(async () => {
this.userBalance = await getBalanceOf(this.tokenContract, this.web3Store.defaultAccount.address) this.userBalance = await getBalanceOf(this.tokenContract, this.web3Store.defaultAccount.address)
@ -264,18 +271,28 @@ class HomeStore {
@action @action
async getFee() { async getFee() {
const feeManager = await getFeeManager(this.homeBridge) if (!isMediatorMode(this.rootStore.bridgeMode)) {
if (feeManager !== ZERO_ADDRESS) { const feeManager = await getFeeManager(this.homeBridge)
const feeManagerModeHash = await getFeeManagerMode(this.homeBridge) if (feeManager !== ZERO_ADDRESS) {
this.feeManager.feeManagerMode = decodeFeeManagerMode(feeManagerModeHash) const feeManagerModeHash = await getFeeManagerMode(this.homeBridge)
this.feeManager.feeManagerMode = decodeFeeManagerMode(feeManagerModeHash)
if (this.feeManager.feeManagerMode === FEE_MANAGER_MODE.BOTH_DIRECTIONS) { if (this.feeManager.feeManagerMode === FEE_MANAGER_MODE.BOTH_DIRECTIONS) {
this.feeManager.homeFee = await getHomeFee(this.homeBridge) this.feeManager.homeFee = await getHomeFee(this.homeBridge)
this.feeManager.foreignFee = await getForeignFee(this.homeBridge) this.feeManager.foreignFee = await getForeignFee(this.homeBridge)
} else {
this.feeManager.homeFee = new BN(0)
this.feeManager.foreignFee = await getForeignFee(this.homeBridge)
}
} else { } else {
this.feeManager.feeManagerMode = FEE_MANAGER_MODE.UNDEFINED
this.feeManager.homeFee = new BN(0) this.feeManager.homeFee = new BN(0)
this.feeManager.foreignFee = await getForeignFee(this.homeBridge) this.feeManager.foreignFee = new BN(0)
} }
} else if (this.rootStore.bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
this.feeManager.feeManagerMode = FEE_MANAGER_MODE.ONE_DIRECTION_STAKE
this.feeManager.homeFee = await getFee(this.homeBridge)
this.feeManager.foreignFee = new BN(0)
} else { } else {
this.feeManager.feeManagerMode = FEE_MANAGER_MODE.UNDEFINED this.feeManager.feeManagerMode = FEE_MANAGER_MODE.UNDEFINED
this.feeManager.homeFee = new BN(0) this.feeManager.homeFee = new BN(0)
@ -285,64 +302,68 @@ class HomeStore {
@action @action
async getEvents(fromBlock, toBlock) { async getEvents(fromBlock, toBlock) {
try { fromBlock = fromBlock || this.filteredBlockNumber || this.latestBlockNumber - 50
fromBlock = fromBlock || this.filteredBlockNumber || this.latestBlockNumber - 50 toBlock = toBlock || this.filteredBlockNumber || 'latest'
toBlock = toBlock || this.filteredBlockNumber || 'latest'
if (fromBlock < 0) { if (fromBlock < 0) {
fromBlock = 0 fromBlock = 0
} }
let events = await getPastEvents(this.homeBridge, fromBlock, toBlock).catch(e => { if (!isMediatorMode(this.rootStore.bridgeMode)) {
console.error("Couldn't get events", e) try {
return [] let events = await getPastEvents(this.homeBridge, fromBlock, toBlock).catch(e => {
}) console.error("Couldn't get events", e)
return []
let homeEvents = []
await asyncForEach(events, async event => {
if (event.event === 'SignedForUserRequest' || event.event === 'CollectedSignatures') {
event.signedTxHash = await this.getSignedTx(event.returnValues.messageHash)
}
homeEvents.push(event)
})
if (!this.filter) {
this.events = homeEvents
}
if (this.waitingForConfirmation.size) {
const confirmationEvents = homeEvents.filter(
event =>
event.event === 'AffirmationCompleted' &&
this.waitingForConfirmation.has(event.returnValues.transactionHash)
)
confirmationEvents.forEach(event => {
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitHome
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.HOME_TRANSFER_SUCCESS
)
}, 2000)
this.waitingForConfirmation.delete(event.returnValues.transactionHash)
}) })
if (confirmationEvents.length) { let homeEvents = []
removePendingTransaction() await asyncForEach(events, async event => {
} if (event.event === 'SignedForUserRequest' || event.event === 'CollectedSignatures') {
} event.signedTxHash = await this.getSignedTx(event.returnValues.messageHash)
}
homeEvents.push(event)
})
return homeEvents if (!this.filter) {
} catch (e) { this.events = homeEvents
this.alertStore.pushError( }
`Cannot establish connection to Home Network.\n
if (this.waitingForConfirmation.size) {
const confirmationEvents = homeEvents.filter(
event =>
event.event === 'AffirmationCompleted' &&
this.waitingForConfirmation.has(event.returnValues.transactionHash)
)
confirmationEvents.forEach(event => {
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitHome
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.HOME_TRANSFER_SUCCESS
)
}, 2000)
this.waitingForConfirmation.delete(event.returnValues.transactionHash)
})
if (confirmationEvents.length) {
removePendingTransaction()
}
}
return homeEvents
} catch (e) {
this.alertStore.pushError(
`Cannot establish connection to Home Network.\n
Please make sure you have set it up in env variables`, Please make sure you have set it up in env variables`,
this.alertStore.HOME_CONNECTION_ERROR this.alertStore.HOME_CONNECTION_ERROR
) )
}
} else {
this.detectMediatorTransferFinished(fromBlock, toBlock)
} }
} }
@ -408,30 +429,40 @@ class HomeStore {
@action @action
async getValidators() { async getValidators() {
try { if (!isMediatorMode(this.rootStore.bridgeMode)) {
const homeValidatorsAddress = await getValidatorContract(this.homeBridge) try {
this.homeBridgeValidators = new this.homeWeb3.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress) const homeValidatorsAddress = await getValidatorContract(this.homeBridge)
this.homeBridgeValidators = new this.homeWeb3.eth.Contract(BRIDGE_VALIDATORS_ABI, homeValidatorsAddress)
this.requiredSignatures = await getRequiredSignatures(this.homeBridgeValidators) this.requiredSignatures = await getRequiredSignatures(this.homeBridgeValidators)
this.validatorsCount = await getValidatorCount(this.homeBridgeValidators) this.validatorsCount = await getValidatorCount(this.homeBridgeValidators)
this.validators = await getValidatorList(homeValidatorsAddress, this.homeWeb3.eth) this.validators = await getValidatorList(homeValidatorsAddress, this.homeWeb3.eth)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
}
} }
} }
async getStatistics() { async getStatistics() {
try { try {
const deployedAtBlock = await getDeployedAtBlock(this.homeBridge) if (!isMediatorMode(this.rootStore.bridgeMode)) {
const { HOME_ABI } = getBridgeABIs(this.rootStore.bridgeMode) const deployedAtBlock = await getDeployedAtBlock(this.homeBridge)
const abi = [...HOME_V1_ABI, ...HOME_ABI] const { HOME_ABI } = getBridgeABIs(this.rootStore.bridgeMode)
const contract = new this.homeWeb3.eth.Contract(abi, this.COMMON_HOME_BRIDGE_ADDRESS) const abi = [...HOME_V1_ABI, ...HOME_ABI]
const events = await getPastEvents(contract, deployedAtBlock, 'latest') const contract = new this.homeWeb3.eth.Contract(abi, this.COMMON_HOME_BRIDGE_ADDRESS)
processLargeArrayAsync(events, this.processEvent, () => { const events = await getPastEvents(contract, deployedAtBlock, 'latest')
this.statistics.finished = true processLargeArrayAsync(events, this.processEvent, () => {
this.statistics.totalBridged = this.statistics.depositsValue.plus(this.statistics.withdrawsValue) this.statistics.finished = true
}) this.statistics.totalBridged = this.statistics.totalBridged.plus(this.statistics.depositsValue)
})
} else {
const events = await getPastEvents(this.homeBridge, 0, 'latest', 'TokensBridged')
processLargeArrayAsync(events, this.processMediatorEvent, () => {
this.statistics.finished = true
this.statistics.totalBridged = this.statistics.depositsValue.plus(this.statistics.withdrawalsValue)
})
}
} catch (e) { } catch (e) {
console.error(e) console.error(e)
this.getStatistics() this.getStatistics()
@ -448,8 +479,8 @@ class HomeStore {
BN(fromDecimals(event.returnValues.value, this.tokenDecimals)) BN(fromDecimals(event.returnValues.value, this.tokenDecimals))
) )
} else if (event.event === 'AffirmationCompleted' || event.event === 'Withdraw') { } else if (event.event === 'AffirmationCompleted' || event.event === 'Withdraw') {
this.statistics.withdraws++ this.statistics.withdrawals++
this.statistics.withdrawsValue = this.statistics.withdrawsValue.plus( this.statistics.withdrawalsValue = this.statistics.withdrawalsValue.plus(
BN(fromDecimals(event.returnValues.value, this.tokenDecimals)) BN(fromDecimals(event.returnValues.value, this.tokenDecimals))
) )
} else if (event.event === 'FeeDistributedFromSignatures') { } else if (event.event === 'FeeDistributedFromSignatures') {
@ -463,9 +494,49 @@ class HomeStore {
} }
} }
processMediatorEvent = event => {
if (event.returnValues && event.returnValues.recipient) {
this.statistics.users.add(event.returnValues.recipient)
}
this.statistics.deposits++
this.statistics.depositsValue = this.statistics.depositsValue.plus(
BN(fromDecimals(event.returnValues.value, this.tokenDecimals))
)
}
async getFeeEvents() {
try {
if (this.rootStore.bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
const blockRewardAddress = await getBlockRewardContract(this.homeBridge)
const blockRewardContract = new this.homeWeb3.eth.Contract(BLOCK_REWARD_ABI, blockRewardAddress)
const events = await getPastEvents(blockRewardContract, 0, 'latest', 'BridgeTokenRewardAdded', {
filter: {
bridge: this.COMMON_HOME_BRIDGE_ADDRESS
}
})
processLargeArrayAsync(events, this.processFeeEvents, () => {
this.feeEventsFinished = true
})
} else {
this.feeEventsFinished = true
}
} catch (e) {
console.error(e)
this.getFeeEvents()
}
}
processFeeEvents = event => {
this.feeManager.totalFeeDistributedFromSignatures = this.feeManager.totalFeeDistributedFromSignatures.plus(
BN(fromDecimals(event.returnValues.amount, this.tokenDecimals))
)
}
calculateCollectedFees() { calculateCollectedFees() {
if ( if (
!this.statistics.finished || !this.statistics.finished ||
!this.feeEventsFinished ||
!this.rootStore.foreignStore.feeEventsFinished || !this.rootStore.foreignStore.feeEventsFinished ||
!this.feeManager.feeManagerMode || !this.feeManager.feeManagerMode ||
!this.rootStore.foreignStore.feeManager.feeManagerMode !this.rootStore.foreignStore.feeManager.feeManagerMode
@ -493,6 +564,10 @@ class HomeStore {
? this.feeManager.totalFeeDistributedFromAffirmation ? this.feeManager.totalFeeDistributedFromAffirmation
: this.rootStore.foreignStore.feeManager.totalFeeDistributedFromAffirmation : this.rootStore.foreignStore.feeManager.totalFeeDistributedFromAffirmation
if (this.rootStore.bridgeMode === BRIDGE_MODES.STAKE_AMB_ERC_TO_ERC) {
this.depositFeeCollected.title = 'Withdrawal Fees'
}
this.depositFeeCollected.finished = true this.depositFeeCollected.finished = true
this.withdrawFeeCollected.finished = true this.withdrawFeeCollected.finished = true
} }
@ -502,9 +577,7 @@ class HomeStore {
} }
getDisplayedBalance() { getDisplayedBalance() {
return this.rootStore.bridgeMode === BRIDGE_MODES.ERC_TO_ERC return isErcToErcMode(this.rootStore.bridgeMode) ? this.userBalance : this.web3Store.defaultAccount.homeBalance
? this.userBalance
: this.web3Store.defaultAccount.homeBalance
} }
async getBlockRewardContract() { async getBlockRewardContract() {
@ -527,6 +600,33 @@ class HomeStore {
return sleep(5000).then(() => this.waitUntilProcessed(txHash, value)) return sleep(5000).then(() => this.waitUntilProcessed(txHash, value))
} }
} }
async detectMediatorTransferFinished(fromBlock, toBlock) {
if (this.waitingForConfirmation.size > 0) {
try {
const events = await getPastEvents(this.homeBridge, fromBlock, toBlock, 'TokensBridged')
const confirmationEvents = events.filter(event => this.waitingForConfirmation.has(event.returnValues.messageId))
if (confirmationEvents.length > 0) {
const event = events[0]
this.alertStore.setLoadingStepIndex(3)
const urlExplorer = this.getExplorerTxUrl(event.transactionHash)
const unitReceived = getUnit(this.rootStore.bridgeMode).unitHome
this.waitingForConfirmation.delete(event.returnValues.messageId)
removePendingTransaction()
setTimeout(() => {
this.alertStore.pushSuccess(
`${unitReceived} received on ${this.networkName} on Tx
<a href='${urlExplorer}' target='blank' style="overflow-wrap: break-word;word-wrap: break-word;">
${event.transactionHash}</a>`,
this.alertStore.HOME_TRANSFER_SUCCESS
)
}, 2000)
}
} catch (e) {
console.log(e)
}
}
}
} }
export default HomeStore export default HomeStore

@ -27,8 +27,8 @@ export const getCurrentLimit = async (contract, decimals) => {
} }
} }
export const getPastEvents = (contract, fromBlock, toBlock, event = 'allEvents') => export const getPastEvents = (contract, fromBlock, toBlock, event = 'allEvents', options = {}) =>
commonGetPastEvents(contract, { fromBlock, toBlock, event }) commonGetPastEvents(contract, { fromBlock, toBlock, event, options })
export const getErc677TokenAddress = contract => contract.methods.erc677token().call() export const getErc677TokenAddress = contract => contract.methods.erc677token().call()
@ -86,6 +86,15 @@ export const getForeignFee = async contract => {
return new BN(fromWei(feeInWei.toString())) return new BN(fromWei(feeInWei.toString()))
} }
export const getFee = async contract => {
try {
const feeInWei = await contract.methods.getFee().call()
return new BN(fromWei(feeInWei.toString()))
} catch (e) {
return new BN(0)
}
}
export const getBlockRewardContract = contract => contract.methods.blockRewardContract().call() export const getBlockRewardContract = contract => contract.methods.blockRewardContract().call()
export const getValidatorContract = contract => contract.methods.validatorContract().call() export const getValidatorContract = contract => contract.methods.validatorContract().call()

@ -65,6 +65,15 @@ export const getRewardableData = (homeFeeManager, foreignFeeManager) => {
displayDeposit: true, displayDeposit: true,
displayWithdraw: false displayWithdraw: false
} }
} else if (homeFeeManager.feeManagerMode === FEE_MANAGER_MODE.ONE_DIRECTION_STAKE) {
return {
homeFee: homeFeeManager.homeFee,
foreignFee: new BN(0),
depositSymbol: 'home',
withdrawSymbol: '',
displayDeposit: true,
displayWithdraw: false
}
} else { } else {
return { return {
homeFee: new BN(0), homeFee: new BN(0),