Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CELO chains support #446

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 75 additions & 33 deletions app/scripts/controllers/network/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,30 @@ const CLASSIC = 'classic'
const RSK = 'rsk'
const RSK_TESTNET = 'rsk_testnet'
const LOCALHOST = 'localhost'
const CELO = 'celo'
const CELO_ALFAJORES_TESTNET = 'celo-alfajores'
const CELO_BAKLAVA_TESTNET = 'celo-baklava'

const ETH_TICK = 'ETH'
const POA_TICK = 'POA'
const RSK_TICK = 'RBTC'
const CLASSIC_TICK = 'ETC'
const CELO_TICK = 'CELO'

const MAINNET_CHAINID = '0x01'
const ROPSTEN_CHAINID = '0x03'
const RINKEBY_CHAINID = '0x04'
const KOVAN_CHAINID = '0x2a'
const GOERLI_TESTNET_CHAINID = '0x5'
const POA_CHAINID = '0x63'
const DAI_CHAINID = '0x64'
const POA_SOKOL_CHAINID = '0x4D'
const RSK_CHAINID = '0x1E'
const RSK_TESTNET_CHAINID = '0x1F'
const CLASSIC_CHAINID = '0x3D'
const MAINNET_CHAIN_ID = '0x01'
const ROPSTEN_CHAIN_ID = '0x03'
const RINKEBY_CHAIN_ID = '0x04'
const KOVAN_CHAIN_ID = '0x2a'
const GOERLI_TESTNET_CHAIN_ID = '0x5'
const POA_CHAIN_ID = '0x63'
const DAI_CHAIN_ID = '0x64'
const POA_SOKOL_CHAIN_ID = '0x4D'
const RSK_CHAIN_ID = '0x1E'
const RSK_TESTNET_CHAIN_ID = '0x1F'
const CLASSIC_CHAIN_ID = '0x3D'
const CELO_CHAIN_ID = '0xA4EC'
const CELO_ALFAJORES_TESTNET_CHAIN_ID = '0xAEF3'
const CELO_BAKLAVA_TESTNET_CHAIN_ID = '0xF370'

const POA_CODE = 99
const DAI_CODE = 100
Expand All @@ -39,6 +46,9 @@ const GOERLI_TESTNET_CODE = 5
const CLASSIC_CODE = 61
const RSK_CODE = 30
const RSK_TESTNET_CODE = 31
const CELO_CODE = 42220
const CELO_ALFAJORES_TESTNET_CODE = 44787
const CELO_BAKLAVA_TESTNET_CODE = 62320


const MAINNET_NETWORK_ID = '1'
Expand All @@ -52,19 +62,25 @@ const POA_SOKOL_NETWORK_ID = '77'
const CLASSIC_NETWORK_ID = '61'
const RSK_NETWORK_ID = '30'
const RSK_TESTNET_NETWORK_ID = '31'
const CELO_NETWORK_ID = '42220'
const CELO_ALFAJORES_NETWORK_ID = '44787'
const CELO_BAKLAVA_NETWORK_ID = '62320'

const NETWORK_TYPE_TO_ID_MAP = {
[ROPSTEN]: { networkId: ROPSTEN_NETWORK_ID, chainId: ROPSTEN_CHAINID },
[RINKEBY]: { networkId: RINKEBY_NETWORK_ID, chainId: RINKEBY_CHAINID },
[KOVAN]: { networkId: KOVAN_NETWORK_ID, chainId: KOVAN_CHAINID },
[GOERLI_TESTNET]: { networkId: GOERLI_NETWORK_ID, chainId: GOERLI_TESTNET_CHAINID },
[MAINNET]: { networkId: MAINNET_NETWORK_ID, chainId: MAINNET_CHAINID },
[POA]: { networkId: POA_NETWORK_ID, chainId: POA_CHAINID },
[DAI]: { networkId: DAI_NETWORK_ID, chainId: DAI_CHAINID },
[POA_SOKOL]: { networkId: POA_SOKOL_NETWORK_ID, chainId: POA_SOKOL_CHAINID },
[CLASSIC]: { networkId: CLASSIC_NETWORK_ID, chainId: CLASSIC_CHAINID },
[RSK]: { networkId: RSK_NETWORK_ID, chainId: RSK_CHAINID },
[RSK_TESTNET]: { networkId: RSK_TESTNET_NETWORK_ID, chainId: RSK_TESTNET_CHAINID },
[ROPSTEN]: { networkId: ROPSTEN_NETWORK_ID, chainId: ROPSTEN_CHAIN_ID },
[RINKEBY]: { networkId: RINKEBY_NETWORK_ID, chainId: RINKEBY_CHAIN_ID },
[KOVAN]: { networkId: KOVAN_NETWORK_ID, chainId: KOVAN_CHAIN_ID },
[GOERLI_TESTNET]: { networkId: GOERLI_NETWORK_ID, chainId: GOERLI_TESTNET_CHAIN_ID },
[MAINNET]: { networkId: MAINNET_NETWORK_ID, chainId: MAINNET_CHAIN_ID },
[POA]: { networkId: POA_NETWORK_ID, chainId: POA_CHAIN_ID },
[DAI]: { networkId: DAI_NETWORK_ID, chainId: DAI_CHAIN_ID },
[POA_SOKOL]: { networkId: POA_SOKOL_NETWORK_ID, chainId: POA_SOKOL_CHAIN_ID },
[CLASSIC]: { networkId: CLASSIC_NETWORK_ID, chainId: CLASSIC_CHAIN_ID },
[RSK]: { networkId: RSK_NETWORK_ID, chainId: RSK_CHAIN_ID },
[RSK_TESTNET]: { networkId: RSK_TESTNET_NETWORK_ID, chainId: RSK_TESTNET_CHAIN_ID },
[CELO]: { networkId: CELO_NETWORK_ID, chainId: CELO_CHAIN_ID},
[CELO_ALFAJORES_TESTNET]: { networkId: CELO_ALFAJORES_NETWORK_ID, chainId: CELO_ALFAJORES_TESTNET_CHAIN_ID},
[CELO_BAKLAVA_TESTNET]: { networkId: CELO_BAKLAVA_NETWORK_ID, chainId: CELO_BAKLAVA_TESTNET_CHAIN_ID},
}

const POA_DISPLAY_NAME = 'POA'
Expand All @@ -78,6 +94,9 @@ const GOERLI_TESTNET_DISPLAY_NAME = 'Görli Testnet'
const CLASSIC_DISPLAY_NAME = 'Ethereum Classic'
const RSK_DISPLAY_NAME = 'RSK'
const RSK_TESTNET_DISPLAY_NAME = 'RSK Testnet'
const CELO_DISPLAY_NAME = 'CELO'
const CELO_ALFAJORES_TESTNET_DISPLAY_NAME = 'CELO Alfajores'
const CELO_BAKLAVA_TESTNET_DISPLAY_NAME = 'CELO Baklava'

const DROPDOWN_POA_DISPLAY_NAME = POA_DISPLAY_NAME
const DROPDOWN_DAI_DISPLAY_NAME = DAI_DISPLAY_NAME
Expand All @@ -90,6 +109,9 @@ const DROPDOWN_GOERLI_TESTNET_DISPLAY_NAME = GOERLI_TESTNET_DISPLAY_NAME
const DROPDOWN_CLASSIC_DISPLAY_NAME = CLASSIC_DISPLAY_NAME
const DROPDOWN_RSK_DISPLAY_NAME = RSK_DISPLAY_NAME
const DROPDOWN_RSK_TESTNET_DISPLAY_NAME = RSK_TESTNET_DISPLAY_NAME
const DROPDOWN_CELO_DISPLAY_NAME = CELO_DISPLAY_NAME
const DROPDOWN_CELO_ALFAJORES_TESTNET_DISPLAY_NAME = CELO_ALFAJORES_TESTNET_DISPLAY_NAME
const DROPDOWN_CELO_BAKLAVA_TESTNET_DISPLAY_NAME = CELO_BAKLAVA_TESTNET_DISPLAY_NAME

const chainTypes = {
TEST: 1,
Expand All @@ -99,28 +121,37 @@ const chainTypes = {
const hdRSKMainnetPath = `m/44'/137'/0'/0`
const hdRSKTestnetPath = `m/44'/37310'/0'/0`
const hdETCPath = `m/44'/61'/0'/0`
const hdCELOPath = `m/44'/52752'/0'`

const customDPaths = {}
customDPaths[RSK] = hdRSKMainnetPath
customDPaths[RSK_TESTNET] = hdRSKTestnetPath
customDPaths[CLASSIC] = hdETCPath
customDPaths[CELO] = hdCELOPath
customDPaths[CELO_ALFAJORES_TESTNET] = hdCELOPath
customDPaths[CELO_BAKLAVA_TESTNET] = hdCELOPath

module.exports = {
POA,
POA_TICK,
ETH_TICK,
RSK_TICK,
CLASSIC_TICK,
MAINNET_CHAINID,
ROPSTEN_CHAINID,
RINKEBY_CHAINID,
KOVAN_CHAINID,
GOERLI_TESTNET_CHAINID,
POA_CHAINID,
DAI_CHAINID,
POA_SOKOL_CHAINID,
RSK_CHAINID,
RSK_TESTNET_CHAINID,
CELO_TICK,
MAINNET_CHAIN_ID,
ROPSTEN_CHAIN_ID,
RINKEBY_CHAIN_ID,
KOVAN_CHAIN_ID,
GOERLI_TESTNET_CHAIN_ID,
POA_CHAIN_ID,
DAI_CHAIN_ID,
POA_SOKOL_CHAIN_ID,
RSK_CHAIN_ID,
RSK_TESTNET_CHAIN_ID,
CLASSIC_CHAIN_ID,
CELO_CHAIN_ID,
CELO_ALFAJORES_TESTNET_CHAIN_ID,
CELO_BAKLAVA_TESTNET_CHAIN_ID,
DAI,
POA_SOKOL,
MAINNET,
Expand All @@ -131,6 +162,9 @@ module.exports = {
CLASSIC,
RSK,
RSK_TESTNET,
CELO,
CELO_ALFAJORES_TESTNET,
CELO_BAKLAVA_TESTNET,
LOCALHOST,
POA_CODE,
DAI_CODE,
Expand All @@ -141,7 +175,9 @@ module.exports = {
KOVAN_CODE,
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
CLASSIC_CHAINID,
CELO_CODE,
CELO_ALFAJORES_TESTNET_CODE,
CELO_BAKLAVA_TESTNET_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
POA_DISPLAY_NAME,
Expand All @@ -155,6 +191,9 @@ module.exports = {
CLASSIC_DISPLAY_NAME,
RSK_DISPLAY_NAME,
RSK_TESTNET_DISPLAY_NAME,
CELO_DISPLAY_NAME,
CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
Expand All @@ -166,6 +205,9 @@ module.exports = {
DROPDOWN_CLASSIC_DISPLAY_NAME,
DROPDOWN_RSK_DISPLAY_NAME,
DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
DROPDOWN_CELO_DISPLAY_NAME,
DROPDOWN_CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
DROPDOWN_CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
chainTypes,
customDPaths,
NETWORK_TYPE_TO_ID_MAP,
Expand Down
12 changes: 12 additions & 0 deletions app/scripts/controllers/network/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@ const {
CLASSIC,
RSK,
RSK_TESTNET,
CELO,
CELO_ALFAJORES_TESTNET,
CELO_BAKLAVA_TESTNET,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
GOERLI_TESTNET_CODE,
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
CELO_CODE,
CELO_ALFAJORES_TESTNET_CODE,
CELO_BAKLAVA_TESTNET_CODE,
} = require('./enums')
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN]
const POCKET_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, POA, DAI, GOERLI_TESTNET, POA_SOKOL]
Expand Down Expand Up @@ -264,6 +270,12 @@ module.exports = class NetworkController extends EventEmitter {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0], chainId, ticker, nickname })
} else if (type === RSK_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0], chainId, ticker, nickname })
} else if (type === CELO) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CELO_CODE)[0], chainId, ticker, nickname })
} else if (type === CELO_ALFAJORES_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CELO_ALFAJORES_TESTNET_CODE)[0], chainId, ticker, nickname })
} else if (type === CELO_BAKLAVA_TESTNET) {
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CELO_BAKLAVA_TESTNET_CODE)[0], chainId, ticker, nickname })
} else if (type === LOCALHOST) {
this._configureLocalhostProvider()
// url-based rpc endpoints
Expand Down
42 changes: 42 additions & 0 deletions app/scripts/controllers/network/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const {
CLASSIC,
RSK,
RSK_TESTNET,
CELO,
CELO_ALFAJORES_TESTNET,
CELO_BAKLAVA_TESTNET,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
Expand All @@ -21,6 +24,9 @@ const {
CLASSIC_CODE,
RSK_CODE,
RSK_TESTNET_CODE,
CELO_CODE,
CELO_ALFAJORES_TESTNET_CODE,
CELO_BAKLAVA_TESTNET_CODE,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME,
Expand All @@ -32,6 +38,9 @@ const {
CLASSIC_DISPLAY_NAME,
RSK_DISPLAY_NAME,
RSK_TESTNET_DISPLAY_NAME,
CELO_DISPLAY_NAME,
CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
Expand All @@ -43,6 +52,9 @@ const {
DROPDOWN_CLASSIC_DISPLAY_NAME,
DROPDOWN_RSK_DISPLAY_NAME,
DROPDOWN_RSK_TESTNET_DISPLAY_NAME,
DROPDOWN_CELO_DISPLAY_NAME,
DROPDOWN_CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
DROPDOWN_CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
chainTypes,
} = require('./enums')

Expand Down Expand Up @@ -167,6 +179,36 @@ const RSK_TESTNET_OBJ = {
networks[RSK_TESTNET_CODE] = RSK_TESTNET_OBJ
networks[RSK_TESTNET] = RSK_TESTNET_OBJ

const CELO_OBJ = {
order: 12,
providerName: CELO,
networkID: CELO_CODE,
displayName: CELO_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_CELO_DISPLAY_NAME,
}
networks[CELO_CODE] = CELO_OBJ
networks[CELO] = CELO_OBJ

const CELO_ALFAJORES_TESTNET_OBJ = {
order: 13,
providerName: CELO_ALFAJORES_TESTNET,
networkID: CELO_ALFAJORES_TESTNET_CODE,
displayName: CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_CELO_ALFAJORES_TESTNET_DISPLAY_NAME,
}
networks[CELO_ALFAJORES_TESTNET_CODE] = CELO_ALFAJORES_TESTNET_OBJ
networks[CELO_ALFAJORES_TESTNET] = CELO_ALFAJORES_TESTNET_OBJ

const CELO_BAKLAVA_TESTNET_OBJ = {
order: 14,
providerName: CELO_BAKLAVA_TESTNET,
networkID: CELO_BAKLAVA_TESTNET_CODE,
displayName: CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_CELO_BAKLAVA_TESTNET_DISPLAY_NAME,
}
networks[CELO_BAKLAVA_TESTNET_CODE] = CELO_BAKLAVA_TESTNET_OBJ
networks[CELO_BAKLAVA_TESTNET] = CELO_BAKLAVA_TESTNET_OBJ

const getNetworkDisplayName = key => networks[key].displayName

function formatTxMetaForRpcResult (txMeta) {
Expand Down
51 changes: 48 additions & 3 deletions app/scripts/controllers/transactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const {
TRANSACTION_TYPE_RETRY,
} = require('./enums')

const ContractKit = require('@celo/contractkit')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing commonjs require and es6 import here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, James! I replaced requires with ES6 imports statements in 86a08d0 specifically for TransactionController. Though I am aware, there can be multiple places where mixing takes places in the code. I suppose other mixing occurrences can be processed in a separate refactoring PR(s).

import Web3 from 'web3-1-3'
import { CELO_CODE, CELO_ALFAJORES_TESTNET_CODE, CELO_BAKLAVA_TESTNET_CODE } from '../network/enums'
import ethNetProps from 'eth-net-props'

const { hexToBn, bnToHex, BnMultiplyByFraction } = require('../../lib/util')

/**
Expand Down Expand Up @@ -62,6 +67,7 @@ class TransactionController extends EventEmitter {
this.provider = opts.provider
this.blockTracker = opts.blockTracker
this.signEthTx = opts.signTransaction
this.getPrivateKeyFor = opts.getPrivateKeyFor
this.getGasPrice = opts.getGasPrice

this.memStore = new ObservableStore({})
Expand Down Expand Up @@ -350,9 +356,15 @@ class TransactionController extends EventEmitter {
// add nonce debugging information to txMeta
txMeta.nonceDetails = nonceLock.nonceDetails
this.txStateManager.updateTx(txMeta, 'transactions#approveTransaction')
// sign transaction
const rawTx = await this.signTransaction(txId)
await this.publishTransaction(txId, rawTx)
const chainId = this.getChainId()
if (chainId === CELO_CODE || chainId === CELO_ALFAJORES_TESTNET_CODE || chainId === CELO_BAKLAVA_TESTNET_CODE) {
const fromAddressPK = await this.getPrivateKeyFor(fromAddress)
await this.sendCelo(txMeta.txParams, txId, fromAddress, fromAddressPK)
} else {
// sign transaction
const rawTx = await this.signTransaction(txId)
await this.publishTransaction(txId, rawTx)
}
// must set transaction to submitted/failed before releasing lock
nonceLock.releaseLock()
} catch (err) {
Expand Down Expand Up @@ -404,6 +416,39 @@ class TransactionController extends EventEmitter {
this.txStateManager.setTxStatusSubmitted(txId)
}

async sendCelo (txParams, txId, fromAddress, fromAddressPK) {
const txMeta = this.txStateManager.getTx(txId)

const network = this.getNetwork()
const rpcUrl = ethNetProps.RPCEndpoints(network)[0]
const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl))
const kit = ContractKit.newKitFromWeb3(web3)

const fromAddressPKstr = fromAddressPK.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')

// Add account to ContractKit to sign transactions
kit.connection.addAccount(fromAddressPKstr)

// Set state to signed
this.txStateManager.setTxStatusSigned(txMeta.id)

// Specify recipient Address
const anAddress = txParams.to

// Specify an amount to send
const amount = parseInt(Number(txParams.value), 10)

// Get the token contract wrappers
const goldtoken = await kit.contracts.getGoldToken()

// Transfer CELO
const celotx = await goldtoken.transfer(anAddress, amount).send({from: fromAddress})
const celoReceipt = await celotx.waitReceipt()

this.setTxHash(txId, celoReceipt.transactionHash)
this.txStateManager.setTxStatusSubmitted(txId)
}

/**
* Sets the status of the transaction to confirmed and sets the status of nonce duplicates as
* dropped if the txParams have data it will fetch the txReceipt
Expand Down
Loading