mirror of https://github.com/embarklabs/embark.git
feat(@embark/accounts-manager): Get alternative coinbase address
In dev mode, accounts are funded per the blockchain accounts config. In specific situations, there may not be enough funds on the account returned by `eth_coinbase`. In that case, and in the case when `eth_coinbase` returns `0x0` (or equivalent), loop through all accounts and find the one that has the most funds and use that as the coinbase account.
This commit is contained in:
parent
edf43470e4
commit
72e609a7e9
|
@ -26,6 +26,7 @@ export default class AccountsManager {
|
||||||
// reset accounts backing variable as the accounts in config may have changed and
|
// reset accounts backing variable as the accounts in config may have changed and
|
||||||
// web.eth.getAccounts may return a different value now
|
// web.eth.getAccounts may return a different value now
|
||||||
this._accounts = null;
|
this._accounts = null;
|
||||||
|
this._web3 = null;
|
||||||
|
|
||||||
// as the accounts may have changed, we need to fund the accounts again
|
// as the accounts may have changed, we need to fund the accounts again
|
||||||
await this.parseAndFundAccounts();
|
await this.parseAndFundAccounts();
|
||||||
|
@ -54,14 +55,13 @@ export default class AccountsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async parseAndFundAccounts() {
|
private async parseAndFundAccounts() {
|
||||||
const web3 = await this.web3;
|
|
||||||
const accounts = await this.accounts;
|
const accounts = await this.accounts;
|
||||||
|
|
||||||
if (!accounts.length || !this.embark.config.blockchainConfig.isDev) {
|
if (!accounts.length || !this.embark.config.blockchainConfig.isDev) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const coinbase = await web3.eth.getCoinbase();
|
const web3 = await this.web3;
|
||||||
|
const coinbase = await this.getCoinbaseAddress();
|
||||||
const acctsFromConfig = AccountParser.parseAccountsConfig(this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, accounts);
|
const acctsFromConfig = AccountParser.parseAccountsConfig(this.embark.config.blockchainConfig.accounts, web3, dappPath(), this.logger, accounts);
|
||||||
const accountsWithBalance = accounts.map((address) => {
|
const accountsWithBalance = accounts.map((address) => {
|
||||||
const acctFromConfig = acctsFromConfig.find((acctCfg) => acctCfg.address === address);
|
const acctFromConfig = acctsFromConfig.find((acctCfg) => acctCfg.address === address);
|
||||||
|
@ -82,4 +82,54 @@ export default class AccountsManager {
|
||||||
this.logger.error(__("Error funding accounts"), err.message || err);
|
this.logger.error(__("Error funding accounts"), err.message || err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findAccountWithMostFunds() {
|
||||||
|
const web3 = await this.web3;
|
||||||
|
const accounts = await web3.eth.getAccounts();
|
||||||
|
let highestBalance = {
|
||||||
|
balance: web3.utils.toBN(0),
|
||||||
|
account: ""
|
||||||
|
};
|
||||||
|
for (const account of accounts) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
const balance = web3.utils.toBN(await web3.eth.getBalance(account));
|
||||||
|
if (balance.gt(highestBalance.balance)) {
|
||||||
|
highestBalance = { balance, account };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return highestBalance.account;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAlternativeCoinbase() {
|
||||||
|
try {
|
||||||
|
return this.findAccountWithMostFunds();
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Error getting coinbase address: ${err.message || err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCoinbaseAddress() {
|
||||||
|
const web3 = await this.web3;
|
||||||
|
try {
|
||||||
|
const coinbaseAddress = await web3.eth.getCoinbase();
|
||||||
|
// if the blockchain returns a zeroed address, we can find the account
|
||||||
|
// with the most funds and use that as the "from" account to txfer
|
||||||
|
// funds.
|
||||||
|
if (!coinbaseAddress ||
|
||||||
|
web3.utils.hexToNumberString(coinbaseAddress) === "0" || // matches 0x0 and 0x00000000000000000000000000000000000000
|
||||||
|
(await web3.eth.getBalance(coinbaseAddress)) === "0"
|
||||||
|
) {
|
||||||
|
return this.findAlternativeCoinbase();
|
||||||
|
}
|
||||||
|
return coinbaseAddress;
|
||||||
|
} catch (err) {
|
||||||
|
// if the blockchain doesn't support 'eth_coinbase' RPC commands,
|
||||||
|
// we can find the account with the most funds and use that as the
|
||||||
|
// "from" account to txfer funds.
|
||||||
|
if (err.message.includes("The method eth_coinbase does not exist/is not available")) {
|
||||||
|
return this.findAlternativeCoinbase();
|
||||||
|
}
|
||||||
|
throw new Error(`Error finding coinbase address: ${err.message || err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue