Skip to content

Commit

Permalink
Add CELO chain support
Browse files Browse the repository at this point in the history
  • Loading branch information
vbaranov committed Feb 11, 2021
1 parent 1bf007c commit af6f510
Show file tree
Hide file tree
Showing 16 changed files with 3,354 additions and 643 deletions.
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')
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

0 comments on commit af6f510

Please sign in to comment.