1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

feature: add Goerli support (#6459)

This commit is contained in:
Paul Bouchon 2019-04-17 13:34:49 -04:00 committed by Whymarrh Whitby
parent 00133d31b1
commit 0db0a187c8
27 changed files with 137 additions and 19 deletions

View File

@ -311,6 +311,9 @@
"connectingToLocalhost": { "connectingToLocalhost": {
"message": "Connecting to Localhost 8545" "message": "Connecting to Localhost 8545"
}, },
"connectingToGoerli": {
"message": "Connecting to Goerli Test Network"
},
"connectingToUnknown": { "connectingToUnknown": {
"message": "Connecting to Unknown Network" "message": "Connecting to Unknown Network"
}, },
@ -1229,6 +1232,9 @@
"ropsten": { "ropsten": {
"message": "Ropsten Test Network" "message": "Ropsten Test Network"
}, },
"goerli": {
"message": "Goerli Test Network"
},
"rpc": { "rpc": {
"message": "Custom RPC" "message": "Custom RPC"
}, },

View File

@ -49,6 +49,10 @@ function createNetworkAndChainIdMiddleware ({ network }) {
netId = '42' netId = '42'
chainId = '0x2a' chainId = '0x2a'
break break
case 'goerli':
netId = '5'
chainId = '0x05'
break
default: default:
throw new Error(`createInfuraClient - unknown network "${network}"`) throw new Error(`createInfuraClient - unknown network "${network}"`)
} }

View File

@ -3,16 +3,19 @@ const RINKEBY = 'rinkeby'
const KOVAN = 'kovan' const KOVAN = 'kovan'
const MAINNET = 'mainnet' const MAINNET = 'mainnet'
const LOCALHOST = 'localhost' const LOCALHOST = 'localhost'
const GOERLI = 'goerli'
const MAINNET_CODE = 1 const MAINNET_CODE = 1
const ROPSTEN_CODE = 3 const ROPSTEN_CODE = 3
const RINKEYBY_CODE = 4 const RINKEYBY_CODE = 4
const KOVAN_CODE = 42 const KOVAN_CODE = 42
const GOERLI_CODE = 5
const ROPSTEN_DISPLAY_NAME = 'Ropsten' const ROPSTEN_DISPLAY_NAME = 'Ropsten'
const RINKEBY_DISPLAY_NAME = 'Rinkeby' const RINKEBY_DISPLAY_NAME = 'Rinkeby'
const KOVAN_DISPLAY_NAME = 'Kovan' const KOVAN_DISPLAY_NAME = 'Kovan'
const MAINNET_DISPLAY_NAME = 'Main Ethereum Network' const MAINNET_DISPLAY_NAME = 'Main Ethereum Network'
const GOERLI_DISPLAY_NAME = 'Goerli'
module.exports = { module.exports = {
ROPSTEN, ROPSTEN,
@ -20,12 +23,15 @@ module.exports = {
KOVAN, KOVAN,
MAINNET, MAINNET,
LOCALHOST, LOCALHOST,
GOERLI,
MAINNET_CODE, MAINNET_CODE,
ROPSTEN_CODE, ROPSTEN_CODE,
RINKEYBY_CODE, RINKEYBY_CODE,
KOVAN_CODE, KOVAN_CODE,
GOERLI_CODE,
ROPSTEN_DISPLAY_NAME, ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME, RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME, KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME, MAINNET_DISPLAY_NAME,
GOERLI_DISPLAY_NAME,
} }

View File

@ -20,8 +20,9 @@ const {
KOVAN, KOVAN,
MAINNET, MAINNET,
LOCALHOST, LOCALHOST,
GOERLI,
} = require('./enums') } = require('./enums')
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET] const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, GOERLI]
const env = process.env.METAMASK_ENV const env = process.env.METAMASK_ENV
const METAMASK_DEBUG = process.env.METAMASK_DEBUG const METAMASK_DEBUG = process.env.METAMASK_DEBUG

View File

@ -3,13 +3,16 @@ const {
RINKEBY, RINKEBY,
KOVAN, KOVAN,
MAINNET, MAINNET,
GOERLI,
ROPSTEN_CODE, ROPSTEN_CODE,
RINKEYBY_CODE, RINKEYBY_CODE,
KOVAN_CODE, KOVAN_CODE,
GOERLI_CODE,
ROPSTEN_DISPLAY_NAME, ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME, RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME, KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME, MAINNET_DISPLAY_NAME,
GOERLI_DISPLAY_NAME,
} = require('./enums') } = require('./enums')
const networkToNameMap = { const networkToNameMap = {
@ -17,9 +20,11 @@ const networkToNameMap = {
[RINKEBY]: RINKEBY_DISPLAY_NAME, [RINKEBY]: RINKEBY_DISPLAY_NAME,
[KOVAN]: KOVAN_DISPLAY_NAME, [KOVAN]: KOVAN_DISPLAY_NAME,
[MAINNET]: MAINNET_DISPLAY_NAME, [MAINNET]: MAINNET_DISPLAY_NAME,
[GOERLI]: GOERLI_DISPLAY_NAME,
[ROPSTEN_CODE]: ROPSTEN_DISPLAY_NAME, [ROPSTEN_CODE]: ROPSTEN_DISPLAY_NAME,
[RINKEYBY_CODE]: RINKEBY_DISPLAY_NAME, [RINKEYBY_CODE]: RINKEBY_DISPLAY_NAME,
[KOVAN_CODE]: KOVAN_DISPLAY_NAME, [KOVAN_CODE]: KOVAN_DISPLAY_NAME,
[GOERLI_CODE]: GOERLI_DISPLAY_NAME,
} }
const getNetworkDisplayName = key => networkToNameMap[key] const getNetworkDisplayName = key => networkToNameMap[key]

View File

@ -8,8 +8,9 @@ const {
RINKEBY, RINKEBY,
KOVAN, KOVAN,
MAINNET, MAINNET,
GOERLI,
} = require('./network/enums') } = require('./network/enums')
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET] const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, GOERLI]
class RecentBlocksController { class RecentBlocksController {

View File

@ -28,6 +28,8 @@ function getBuyEthUrl ({ network, amount, address, service }) {
return 'https://www.rinkeby.io/' return 'https://www.rinkeby.io/'
case 'kovan-faucet': case 'kovan-faucet':
return 'https://github.com/kovan-testnet/faucet' return 'https://github.com/kovan-testnet/faucet'
case 'goerli-faucet':
return 'https://goerli-faucet.slock.it/'
} }
throw new Error(`Unknown cryptocurrency exchange or faucet: "${service}"`) throw new Error(`Unknown cryptocurrency exchange or faucet: "${service}"`)
} }
@ -42,6 +44,8 @@ function getDefaultServiceForNetwork (network) {
return 'rinkeby-faucet' return 'rinkeby-faucet'
case '42': case '42':
return 'kovan-faucet' return 'kovan-faucet'
case '5':
return 'goerli-faucet'
} }
throw new Error(`No default cryptocurrency exchange or faucet for networkId: "${network}"`) throw new Error(`No default cryptocurrency exchange or faucet for networkId: "${network}"`)
} }

View File

@ -230,7 +230,8 @@
"kovan": "ok", "kovan": "ok",
"mainnet": "ok", "mainnet": "ok",
"rinkeby": "ok", "rinkeby": "ok",
"ropsten": "ok" "ropsten": "ok",
"goerli": "ok"
}, },
"lostAccounts": [] "lostAccounts": []
}, },

View File

@ -704,7 +704,8 @@
"mainnet": "ok", "mainnet": "ok",
"ropsten": "ok", "ropsten": "ok",
"kovan": "ok", "kovan": "ok",
"rinkeby": "ok" "rinkeby": "ok",
"goerli": "ok"
}, },
"shapeShiftTxList": [], "shapeShiftTxList": [],
"lostAccounts": [] "lostAccounts": []

View File

@ -54,7 +54,8 @@
"mainnet": "degraded", "mainnet": "degraded",
"ropsten": "ok", "ropsten": "ok",
"kovan": "ok", "kovan": "ok",
"rinkeby": "ok" "rinkeby": "ok",
"goerli": "ok"
} }
}, },
"BlacklistController": { "BlacklistController": {

View File

@ -4,7 +4,7 @@ const InfuraController = require('../../../../app/scripts/controllers/infura')
describe('infura-controller', function () { describe('infura-controller', function () {
let infuraController, sandbox, networkStatus let infuraController, sandbox, networkStatus
const response = {'mainnet': 'degraded', 'ropsten': 'ok', 'kovan': 'ok', 'rinkeby': 'down'} const response = {'mainnet': 'degraded', 'ropsten': 'ok', 'kovan': 'ok', 'rinkeby': 'down', 'goerli': 'ok'}
before(async function () { before(async function () {
infuraController = new InfuraController() infuraController = new InfuraController()
@ -58,5 +58,15 @@ describe('infura-controller', function () {
assert.equal(networkStatus.rinkeby, 'down') assert.equal(networkStatus.rinkeby, 'down')
}) })
}) })
describe('Goerli', function () {
it('should have Goerli', function () {
assert.equal(Object.keys(networkStatus)[4], 'goerli')
})
it('should have a value for Goerli status', function () {
assert.equal(networkStatus.goerli, 'ok')
})
})
}) })
}) })

View File

@ -92,6 +92,9 @@ describe('Network utils', () => {
}, { }, {
input: 'mainnet', input: 'mainnet',
expected: 'Main Ethereum Network', expected: 'Main Ethereum Network',
}, {
input: 'goerli',
expected: 'Goerli',
}, },
] ]

View File

@ -4,6 +4,7 @@ const {
ROPSTEN_CODE, ROPSTEN_CODE,
RINKEYBY_CODE, RINKEYBY_CODE,
KOVAN_CODE, KOVAN_CODE,
GOERLI_CODE,
} = require('../../../../../app/scripts/controllers/network/enums') } = require('../../../../../app/scripts/controllers/network/enums')
const KeyringController = require('eth-keyring-controller') const KeyringController = require('eth-keyring-controller')
@ -27,14 +28,14 @@ describe('Recipient Blacklist Checker', function () {
describe('#checkAccount', function () { describe('#checkAccount', function () {
it('does not fail on test networks', function () { it('does not fail on test networks', function () {
let callCount = 0 let callCount = 0
const networks = [ROPSTEN_CODE, RINKEYBY_CODE, KOVAN_CODE] const networks = [ROPSTEN_CODE, RINKEYBY_CODE, KOVAN_CODE, GOERLI_CODE]
for (const networkId in networks) { for (const networkId in networks) {
publicAccounts.forEach((account) => { publicAccounts.forEach((account) => {
recipientBlackListChecker.checkAccount(networkId, account) recipientBlackListChecker.checkAccount(networkId, account)
callCount++ callCount++
}) })
} }
assert.equal(callCount, 30) assert.equal(callCount, 40)
}) })
it('fails on mainnet', function () { it('fails on mainnet', function () {

View File

@ -23,4 +23,8 @@ describe('Etherscan Network Prefix', () => {
assert.equal(etherscanNetworkPrefix(42), 'kovan.') assert.equal(etherscanNetworkPrefix(42), 'kovan.')
}) })
it('returs goerli as prefix for networkId of 5', () => {
assert.equal(etherscanNetworkPrefix(5), 'goerli.')
})
}) })

View File

@ -204,6 +204,28 @@ NetworkDropdown.prototype.render = function () {
] ]
), ),
h(
DropdownMenuItem,
{
key: 'goerli',
closeMenu: () => this.props.hideNetworkDropdown(),
onClick: () => this.handleClick('goerli'),
style: dropdownMenuItemStyle,
},
[
providerType === 'goerli' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
backgroundColor: '#3099f2', // $dodger-blue
isSelected: providerType === 'goerli',
}),
h('span.network-name-item', {
style: {
color: providerType === 'goerli' ? '#ffffff' : '#9b9b9b',
},
}, this.context.t('goerli')),
]
),
h( h(
DropdownMenuItem, DropdownMenuItem,
{ {
@ -287,6 +309,8 @@ NetworkDropdown.prototype.getNetworkName = function () {
name = this.context.t('rinkeby') name = this.context.t('rinkeby')
} else if (providerName === 'localhost') { } else if (providerName === 'localhost') {
name = this.context.t('localhost') name = this.context.t('localhost')
} else if (providerName === 'goerli') {
name = this.context.t('goerli')
} else { } else {
name = provider.nickname || this.context.t('unknownNetwork') name = provider.nickname || this.context.t('unknownNetwork')
} }

View File

@ -62,7 +62,7 @@ describe('Network Dropdown', () => {
}) })
it('renders 7 DropDownMenuItems ', () => { it('renders 7 DropDownMenuItems ', () => {
assert.equal(wrapper.find(DropdownMenuItem).length, 7) assert.equal(wrapper.find(DropdownMenuItem).length, 8)
}) })
it('checks background color for first NetworkDropdownIcon', () => { it('checks background color for first NetworkDropdownIcon', () => {
@ -82,16 +82,20 @@ describe('Network Dropdown', () => {
}) })
it('checks background color for fifth NetworkDropdownIcon', () => { it('checks background color for fifth NetworkDropdownIcon', () => {
assert.equal(wrapper.find(NetworkDropdownIcon).at(4).prop('innerBorder'), '1px solid #9b9b9b') assert.equal(wrapper.find(NetworkDropdownIcon).at(4).prop('backgroundColor'), '#3099f2') // Goerli Blue
})
it('checks dropdown for frequestRPCList from state ', () => {
assert.equal(wrapper.find(DropdownMenuItem).at(5).text(), '✓http://localhost:7545')
}) })
it('checks background color for sixth NetworkDropdownIcon', () => { it('checks background color for sixth NetworkDropdownIcon', () => {
assert.equal(wrapper.find(NetworkDropdownIcon).at(5).prop('innerBorder'), '1px solid #9b9b9b') assert.equal(wrapper.find(NetworkDropdownIcon).at(5).prop('innerBorder'), '1px solid #9b9b9b')
}) })
it('checks dropdown for frequestRPCList from state ', () => {
assert.equal(wrapper.find(DropdownMenuItem).at(6).text(), '✓http://localhost:7545')
})
it('checks background color for seventh NetworkDropdownIcon', () => {
assert.equal(wrapper.find(NetworkDropdownIcon).at(6).prop('innerBorder'), '1px solid #9b9b9b')
})
}) })
}) })

View File

@ -47,6 +47,8 @@ export default class LoadingNetworkScreen extends PureComponent {
name = this.context.t('connectingToRinkeby') name = this.context.t('connectingToRinkeby')
} else if (providerName === 'localhost') { } else if (providerName === 'localhost') {
name = this.context.t('connectingToLocalhost') name = this.context.t('connectingToLocalhost')
} else if (providerName === 'goerli') {
name = this.context.t('connectingToGoerli')
} else { } else {
name = this.context.t('connectingTo', [providerId]) name = this.context.t('connectingTo', [providerId])
} }

View File

@ -133,7 +133,7 @@ DepositEtherModal.prototype.render = function () {
const { network, toWyre, toCoinSwitch, address, toFaucet } = this.props const { network, toWyre, toCoinSwitch, address, toFaucet } = this.props
const { buyingWithShapeshift } = this.state const { buyingWithShapeshift } = this.state
const isTestNetwork = ['3', '4', '42'].find(n => n === network) const isTestNetwork = ['3', '4', '5', '42'].find(n => n === network)
const networkName = getNetworkDisplayName(network) const networkName = getNetworkDisplayName(network)
return h('div.page-container.page-container--full-width.page-container--full-height', {}, [ return h('div.page-container.page-container--full-width.page-container--full-height', {}, [

View File

@ -26,6 +26,10 @@
&--rinkeby { &--rinkeby {
background-color: lighten($tulip-tree, 35%); background-color: lighten($tulip-tree, 35%);
} }
&--goerli {
background-color: lighten($dodger-blue, 35%);
}
} }
&__name { &__name {
@ -53,5 +57,9 @@
&--rinkeby { &--rinkeby {
background-color: $tulip-tree; background-color: $tulip-tree;
} }
&--goerli {
background-color: $dodger-blue;
}
} }
} }

View File

@ -6,12 +6,14 @@ import {
ROPSTEN_CODE, ROPSTEN_CODE,
RINKEYBY_CODE, RINKEYBY_CODE,
KOVAN_CODE, KOVAN_CODE,
GOERLI_CODE,
} from '../../../../../app/scripts/controllers/network/enums' } from '../../../../../app/scripts/controllers/network/enums'
const networkToClassHash = { const networkToClassHash = {
[MAINNET_CODE]: 'mainnet', [MAINNET_CODE]: 'mainnet',
[ROPSTEN_CODE]: 'ropsten', [ROPSTEN_CODE]: 'ropsten',
[RINKEYBY_CODE]: 'rinkeby', [RINKEYBY_CODE]: 'rinkeby',
[GOERLI_CODE]: 'goerli',
[KOVAN_CODE]: 'kovan', [KOVAN_CODE]: 'kovan',
} }

View File

@ -50,6 +50,9 @@ Network.prototype.render = function () {
} else if (providerName === 'rinkeby') { } else if (providerName === 'rinkeby') {
hoverText = context.t('rinkeby') hoverText = context.t('rinkeby')
iconName = 'rinkeby-test-network' iconName = 'rinkeby-test-network'
} else if (providerName === 'goerli') {
hoverText = context.t('goerli')
iconName = 'goerli-test-network'
} else { } else {
hoverText = providerId hoverText = providerId
iconName = 'private-network' iconName = 'private-network'
@ -63,6 +66,7 @@ Network.prototype.render = function () {
'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3, 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3,
'kovan-test-network': providerName === 'kovan', 'kovan-test-network': providerName === 'kovan',
'rinkeby-test-network': providerName === 'rinkeby', 'rinkeby-test-network': providerName === 'rinkeby',
'goerli-test-network': providerName === 'goerli',
}), }),
title: hoverText, title: hoverText,
onClick: (event) => { onClick: (event) => {
@ -113,6 +117,16 @@ Network.prototype.render = function () {
h('.network-name', context.t('rinkeby')), h('.network-name', context.t('rinkeby')),
h('i.fa.fa-chevron-down.fa-lg.network-caret'), h('i.fa.fa-chevron-down.fa-lg.network-caret'),
]) ])
case 'goerli-test-network':
return h('.network-indicator', [
h(NetworkDropdownIcon, {
backgroundColor: '#3099f2', // $dodger-blue
nonSelectBackgroundColor: '#ecb23e',
loading: networkNumber === 'loading',
}),
h('.network-name', context.t('goerli')),
h('i.fa.fa-chevron-down.fa-lg.network-caret'),
])
default: default:
return h('.network-indicator', [ return h('.network-indicator', [
networkNumber === 'loading' networkNumber === 'loading'

View File

@ -29,6 +29,10 @@
&.rinkeby-test-network .menu-icon-circle div { &.rinkeby-test-network .menu-icon-circle div {
background-color: rgba(235, 179, 63, .7) !important; background-color: rgba(235, 179, 63, .7) !important;
} }
&.goerli-test-network .menu-icon-circle div {
background-color: rgba(48, 153, 242, .7) !important;
}
} }
.dropdown-menu-item { .dropdown-menu-item {

View File

@ -10,4 +10,5 @@ export const NETWORK_TYPES = {
MAINNET: 'mainnet', MAINNET: 'mainnet',
RINKEBY: 'rinkeby', RINKEBY: 'rinkeby',
ROPSTEN: 'ropsten', ROPSTEN: 'ropsten',
GOERLI: 'goerli',
} }

View File

@ -269,6 +269,8 @@ class Routes extends Component {
name = this.context.t('connectingToRinkeby') name = this.context.t('connectingToRinkeby')
} else if (providerName === 'localhost') { } else if (providerName === 'localhost') {
name = this.context.t('connectingToLocalhost') name = this.context.t('connectingToLocalhost')
} else if (providerName === 'goerli') {
name = this.context.t('connectingToGoerli')
} else { } else {
name = this.context.t('connectingTo', [providerId]) name = this.context.t('connectingTo', [providerId])
} }
@ -292,6 +294,8 @@ class Routes extends Component {
name = this.context.t('rinkeby') name = this.context.t('rinkeby')
} else if (providerName === 'localhost') { } else if (providerName === 'localhost') {
name = this.context.t('localhost') name = this.context.t('localhost')
} else if (providerName === 'goerli') {
name = this.context.t('goerli')
} else { } else {
name = this.context.t('unknownNetwork') name = this.context.t('unknownNetwork')
} }

View File

@ -300,9 +300,10 @@ function isEthereumNetwork (state) {
MAINNET, MAINNET,
RINKEBY, RINKEBY,
ROPSTEN, ROPSTEN,
GOERLI,
} = NETWORK_TYPES } = NETWORK_TYPES
return [ KOVAN, MAINNET, RINKEBY, ROPSTEN].includes(networkType) return [ KOVAN, MAINNET, RINKEBY, ROPSTEN, GOERLI].includes(networkType)
} }
function preferencesSelector ({ metamask }) { function preferencesSelector ({ metamask }) {

View File

@ -17,6 +17,9 @@ module.exports = function (address, network) {
case 42: // kovan test net case 42: // kovan test net
link = `https://kovan.etherscan.io/address/${address}` link = `https://kovan.etherscan.io/address/${address}`
break break
case 5: // goerli test net
link = `https://goerli.etherscan.io/address/${address}`
break
default: default:
link = '' link = ''
break break

View File

@ -14,6 +14,9 @@ module.exports = function (network) {
case 42: // kovan test net case 42: // kovan test net
prefix = 'kovan.' prefix = 'kovan.'
break break
case 5: // goerli test net
prefix = 'goerli.'
break
default: default:
prefix = '' prefix = ''
} }