@@ -26,6 +26,7 @@ export default class AccountsManager {
26
26
// reset accounts backing variable as the accounts in config may have changed and
27
27
// web.eth.getAccounts may return a different value now
28
28
this . _accounts = null ;
29
+ this . _web3 = null ;
29
30
30
31
// as the accounts may have changed, we need to fund the accounts again
31
32
await this . parseAndFundAccounts ( ) ;
@@ -54,14 +55,13 @@ export default class AccountsManager {
54
55
}
55
56
56
57
private async parseAndFundAccounts ( ) {
57
- const web3 = await this . web3 ;
58
58
const accounts = await this . accounts ;
59
-
60
59
if ( ! accounts . length || ! this . embark . config . blockchainConfig . isDev ) {
61
60
return ;
62
61
}
63
62
try {
64
- const coinbase = await web3 . eth . getCoinbase ( ) ;
63
+ const web3 = await this . web3 ;
64
+ const coinbase = await this . getCoinbaseAddress ( ) ;
65
65
const acctsFromConfig = AccountParser . parseAccountsConfig ( this . embark . config . blockchainConfig . accounts , web3 , dappPath ( ) , this . logger , accounts ) ;
66
66
const accountsWithBalance = accounts . map ( ( address ) => {
67
67
const acctFromConfig = acctsFromConfig . find ( ( acctCfg ) => acctCfg . address === address ) ;
@@ -82,4 +82,54 @@ export default class AccountsManager {
82
82
this . logger . error ( __ ( "Error funding accounts" ) , err . message || err ) ;
83
83
}
84
84
}
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
+ }
85
135
}
0 commit comments