@@ -26,6 +26,7 @@ export default class AccountsManager {
2626 // reset accounts backing variable as the accounts in config may have changed and
2727 // web.eth.getAccounts may return a different value now
2828 this . _accounts = null ;
29+ this . _web3 = null ;
2930
3031 // as the accounts may have changed, we need to fund the accounts again
3132 await this . parseAndFundAccounts ( ) ;
@@ -54,14 +55,13 @@ export default class AccountsManager {
5455 }
5556
5657 private async parseAndFundAccounts ( ) {
57- const web3 = await this . web3 ;
5858 const accounts = await this . accounts ;
59-
6059 if ( ! accounts . length || ! this . embark . config . blockchainConfig . isDev ) {
6160 return ;
6261 }
6362 try {
64- const coinbase = await web3 . eth . getCoinbase ( ) ;
63+ const web3 = await this . web3 ;
64+ const coinbase = await this . getCoinbaseAddress ( ) ;
6565 const acctsFromConfig = AccountParser . parseAccountsConfig ( this . embark . config . blockchainConfig . accounts , web3 , dappPath ( ) , this . logger , accounts ) ;
6666 const accountsWithBalance = accounts . map ( ( address ) => {
6767 const acctFromConfig = acctsFromConfig . find ( ( acctCfg ) => acctCfg . address === address ) ;
@@ -82,4 +82,54 @@ export default class AccountsManager {
8282 this . logger . error ( __ ( "Error funding accounts" ) , err . message || err ) ;
8383 }
8484 }
85+
86+ async findAccountWithMostFunds ( ) {
87+ const web3 = await this . web3 ;
88+ const accounts = await web3 . eth . getAccounts ( ) ;
89+ let highestBalance = {
90+ balance : web3 . utils . toBN ( 0 ) ,
91+ account : ""
92+ } ;
93+ for ( const account of accounts ) {
94+ // eslint-disable-next-line no-await-in-loop
95+ const balance = web3 . utils . toBN ( await web3 . eth . getBalance ( account ) ) ;
96+ if ( balance . gt ( highestBalance . balance ) ) {
97+ highestBalance = { balance, account } ;
98+ }
99+ }
100+ return highestBalance . account ;
101+ }
102+
103+ async findAlternativeCoinbase ( ) {
104+ try {
105+ return this . findAccountWithMostFunds ( ) ;
106+ } catch ( err ) {
107+ throw new Error ( `Error getting coinbase address: ${ err . message || err } ` ) ;
108+ }
109+ }
110+
111+ async getCoinbaseAddress ( ) {
112+ const web3 = await this . web3 ;
113+ try {
114+ const coinbaseAddress = await web3 . eth . getCoinbase ( ) ;
115+ // if the blockchain returns a zeroed address, we can find the account
116+ // with the most funds and use that as the "from" account to txfer
117+ // funds.
118+ if ( ! coinbaseAddress ||
119+ web3 . utils . hexToNumberString ( coinbaseAddress ) === "0" || // matches 0x0 and 0x00000000000000000000000000000000000000
120+ ( await web3 . eth . getBalance ( coinbaseAddress ) ) === "0"
121+ ) {
122+ return this . findAlternativeCoinbase ( ) ;
123+ }
124+ return coinbaseAddress ;
125+ } catch ( err ) {
126+ // if the blockchain doesn't support 'eth_coinbase' RPC commands,
127+ // we can find the account with the most funds and use that as the
128+ // "from" account to txfer funds.
129+ if ( err . message . includes ( "The method eth_coinbase does not exist/is not available" ) ) {
130+ return this . findAlternativeCoinbase ( ) ;
131+ }
132+ throw new Error ( `Error finding coinbase address: ${ err . message || err } ` ) ;
133+ }
134+ }
85135}
0 commit comments