Merge pull request #289 from poanetwork/rsk-testnet-support

RSK testnet support
This commit is contained in:
Victor Baranov 2019-06-11 22:35:42 +03:00 committed by GitHub
commit 3b81f2855e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 204 additions and 58 deletions

View File

@ -8,6 +8,7 @@ const KOVAN = 'kovan'
const GOERLI_TESTNET = 'goerli_testnet'
const CLASSIC = 'classic'
const RSK = 'rsk'
const RSK_TESTNET = 'rsk_testnet'
const LOCALHOST = 'localhost'
const POA_CODE = 99
@ -20,6 +21,7 @@ const KOVAN_CODE = 42
const GOERLI_TESTNET_CODE = 5
const CLASSIC_CODE = 61
const RSK_CODE = 30
const RSK_TESTNET_CODE = 31
const POA_DISPLAY_NAME = 'POA Core'
const DAI_DISPLAY_NAME = 'xDai Chain'
@ -31,6 +33,7 @@ const KOVAN_DISPLAY_NAME = 'Kovan'
const GOERLI_TESTNET_DISPLAY_NAME = 'Görli Testnet'
const CLASSIC_DISPLAY_NAME = 'Ethereum Classic'
const RSK_DISPLAY_NAME = 'RSK Mainnet'
const RSK_TESTNET_DISPLAY_NAME = 'RSK Testnet'
const DROPDOWN_POA_DISPLAY_NAME = POA_DISPLAY_NAME
const DROPDOWN_DAI_DISPLAY_NAME = DAI_DISPLAY_NAME
@ -42,6 +45,7 @@ const DROPDOWN_KOVAN_DISPLAY_NAME = 'Kovan Test Net'
const DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME = 'Görli Test Net'
const DROPDOWN_CLASSIC_DISPLAY_NAME = 'Ethereum Classic'
const DROPDOWN_RSK_DISPLAY_NAME = 'RSK Main Net'
const DROPDOWN_RSK_TESTNET_DISPLAY_NAME = 'RSK Test Net'
const chainTypes = {
TEST: 1,
@ -59,6 +63,7 @@ module.exports = {
GOERLI_TESTNET,
CLASSIC,
RSK,
RSK_TESTNET,
LOCALHOST,
POA_CODE,
DAI_CODE,
@ -70,6 +75,7 @@ module.exports = {
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME,
@ -80,6 +86,7 @@ module.exports = {
GOERLI_TESTNET_DISPLAY_NAME,
CLASSIC_DISPLAY_NAME,
RSK_DISPLAY_NAME,
RSK_TESTNET_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
@ -90,5 +97,6 @@ module.exports = {
DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME,
DROPDOWN_CLASSIC_DISPLAY_NAME,
DROPDOWN_RSK_DISPLAY_NAME,
DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
chainTypes,
}

View File

@ -26,12 +26,14 @@ const {
GOERLI_TESTNET,
CLASSIC,
RSK,
RSK_TESTNET,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
} = require('./enums')
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET]
@ -130,7 +132,8 @@ module.exports = class NetworkController extends EventEmitter {
type === DAI ||
type === GOERLI_TESTNET ||
type === CLASSIC ||
type === RSK
type === RSK ||
type === RSK_TESTNET
, `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type }
this.providerConfig = providerConfig
@ -178,6 +181,8 @@ module.exports = class NetworkController extends EventEmitter {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CLASSIC_CODE)[0] })
} else if (type === RSK) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0] })
} else if (type === RSK_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0] })
} else if (type === LOCALHOST) {
this._configureLocalhostProvider()
// url-based rpc endpoints

View File

@ -9,6 +9,7 @@ const {
GOERLI_TESTNET,
CLASSIC,
RSK,
RSK_TESTNET,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
@ -19,6 +20,7 @@ const {
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME,
@ -29,6 +31,7 @@ const {
GOERLI_TESTNET_DISPLAY_NAME,
CLASSIC_DISPLAY_NAME,
RSK_DISPLAY_NAME,
RSK_TESTNET_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
@ -39,6 +42,7 @@ const {
DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME,
DROPDOWN_CLASSIC_DISPLAY_NAME,
DROPDOWN_RSK_DISPLAY_NAME,
DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
chainTypes,
} = require('./enums')
@ -67,19 +71,8 @@ const DAI_OBJ = {
networks[DAI_CODE] = DAI_OBJ
networks[DAI] = DAI_OBJ
const POA_SOKOL_OBJ = {
order: 3,
chainType: TEST,
providerName: POA_SOKOL,
networkID: POA_SOKOL_CODE,
displayName: POA_SOKOL_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_POA_SOKOL_DISPLAY_NAME,
}
networks[POA_SOKOL_CODE] = POA_SOKOL_OBJ
networks[POA_SOKOL] = POA_SOKOL_OBJ
const MAINNET_OBJ = {
order: 4,
order: 3,
chainType: PROD,
providerName: MAINNET,
networkID: MAINNET_CODE,
@ -90,7 +83,7 @@ networks[MAINNET_CODE] = MAINNET_OBJ
networks[MAINNET] = MAINNET_OBJ
const CLASSIC_OBJ = {
order: 5,
order: 4,
chainType: PROD,
providerName: CLASSIC,
networkID: CLASSIC_CODE,
@ -100,16 +93,25 @@ const CLASSIC_OBJ = {
networks[CLASSIC_CODE] = CLASSIC_OBJ
networks[CLASSIC] = CLASSIC_OBJ
const ROPSTEN_OBJ = {
order: 6,
chainType: TEST,
providerName: ROPSTEN,
networkID: ROPSTEN_CODE,
displayName: ROPSTEN_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_ROPSTEN_DISPLAY_NAME,
const RSK_OBJ = {
order: 5,
providerName: RSK,
networkID: RSK_CODE,
displayName: RSK_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_RSK_DISPLAY_NAME,
}
networks[ROPSTEN_CODE] = ROPSTEN_OBJ
networks[ROPSTEN] = ROPSTEN_OBJ
networks[RSK_CODE] = RSK_OBJ
networks[RSK] = RSK_OBJ
const GOERLI_TESTNET_OBJ = {
order: 6,
providerName: GOERLI_TESTNET,
networkID: GOERLI_TESTNET_CODE,
displayName: GOERLI_TESTNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME,
}
networks[GOERLI_TESTNET_CODE] = GOERLI_TESTNET_OBJ
networks[GOERLI_TESTNET] = GOERLI_TESTNET_OBJ
const KOVAN_OBJ = {
order: 7,
@ -122,9 +124,20 @@ const KOVAN_OBJ = {
networks[KOVAN_CODE] = KOVAN_OBJ
networks[KOVAN] = KOVAN_OBJ
const RINKEBY_OBJ = {
const POA_SOKOL_OBJ = {
order: 8,
chainType: TEST,
providerName: POA_SOKOL,
networkID: POA_SOKOL_CODE,
displayName: POA_SOKOL_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_POA_SOKOL_DISPLAY_NAME,
}
networks[POA_SOKOL_CODE] = POA_SOKOL_OBJ
networks[POA_SOKOL] = POA_SOKOL_OBJ
const RINKEBY_OBJ = {
order: 9,
chainType: TEST,
providerName: RINKEBY,
networkID: RINKEBY_CODE,
displayName: RINKEBY_DISPLAY_NAME,
@ -133,25 +146,26 @@ const RINKEBY_OBJ = {
networks[RINKEBY_CODE] = RINKEBY_OBJ
networks[RINKEBY] = RINKEBY_OBJ
const GOERLI_TESTNET_OBJ = {
order: 9,
providerName: GOERLI_TESTNET,
networkID: GOERLI_TESTNET_CODE,
displayName: GOERLI_TESTNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME,
}
networks[GOERLI_TESTNET_CODE] = GOERLI_TESTNET_OBJ
networks[GOERLI_TESTNET] = GOERLI_TESTNET_OBJ
const RSK_OBJ = {
const ROPSTEN_OBJ = {
order: 10,
providerName: RSK,
networkID: RSK_CODE,
displayName: RSK_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_RSK_DISPLAY_NAME,
chainType: TEST,
providerName: ROPSTEN,
networkID: ROPSTEN_CODE,
displayName: ROPSTEN_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_ROPSTEN_DISPLAY_NAME,
}
networks[RSK_CODE] = RSK_OBJ
networks[RSK] = RSK_OBJ
networks[ROPSTEN_CODE] = ROPSTEN_OBJ
networks[ROPSTEN] = ROPSTEN_OBJ
const RSK_TESTNET_OBJ = {
order: 11,
providerName: RSK_TESTNET,
networkID: RSK_TESTNET_CODE,
displayName: RSK_TESTNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
}
networks[RSK_TESTNET_CODE] = RSK_TESTNET_OBJ
networks[RSK_TESTNET] = RSK_TESTNET_OBJ
const getNetworkDisplayName = key => networks[key].displayName

View File

@ -15,7 +15,8 @@ const {
RINKEBY_CODE,
KOVAN_CODE,
GOERLI_TESTNET_CODE,
RSK_CODE} = require('../controllers/network/enums')
RSK_CODE,
RSK_TESTNET_CODE} = require('../controllers/network/enums')
/**
* Gives the caller a url at which the user can acquire coin, depending on the network they are in
@ -43,6 +44,7 @@ function getBuyEthUrl ({ network, amount, address, ind }) {
case RINKEBY_CODE:
case KOVAN_CODE:
case POA_SOKOL_CODE:
case RSK_TESTNET_CODE:
case GOERLI_TESTNET_CODE:
url = getFaucets(network)[ind]
break

View File

@ -1,14 +1,14 @@
import React, { Component } from 'react'
import { formatBalance, countSignificantDecimals } from '../util'
import PropTypes from 'prop-types'
import { DAI_CODE, POA_SOKOL_CODE, GOERLI_TESTNET_CODE } from '../../../app/scripts/controllers/network/enums'
import { DAI_CODE, POA_SOKOL_CODE, RSK_TESTNET_CODE, GOERLI_TESTNET_CODE } from '../../../app/scripts/controllers/network/enums'
class FiatValue extends Component {
render = () => {
const props = this.props
let { conversionRate } = props
const { currentCurrency, network } = props
const isTestnet = parseInt(network) === POA_SOKOL_CODE || parseInt(network) === GOERLI_TESTNET_CODE
const isTestnet = parseInt(network) === POA_SOKOL_CODE || parseInt(network) === RSK_TESTNET_CODE || parseInt(network) === GOERLI_TESTNET_CODE
const isDai = parseInt(network) === DAI_CODE
if (isTestnet) {
conversionRate = 0

View File

@ -25,6 +25,7 @@ const { POA_CODE,
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
} = require('../../../app/scripts/controllers/network/enums')
const mapDispatchToProps = dispatch => {
@ -86,7 +87,8 @@ TransactionListItem.prototype.render = function () {
numericNet === DAI_CODE ||
numericNet === GOERLI_TESTNET_CODE ||
numericNet === CLASSIC_CODE ||
numericNet === RSK_CODE
numericNet === RSK_CODE ||
numericNet === RSK_TESTNET_CODE
var isMsg = ('msgParams' in transaction)
var isTx = ('txParams' in transaction)

View File

@ -13,7 +13,7 @@ import PendingMsg from './components/pending-msg'
import PendingPersonalMsg from './components/pending-personal-msg'
import PendingTypedMsg from './components/pending-typed-msg'
const Loading = require('./components/loading')
const { DAI_CODE, POA_SOKOL_CODE, GOERLI_TESTNET_CODE } = require('../../app/scripts/controllers/network/enums')
const { DAI_CODE, POA_SOKOL_CODE, RSK_TESTNET_CODE, GOERLI_TESTNET_CODE } = require('../../app/scripts/controllers/network/enums')
const { getMetaMaskAccounts } = require('../../ui/app/selectors')
module.exports = connect(mapStateToProps)(ConfirmTxScreen)
@ -57,7 +57,7 @@ ConfirmTxScreen.prototype.render = function () {
unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, blockGasLimit } = props
let { conversionRate } = props
const isTestnet = parseInt(network) === POA_SOKOL_CODE || parseInt(network) === GOERLI_TESTNET_CODE
const isTestnet = parseInt(network) === POA_SOKOL_CODE || parseInt(network) === RSK_TESTNET_CODE || parseInt(network) === GOERLI_TESTNET_CODE
const isDai = parseInt(network) === DAI_CODE
if (isTestnet) {
conversionRate = 0

View File

@ -404,6 +404,7 @@ module.exports = {
RINKEBY: 'rinkeby',
GOERLI: 'goerli',
RSK: 'rsk',
RSK_TESTNET: 'rsk_testnet',
LOCALHOST: 'localhost',
CUSTOM: 'http://test.com',
},

View File

@ -117,38 +117,41 @@ class Functions {
case NETWORKS.DAI:
counter = 1
break
case NETWORKS.SOKOL:
case NETWORKS.MAINNET:
counter = 2
break
case NETWORKS.MAINNET:
case NETWORKS.CLASSIC:
counter = 3
break
case NETWORKS.CLASSIC:
case NETWORKS.RSK:
counter = 4
break
case NETWORKS.ROPSTEN:
case NETWORKS.GOERLI:
counter = 5
break
case NETWORKS.KOVAN:
counter = 6
break
case NETWORKS.RINKEBY:
case NETWORKS.SOKOL:
counter = 7
break
case NETWORKS.GOERLI:
case NETWORKS.RINKEBY:
counter = 8
break
case NETWORKS.RSK:
case NETWORKS.ROPSTEN:
counter = 9
break
case NETWORKS.LOCALHOST:
case NETWORKS.RSK_TESTNET:
counter = 10
break
case NETWORKS.CUSTOM:
case NETWORKS.LOCALHOST:
counter = 11
break
case NETWORKS.CUSTOM:
counter = 12
break
default:
counter = 10
counter = 11
}
await this.driver.executeScript("document.getElementsByClassName('dropdown-menu-item')[" + counter + '].click();')
}

View File

@ -13,6 +13,7 @@ const deleteImportedAccount = require(`${testsFolder}/delete-imported-account.sp
const signData = require(`${testsFolder}/sign-data.spec`)
const exportPrivateKey = require(`${testsFolder}/export-private-key.spec`)
const importGanacheSeedPhrase = require(`${testsFolder}/import-ganache-seed-phrase.spec`)
const RSKNetworkTests = require(`${testsFolder}/RSK-network-tests.js`)
const checkEmittedEvents = require(`${testsFolder}/check-emitted-events.spec`)
const addCustomToken = require(`${testsFolder}/add-token-custom.spec`)
const changePassword = require(`${testsFolder}/change-password.spec`)
@ -115,6 +116,10 @@ describe('Metamask popup page', async function () {
await importGanacheSeedPhrase(f, account2, password)
})
describe('RSK network tests', async () => {
await RSKNetworkTests(f, account1)
})
describe('Check the filter of emitted events', async () => {
await checkEmittedEvents(f, account1, account2)
})

View File

@ -0,0 +1,90 @@
const assert = require('assert')
const { screens, elements, NETWORKS } = require('../elements')
const RSKNetworkTests = async (f, account1) => {
it('connects to RSK mainnet', async function () {
await f.setProvider(NETWORKS.RSK)
await f.delay(2000)
})
it('connects to RSK testnet', async function () {
await f.setProvider(NETWORKS.RSK_TESTNET)
await f.delay(2000)
})
it('checks zero exchange rate for RSK testnet', async function () {
const balanceField = await f.waitUntilShowUp(screens.main.balance)
const balanceUSDField = await f.waitUntilShowUp(screens.main.balanceUSD)
await f.delay(2000)
const balance = await balanceField.getText()
const balanceUSD = await balanceUSDField.getText()
console.log('Balance = ' + parseFloat(balance))
console.log('balanceUSD = ' + parseFloat(balanceUSD))
assert.equal(parseFloat(balance) > 0.0001, true, 'Balance of account ' + account1 + ' is TOO LOW in RSK testnet !!! Please refill it!!!!')
assert.equal(parseFloat(balanceUSD), 0, 'USD balance of account is not zero')
})
it('opens RSK faucet', async function () {
await f.waitUntilShowUp(screens.main.buttons.buyRSK)
const buttons = await f.driver.findElements(screens.main.buttons.buyRSK)
assert.equal(buttons.length, 1, 'main screen isn\'t displayed')
const buyButton = buttons[0]
const buyButtonText = await buyButton.getText()
assert.equal(buyButtonText, 'Buy', 'button has incorrect name')
await buyButton.click()
await f.delay(2000)
const title = await f.waitUntilShowUp(screens.buyEther.title)
assert.equal(await title.getText(), 'Buy RBTC', "screen 'Buy RBTC' has incorrect title text")
await f.waitUntilShowUp(screens.buyEther.faucetLinkRSK)
const faucetButtons = await f.driver.findElements(screens.buyEther.faucetLinkRSK)
assert.equal(faucetButtons.length, 1, 'there is no faucet button on the screen')
const faucetLinkButton = faucetButtons[0]
assert.equal(await faucetLinkButton.getText(), 'RSK Testnet Test Faucet', "screen 'Buy RSK' has incorrect name for faucet link")
await faucetLinkButton.click()
await f.delay(3000)
const [tab0, tab1] = await f.driver.getAllWindowHandles()
await f.driver.switchTo().window(tab1)
const faucetLink = await f.driver.getCurrentUrl()
assert.equal(faucetLink, 'https://faucet.testnet.rsk.co/', 'Incorrect faucet link for RSK network')
await f.driver.close()
await f.driver.switchTo().window(tab0)
const arrow = await f.waitUntilShowUp(elements.buttonArrow)
await arrow.click()
await f.delay(2000)
})
it('opens send transaction screen', async function () {
const sendButton = await f.waitUntilShowUp(screens.main.buttons.sendRSK)
assert.equal(await sendButton.getText(), screens.main.buttons.sendText)
await f.click(sendButton)
})
it('adds recipient address and amount', async function () {
const sendTranscationScreen = await f.waitUntilShowUp(screens.sendTransaction.title)
assert.equal(await sendTranscationScreen.getText(), screens.sendTransaction.titleText, 'Transaction screen has incorrect titlr')
const inputAddress = await f.waitUntilShowUp(screens.sendTransaction.field.address)
const inputAmmount = await f.waitUntilShowUp(screens.sendTransaction.field.amount)
await inputAddress.sendKeys(account1)
await f.clearField(inputAmmount)
await inputAmmount.sendKeys('0.000001')
const button = await f.waitUntilShowUp(screens.sendTransaction.buttonNext)
assert.equal(await button.getText(), 'Next', 'button has incorrect name')
await f.click(button)
})
it('confirms transaction', async function () {
const inputGasLimit = await f.waitUntilShowUp(screens.confirmTransaction.fields.gasLimit)
await f.clearField(inputGasLimit)
await inputGasLimit.sendKeys('21000')
const button = await f.waitUntilShowUp(screens.confirmTransaction.button.submit)
assert.equal(await button.getAttribute('value'), 'Submit', 'button has incorrect name')
await f.click(button)
})
it('finds the transaction in the transactions list', async function () {
const transactionAmount = await f.waitUntilShowUp(screens.main.transactionList)
assert.equal(await transactionAmount.getText(), '<0.001')
})
}
module.exports = RSKNetworkTests

View File

@ -170,6 +170,11 @@ const addCustomToken = async (f, account1, account2) => {
await f.setProvider(NETWORKS.RSK)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
})
it('token should not be displayed in RSK testnet', async () => {
await f.setProvider(NETWORKS.RSK_TESTNET)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
})
})
describe.skip('Custom tokens validation ', async () => {
@ -210,6 +215,11 @@ const addCustomToken = async (f, account1, account2) => {
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in RSK mainnet')
})
it('can not add inexistent token to RSK testnet', async () => {
await f.setProvider(NETWORKS.RSK_TESTNET)
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in RSK testnet')
})
it('can not add inexistent token to LOCALHOST network', async () => {
await f.setProvider(NETWORKS.LOCALHOST)
assert(await f.isDisabledAddInexistentToken(tokenAddress.slice(0, tokenAddress.length - 2) + '0'), true, 'can add inexistent token in LOCALHOST network')

View File

@ -255,6 +255,11 @@ const addTokeFromSearch = async (f) => {
await f.setProvider(NETWORKS.RSK)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
})
it('token should not be displayed in RSK testnet', async () => {
await f.setProvider(NETWORKS.RSK_TESTNET)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
})
})
describe('remove Mainnet\'s tokens', function () {

View File

@ -15,6 +15,7 @@ const { POA,
DAI,
POA_SOKOL,
RSK,
RSK_TESTNET,
CLASSIC } = require('../../app/scripts/controllers/network/enums')
const { hasUnconfirmedTransactions } = require('./helpers/confirm-transaction/util')
const WebcamUtils = require('../lib/webcam-utils')
@ -2015,7 +2016,7 @@ function setProviderType (type) {
const newCoin = type === POA || type === POA_SOKOL ?
'poa' : type === DAI ?
'dai' : type === CLASSIC ?
'etc' : type === RSK ?
'etc' : type === RSK || type === RSK_TESTNET ?
'rbtc' : 'eth'
background.setCurrentCoin(newCoin, (err, data) => {
if (err) {