Add bw plugin assets (#387)

This commit is contained in:
Kirill Fedoseev 2020-07-07 21:26:14 +07:00 committed by GitHub
parent 861c755b09
commit 2edd8f2783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 174 additions and 48 deletions

@ -2,19 +2,37 @@ import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import BurnerCore from '@burner-wallet/core' import BurnerCore from '@burner-wallet/core'
import { InjectedSigner, LocalSigner } from '@burner-wallet/core/signers' import { InjectedSigner, LocalSigner } from '@burner-wallet/core/signers'
import { InfuraGateway, InjectedGateway } from '@burner-wallet/core/gateways' import { XDaiBridge } from '@burner-wallet/exchange'
import { xdai } from '@burner-wallet/assets'
import { InfuraGateway, InjectedGateway, XDaiGateway } from '@burner-wallet/core/gateways'
import Exchange from '@burner-wallet/exchange' import Exchange from '@burner-wallet/exchange'
import ModernUI from '@burner-wallet/modern-ui' import ModernUI from '@burner-wallet/modern-ui'
import { Etc, Wetc, TokenBridgeGateway, WETCBridge } from '@poanet/tokenbridge-bw-exchange' import {
Etc,
Wetc,
Dai,
qDai,
MOON,
xMOON,
TokenBridgeGateway,
WETCBridge,
QDAIBridge,
MOONBridge
} from '@poanet/tokenbridge-bw-exchange'
import MetamaskPlugin from '@burner-wallet/metamask-plugin' import MetamaskPlugin from '@burner-wallet/metamask-plugin'
const core = new BurnerCore({ const core = new BurnerCore({
signers: [new InjectedSigner(), new LocalSigner()], signers: [new InjectedSigner(), new LocalSigner()],
gateways: [new InjectedGateway(), new InfuraGateway(process.env.REACT_APP_INFURA_KEY), new TokenBridgeGateway()], gateways: [
assets: [Wetc, Etc] new InjectedGateway(),
new XDaiGateway(),
new InfuraGateway(process.env.REACT_APP_INFURA_KEY),
new TokenBridgeGateway()
],
assets: [xdai, Wetc, Etc, Dai, qDai, MOON, xMOON]
}) })
const exchange = new Exchange([new WETCBridge()]) const exchange = new Exchange([new XDaiBridge(), new WETCBridge(), new QDAIBridge(), new MOONBridge()])
const BurnerWallet = () => <ModernUI title="Staging Wallet" core={core} plugins={[exchange, new MetamaskPlugin()]} /> const BurnerWallet = () => <ModernUI title="Staging Wallet" core={core} plugins={[exchange, new MetamaskPlugin()]} />

@ -93,8 +93,7 @@ if (process.env.REACT_APP_MODE === 'AMB_NATIVE_TO_ERC677') {
network: process.env.REACT_APP_FOREIGN_NETWORK, network: process.env.REACT_APP_FOREIGN_NETWORK,
// @ts-ignore // @ts-ignore
address: process.env.REACT_APP_FOREIGN_TOKEN_ADDRESS, address: process.env.REACT_APP_FOREIGN_TOKEN_ADDRESS,
// @ts-ignore bridgeModes: ['erc-to-native-amb']
bridgeAddress: process.env.REACT_APP_FOREIGN_MEDIATOR_ADDRESS
}) })
testBridge = new MediatorErcToNative({ testBridge = new MediatorErcToNative({

@ -0,0 +1,12 @@
import { Mediator } from '../burner-wallet'
export default class MOONBridge extends Mediator {
constructor() {
super({
assetA: 'xmoon',
assetABridge: '0x1E0507046130c31DEb20EC2f870ad070Ff266079',
assetB: 'moon',
assetBBridge: '0xFEaB457D95D9990b7eb6c943c839258245541754'
})
}
}

@ -0,0 +1,12 @@
import { MediatorErcToNative } from '../burner-wallet'
export default class QDAIBridge extends MediatorErcToNative {
constructor() {
super({
assetA: 'qdai',
assetABridge: '0xFEaB457D95D9990b7eb6c943c839258245541754',
assetB: 'dai',
assetBBridge: '0xf6edFA16926f30b0520099028A145F4E06FD54ed'
})
}
}

@ -1,6 +1,6 @@
import { Mediator } from '../burner-wallet' import { Mediator } from '../burner-wallet'
import { HOME_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI } from '../utils' import { HOME_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI } from '../utils'
import { waitForEvent, isBridgeContract, constants } from '../utils' import { waitForEvent, isVanillaBridgeContract, constants } from '../utils'
import { ValueTypes } from '@burner-wallet/exchange' import { ValueTypes } from '@burner-wallet/exchange'
import { toBN, fromWei } from 'web3-utils' import { toBN, fromWei } from 'web3-utils'
@ -19,7 +19,7 @@ export default class WETCBridge extends Mediator {
.getAsset(this.assetA) .getAsset(this.assetA)
.getWeb3() .getWeb3()
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge) const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge)
const listenToBridgeEvent = await isBridgeContract(contract) const listenToBridgeEvent = await isVanillaBridgeContract(contract)
if (listenToBridgeEvent) { if (listenToBridgeEvent) {
await waitForEvent(web3, contract, 'AffirmationCompleted', this.processBridgeEvents(sendResult.txHash)) await waitForEvent(web3, contract, 'AffirmationCompleted', this.processBridgeEvents(sendResult.txHash))
} else { } else {
@ -32,7 +32,7 @@ export default class WETCBridge extends Mediator {
.getAsset(this.assetB) .getAsset(this.assetB)
.getWeb3() .getWeb3()
const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge) const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge)
const listenToBridgeEvent = await isBridgeContract(contract) const listenToBridgeEvent = await isVanillaBridgeContract(contract)
if (listenToBridgeEvent) { if (listenToBridgeEvent) {
await waitForEvent(web3, contract, 'RelayedMessage', this.processBridgeEvents(sendResult.txHash)) await waitForEvent(web3, contract, 'RelayedMessage', this.processBridgeEvents(sendResult.txHash))
} else { } else {
@ -53,7 +53,7 @@ export default class WETCBridge extends Mediator {
.getWeb3() .getWeb3()
const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge) const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge)
const useBridgeContract = await isBridgeContract(contract) const useBridgeContract = await isVanillaBridgeContract(contract)
if (useBridgeContract) { if (useBridgeContract) {
const fee = toBN(await contract.methods.getHomeFee().call()) const fee = toBN(await contract.methods.getHomeFee().call())
@ -79,7 +79,7 @@ export default class WETCBridge extends Mediator {
.getWeb3() .getWeb3()
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge) const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge)
const useBridgeContract = await isBridgeContract(contract) const useBridgeContract = await isVanillaBridgeContract(contract)
if (useBridgeContract) { if (useBridgeContract) {
const fee = toBN(await contract.methods.getForeignFee().call()) const fee = toBN(await contract.methods.getForeignFee().call())

@ -0,0 +1,3 @@
export { default as WETCBridge } from './WETCBridge'
export { default as QDAIBridge } from './QDAIBridge'
export { default as MOONBridge } from './MOONBridge'

@ -1,42 +1,55 @@
import { ERC20Asset } from '@burner-wallet/assets' import { ERC20Asset } from '@burner-wallet/assets'
import { MEDIATOR_ABI, constants } from '../../utils' import { AssetConstructor } from '@burner-wallet/assets/Asset'
import { toBN } from 'web3-utils' import { MEDIATOR_ABI, constants, isBridgeContract } from '../../utils'
import { toBN, soliditySha3 } from 'web3-utils'
interface BridgeableERC20Constructor { interface BridgeableERC20Constructor extends AssetConstructor {
abi?: object abi?: object
address: string address: string
id: string bridgeModes: string[]
name: string
network: string
bridgeAddress: string
} }
export default class BridgeableERC20Asset extends ERC20Asset { export default class BridgeableERC20Asset extends ERC20Asset {
protected bridgeAddress: string private _bridgeModes
private _bridge private _bridges: { [addr: string]: object | false }
constructor({ bridgeAddress, ...params }: BridgeableERC20Constructor) { public set bridgeModes(bridgeModes: string[]) {
super({ ...params }) this._bridgeModes = bridgeModes.map(s => soliditySha3(s)!.slice(0, 10))
this.bridgeAddress = bridgeAddress.toLowerCase()
} }
getBridgeContract() { public get bridgeModes() {
if (!this._bridge) { return this._bridgeModes
}
constructor({
bridgeModes = ['erc-to-native-core', 'erc-to-native-amb', 'erc-to-erc-core', 'erc-to-erc-amb'],
...params
}: BridgeableERC20Constructor) {
super(params)
this._bridges = {}
this.bridgeModes = bridgeModes
}
async getBridgeContract(addr: string) {
if (typeof this._bridges[addr] === 'undefined') {
const Contract = this.getWeb3().eth.Contract const Contract = this.getWeb3().eth.Contract
this._bridge = new Contract(MEDIATOR_ABI, this.bridgeAddress) const bridge = new Contract(MEDIATOR_ABI, addr)
if (await isBridgeContract(bridge, this.bridgeModes)) {
return (this._bridges[addr] = bridge)
} }
return this._bridge return (this._bridges[addr] = false)
}
return this._bridges[addr]
} }
async _send({ from, to, value }) { async _send({ from, to, value }) {
if (to.toLowerCase() === this.bridgeAddress) { const bridge = await this.getBridgeContract(to)
if (bridge) {
const allowance = await this.allowance(from, to) const allowance = await this.allowance(from, to)
if (toBN(allowance).lt(toBN(value))) { if (toBN(allowance).lt(toBN(value))) {
await this.approve(from, to, value) await this.approve(from, to, value)
} }
const receipt = await this.getBridgeContract() const receipt = await bridge.methods.relayTokens(from, value).send({ from })
.methods.relayTokens(from, value)
.send({ from })
const transferLog = Object.values(receipt.events as object).find( const transferLog = Object.values(receipt.events as object).find(
e => e.raw.topics[0] === constants.TRANSFER_TOPIC e => e.raw.topics[0] === constants.TRANSFER_TOPIC
) )

@ -0,0 +1,11 @@
import BridgeableERC20Asset from './BridgeableERC20Asset'
export default new BridgeableERC20Asset({
id: 'dai',
name: 'Dai',
network: '1',
address: '0x6b175474e89094c44da98b954eedeac495271d0f',
usdPrice: 1,
icon: 'https://static.burnerfactory.com/icons/mcd.svg',
bridgeModes: ['erc-to-native-amb']
})

@ -1,14 +1,12 @@
import { ERC20Asset } from '@burner-wallet/assets' import { ERC20Asset } from '@burner-wallet/assets'
import { AssetConstructor } from '@burner-wallet/assets/Asset'
import { ERC677_ABI, constants } from '../../utils' import { ERC677_ABI, constants } from '../../utils'
const BLOCK_LOOKBACK = 250 const BLOCK_LOOKBACK = 250
interface ERC677Constructor { interface ERC677Constructor extends AssetConstructor {
abi?: object abi?: object
address: string address: string
id: string
name: string
network: string
} }
export default class ERC677Asset extends ERC20Asset { export default class ERC677Asset extends ERC20Asset {

@ -1,5 +1,5 @@
import NativeMediatorAsset from './NativeMediatorAsset' import NativeMediatorAsset from './NativeMediatorAsset'
import { isBridgeContract, HOME_NATIVE_TO_ERC_ABI } from '../../utils' import { isVanillaBridgeContract, HOME_NATIVE_TO_ERC_ABI } from '../../utils'
class EtcNativeAsset extends NativeMediatorAsset { class EtcNativeAsset extends NativeMediatorAsset {
constructor(props) { constructor(props) {
@ -9,7 +9,7 @@ class EtcNativeAsset extends NativeMediatorAsset {
async scanMediatorEvents(address, fromBlock, toBlock) { async scanMediatorEvents(address, fromBlock, toBlock) {
const web3 = this.getWeb3() const web3 = this.getWeb3()
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.mediatorAddress) const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.mediatorAddress)
const listenToBridgeEvent = await isBridgeContract(contract) const listenToBridgeEvent = await isVanillaBridgeContract(contract)
if (listenToBridgeEvent && this.mediatorAddress != '') { if (listenToBridgeEvent && this.mediatorAddress != '') {
const events = await contract.getPastEvents('AffirmationCompleted', { const events = await contract.getPastEvents('AffirmationCompleted', {
fromBlock, fromBlock,

@ -0,0 +1,10 @@
import BridgeableERC20Asset from './BridgeableERC20Asset'
export default new BridgeableERC20Asset({
id: 'moon',
name: 'MOON',
network: '4',
address: '0xDF82c9014F127243CE1305DFE54151647d74B27A',
icon: 'https://blockscout.com/poa/xdai/images/icons/moon.png',
bridgeModes: ['erc-to-erc-amb']
})

@ -1,12 +1,10 @@
import { NativeAsset } from '@burner-wallet/assets' import { NativeAsset } from '@burner-wallet/assets'
import { Contract, EventData } from 'web3-eth-contract' import { Contract, EventData } from 'web3-eth-contract'
import { MEDIATOR_ABI } from '../../utils' import { MEDIATOR_ABI } from '../../utils'
import { AssetConstructor } from '@burner-wallet/assets/Asset'
interface NativeMediatorConstructor { interface NativeMediatorConstructor extends AssetConstructor {
mediatorAddress?: string mediatorAddress?: string
id: string
name: string
network: string
} }
export default class NativeMediatorAsset extends NativeAsset { export default class NativeMediatorAsset extends NativeAsset {

@ -0,0 +1,9 @@
import NativeMediatorAsset from './NativeMediatorAsset'
export default new NativeMediatorAsset({
id: 'qdai',
name: 'qDai',
network: '181',
usdPrice: 1,
mediatorAddress: '0xFEaB457D95D9990b7eb6c943c839258245541754'
})

@ -0,0 +1,9 @@
import { default as ERC677Asset } from './ERC677Asset'
export default new ERC677Asset({
id: 'xmoon',
name: 'xMOON',
network: '100',
address: '0x1e16aa4Df73d29C029d94CeDa3e3114EC191E25A',
icon: 'https://blockscout.com/poa/xdai/images/icons/moon.png'
})

@ -9,7 +9,8 @@ export default class TokenBridgeGateway extends Gateway {
this.providerStrings = { this.providerStrings = {
'61': `https://www.ethercluster.com/etc`, '61': `https://www.ethercluster.com/etc`,
'77': 'https://sokol.poa.network', '77': 'https://sokol.poa.network',
'99': 'https://core.poa.network' '99': 'https://core.poa.network',
'181': 'https://quorum-rpc.tokenbridge.net'
} }
this.providers = {} this.providers = {}
} }
@ -19,7 +20,7 @@ export default class TokenBridgeGateway extends Gateway {
} }
getNetworks() { getNetworks() {
return ['61', '77', '99'] return ['61', '77', '99', '181']
} }
_provider(network) { _provider(network) {

@ -1,6 +1,10 @@
export { default as sPOA } from './assets/sPOA' export { default as sPOA } from './assets/sPOA'
export { default as Etc } from './assets/Etc' export { default as Etc } from './assets/Etc'
export { default as Wetc } from './assets/Wetc' export { default as Wetc } from './assets/Wetc'
export { default as Dai } from './assets/Dai'
export { default as qDai } from './assets/qDai'
export { default as MOON } from './assets/MOON'
export { default as xMOON } from './assets/xMOON'
export { default as ERC677Asset } from './assets/ERC677Asset' export { default as ERC677Asset } from './assets/ERC677Asset'
export { default as BridgeableERC20Asset } from './assets/BridgeableERC20Asset' export { default as BridgeableERC20Asset } from './assets/BridgeableERC20Asset'
export { default as NativeMediatorAsset } from './assets/NativeMediatorAsset' export { default as NativeMediatorAsset } from './assets/NativeMediatorAsset'

@ -5,8 +5,12 @@ export {
sPOA, sPOA,
Etc, Etc,
Wetc, Wetc,
qDai,
Dai,
MOON,
xMOON,
TokenBridgeGateway, TokenBridgeGateway,
Mediator, Mediator,
MediatorErcToNative MediatorErcToNative
} from './burner-wallet' } from './burner-wallet'
export { WETCBridge } from './wetc-bridge' export { WETCBridge, QDAIBridge, MOONBridge } from './bridges'

@ -52,5 +52,19 @@ export default [
payable: false, payable: false,
stateMutability: 'nonpayable', stateMutability: 'nonpayable',
type: 'function' type: 'function'
},
{
constant: true,
inputs: [],
name: 'getBridgeMode',
outputs: [
{
name: '',
type: 'bytes4'
}
],
payable: false,
stateMutability: 'pure',
type: 'function'
} }
] ]

@ -1,4 +1,4 @@
export { constants, wait, waitForEvent, isBridgeContract } from './utils' export { constants, wait, waitForEvent, isVanillaBridgeContract, isBridgeContract } from './utils'
export { export {
ERC677_ABI, ERC677_ABI,
FOREIGN_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI,

@ -34,7 +34,7 @@ export const waitForEvent = async (web3, contract: Contract, event: string, call
} }
} }
export const isBridgeContract = async (contract: Contract): Promise<boolean> => { export const isVanillaBridgeContract = async (contract: Contract): Promise<boolean> => {
try { try {
await contract.methods.deployedAtBlock().call() await contract.methods.deployedAtBlock().call()
return true return true
@ -42,3 +42,15 @@ export const isBridgeContract = async (contract: Contract): Promise<boolean> =>
return false return false
} }
} }
export const isBridgeContract = async (contract: Contract, allowedModes?: string[]): Promise<boolean> => {
try {
const mode = await contract.methods.getBridgeMode().call()
if (typeof allowedModes === 'undefined') {
return true
}
return allowedModes.includes(mode)
} catch (e) {
return false
}
}

@ -1 +0,0 @@
export { default as WETCBridge } from './WETCBridge'