|
|
|
@ -29,9 +29,10 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
super() |
|
|
|
|
this.opts = opts |
|
|
|
|
this.state = { network: 'loading' } |
|
|
|
|
let initState = opts.initState || {} |
|
|
|
|
|
|
|
|
|
// observable state store
|
|
|
|
|
this.store = new ObservableStore(opts.initState) |
|
|
|
|
this.store = new ObservableStore(initState) |
|
|
|
|
|
|
|
|
|
// config manager
|
|
|
|
|
this.configManager = new ConfigManager({ |
|
|
|
@ -41,7 +42,7 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
|
|
|
|
|
// rpc provider
|
|
|
|
|
this.provider = this.initializeProvider(opts) |
|
|
|
|
this.provider.on('block', this.processBlock.bind(this)) |
|
|
|
|
this.provider.on('block', this.logBlock.bind(this)) |
|
|
|
|
this.provider.on('error', this.getNetwork.bind(this)) |
|
|
|
|
|
|
|
|
|
// eth data query tools
|
|
|
|
@ -50,6 +51,7 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
|
|
|
|
|
// key mgmt
|
|
|
|
|
this.keyringController = new KeyringController({ |
|
|
|
|
initState: initState.KeyringController, |
|
|
|
|
ethStore: this.ethStore, |
|
|
|
|
configManager: this.configManager, |
|
|
|
|
getNetwork: this.getStateNetwork.bind(this), |
|
|
|
@ -97,6 +99,9 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
this.keyringController.on('update', this.sendUpdate.bind(this)) |
|
|
|
|
this.txManager.on('update', this.sendUpdate.bind(this)) |
|
|
|
|
this.messageManager.on('update', this.sendUpdate.bind(this)) |
|
|
|
|
this.keyringController.store.subscribe((state) => { |
|
|
|
|
this.store.updateState({ KeyringController: state }) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -139,9 +144,7 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
const result = { selectedAccount: undefined } |
|
|
|
|
try { |
|
|
|
|
result.selectedAccount = state.config.selectedAccount |
|
|
|
|
} catch (_) { |
|
|
|
|
// thats fine, im sure it will be there next time...
|
|
|
|
|
} |
|
|
|
|
} catch (_) {} |
|
|
|
|
return result |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -162,7 +165,9 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
this.txManager.getState(), |
|
|
|
|
this.messageManager.getState(), |
|
|
|
|
keyringControllerState, |
|
|
|
|
this.noticeController.getState(), { |
|
|
|
|
this.noticeController.getState(), |
|
|
|
|
{ |
|
|
|
|
shapeShiftTxList: this.configManager.getShapeShiftTxList(), |
|
|
|
|
lostAccounts: this.configManager.getLostAccounts(), |
|
|
|
|
} |
|
|
|
|
) |
|
|
|
@ -268,6 +273,13 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setupPublicConfig (outStream) { |
|
|
|
|
pipe( |
|
|
|
|
this.publicConfigStore, |
|
|
|
|
outStream |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sendUpdate () { |
|
|
|
|
this.getState() |
|
|
|
|
.then((state) => { |
|
|
|
@ -388,31 +400,90 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
}).catch((err) => cb(err)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setupPublicConfig (outStream) { |
|
|
|
|
pipe( |
|
|
|
|
this.publicConfigStore, |
|
|
|
|
outStream |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
markAccountsFound (cb) { |
|
|
|
|
this.configManager.setLostAccounts([]) |
|
|
|
|
this.sendUpdate() |
|
|
|
|
cb(null, this.getState()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Log blocks
|
|
|
|
|
processBlock (block) { |
|
|
|
|
if (global.METAMASK_DEBUG) { |
|
|
|
|
console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) |
|
|
|
|
// Migrate Old Vault If Any
|
|
|
|
|
// @string password
|
|
|
|
|
//
|
|
|
|
|
// returns Promise()
|
|
|
|
|
//
|
|
|
|
|
// Temporary step used when logging in.
|
|
|
|
|
// Checks if old style (pre-3.0.0) Metamask Vault exists.
|
|
|
|
|
// If so, persists that vault in the new vault format
|
|
|
|
|
// with the provided password, so the other unlock steps
|
|
|
|
|
// may be completed without interruption.
|
|
|
|
|
migrateOldVaultIfAny (password) { |
|
|
|
|
|
|
|
|
|
if (!this.checkIfShouldMigrate()) { |
|
|
|
|
return Promise.resolve(password) |
|
|
|
|
} |
|
|
|
|
this.verifyNetwork() |
|
|
|
|
|
|
|
|
|
const keyringController = this.keyringController |
|
|
|
|
|
|
|
|
|
return this.idStoreMigrator.migratedVaultForPassword(password) |
|
|
|
|
.then(this.restoreOldVaultAccounts.bind(this)) |
|
|
|
|
.then(this.restoreOldLostAccounts.bind(this)) |
|
|
|
|
.then(keyringController.persistAllKeyrings.bind(keyringController, password)) |
|
|
|
|
.then(() => password) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
verifyNetwork () { |
|
|
|
|
// Check network when restoring connectivity:
|
|
|
|
|
if (this.state.network === 'loading') { |
|
|
|
|
this.getNetwork() |
|
|
|
|
checkIfShouldMigrate() { |
|
|
|
|
return !!this.configManager.getWallet() && !this.configManager.getVault() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
restoreOldVaultAccounts(migratorOutput) { |
|
|
|
|
const { serialized } = migratorOutput |
|
|
|
|
return this.keyringController.restoreKeyring(serialized) |
|
|
|
|
.then(() => migratorOutput) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// config
|
|
|
|
|
restoreOldLostAccounts(migratorOutput) { |
|
|
|
|
const { lostAccounts } = migratorOutput |
|
|
|
|
if (lostAccounts) { |
|
|
|
|
this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address)) |
|
|
|
|
return this.importLostAccounts(migratorOutput) |
|
|
|
|
} |
|
|
|
|
return Promise.resolve(migratorOutput) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// IMPORT LOST ACCOUNTS
|
|
|
|
|
// @Object with key lostAccounts: @Array accounts <{ address, privateKey }>
|
|
|
|
|
// Uses the array's private keys to create a new Simple Key Pair keychain
|
|
|
|
|
// and add it to the keyring controller.
|
|
|
|
|
importLostAccounts ({ lostAccounts }) { |
|
|
|
|
const privKeys = lostAccounts.map(acct => acct.privateKey) |
|
|
|
|
return this.keyringController.restoreKeyring({ |
|
|
|
|
type: 'Simple Key Pair', |
|
|
|
|
data: privKeys, |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// disclaimer
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
agreeToDisclaimer (cb) { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setConfirmedDisclaimer(true) |
|
|
|
|
cb() |
|
|
|
|
} catch (err) { |
|
|
|
|
cb(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
resetDisclaimer () { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setConfirmedDisclaimer(false) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error(e) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setTOSHash (hash) { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setTOSHash(hash) |
|
|
|
@ -433,23 +504,16 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// disclaimer
|
|
|
|
|
|
|
|
|
|
agreeToDisclaimer (cb) { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setConfirmedDisclaimer(true) |
|
|
|
|
cb() |
|
|
|
|
} catch (err) { |
|
|
|
|
cb(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//
|
|
|
|
|
// config
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
resetDisclaimer () { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setConfirmedDisclaimer(false) |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error(e) |
|
|
|
|
// Log blocks
|
|
|
|
|
logBlock (block) { |
|
|
|
|
if (global.METAMASK_DEBUG) { |
|
|
|
|
console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) |
|
|
|
|
} |
|
|
|
|
this.verifyNetwork() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setCurrentFiat (fiat, cb) { |
|
|
|
@ -477,24 +541,6 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
}, 300000) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// called from popup
|
|
|
|
|
setRpcTarget (rpcTarget) { |
|
|
|
|
this.configManager.setRpcTarget(rpcTarget) |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
this.getNetwork() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setProviderType (type) { |
|
|
|
|
this.configManager.setProviderType(type) |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
this.getNetwork() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
useEtherscanProvider () { |
|
|
|
|
this.configManager.useEtherscanProvider() |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buyEth (address, amount) { |
|
|
|
|
if (!amount) amount = '5' |
|
|
|
|
|
|
|
|
@ -514,25 +560,6 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
this.configManager.createShapeShiftTx(depositAddress, depositType) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getNetwork (err) { |
|
|
|
|
if (err) { |
|
|
|
|
this.state.network = 'loading' |
|
|
|
|
this.sendUpdate() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { |
|
|
|
|
if (err) { |
|
|
|
|
this.state.network = 'loading' |
|
|
|
|
return this.sendUpdate() |
|
|
|
|
} |
|
|
|
|
if (global.METAMASK_DEBUG) { |
|
|
|
|
console.log('web3.getNetwork returned ' + network) |
|
|
|
|
} |
|
|
|
|
this.state.network = network |
|
|
|
|
this.sendUpdate() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setGasMultiplier (gasMultiplier, cb) { |
|
|
|
|
try { |
|
|
|
|
this.configManager.setGasMultiplier(gasMultiplier) |
|
|
|
@ -542,69 +569,55 @@ module.exports = class MetamaskController extends EventEmitter { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getStateNetwork () { |
|
|
|
|
return this.state.network |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
markAccountsFound (cb) { |
|
|
|
|
this.configManager.setLostAccounts([]) |
|
|
|
|
this.sendUpdate() |
|
|
|
|
cb(null, this.getState()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Migrate Old Vault If Any
|
|
|
|
|
// @string password
|
|
|
|
|
//
|
|
|
|
|
// returns Promise()
|
|
|
|
|
// network
|
|
|
|
|
//
|
|
|
|
|
// Temporary step used when logging in.
|
|
|
|
|
// Checks if old style (pre-3.0.0) Metamask Vault exists.
|
|
|
|
|
// If so, persists that vault in the new vault format
|
|
|
|
|
// with the provided password, so the other unlock steps
|
|
|
|
|
// may be completed without interruption.
|
|
|
|
|
migrateOldVaultIfAny (password) { |
|
|
|
|
|
|
|
|
|
if (!this.checkIfShouldMigrate()) { |
|
|
|
|
return Promise.resolve(password) |
|
|
|
|
verifyNetwork () { |
|
|
|
|
// Check network when restoring connectivity:
|
|
|
|
|
if (this.state.network === 'loading') { |
|
|
|
|
this.getNetwork() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const keyringController = this.keyringController |
|
|
|
|
|
|
|
|
|
return this.idStoreMigrator.migratedVaultForPassword(password) |
|
|
|
|
.then(this.restoreOldVaultAccounts.bind(this)) |
|
|
|
|
.then(this.restoreOldLostAccounts.bind(this)) |
|
|
|
|
.then(keyringController.persistAllKeyrings.bind(keyringController, password)) |
|
|
|
|
.then(() => password) |
|
|
|
|
setRpcTarget (rpcTarget) { |
|
|
|
|
this.configManager.setRpcTarget(rpcTarget) |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
this.getNetwork() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
checkIfShouldMigrate() { |
|
|
|
|
return !!this.configManager.getWallet() && !this.configManager.getVault() |
|
|
|
|
setProviderType (type) { |
|
|
|
|
this.configManager.setProviderType(type) |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
this.getNetwork() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
restoreOldVaultAccounts(migratorOutput) { |
|
|
|
|
const { serialized } = migratorOutput |
|
|
|
|
return this.keyringController.restoreKeyring(serialized) |
|
|
|
|
.then(() => migratorOutput) |
|
|
|
|
useEtherscanProvider () { |
|
|
|
|
this.configManager.useEtherscanProvider() |
|
|
|
|
extension.runtime.reload() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
restoreOldLostAccounts(migratorOutput) { |
|
|
|
|
const { lostAccounts } = migratorOutput |
|
|
|
|
if (lostAccounts) { |
|
|
|
|
this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address)) |
|
|
|
|
return this.importLostAccounts(migratorOutput) |
|
|
|
|
getStateNetwork () { |
|
|
|
|
return this.state.network |
|
|
|
|
} |
|
|
|
|
return Promise.resolve(migratorOutput) |
|
|
|
|
|
|
|
|
|
getNetwork (err) { |
|
|
|
|
if (err) { |
|
|
|
|
this.state.network = 'loading' |
|
|
|
|
this.sendUpdate() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// IMPORT LOST ACCOUNTS
|
|
|
|
|
// @Object with key lostAccounts: @Array accounts <{ address, privateKey }>
|
|
|
|
|
// Uses the array's private keys to create a new Simple Key Pair keychain
|
|
|
|
|
// and add it to the keyring controller.
|
|
|
|
|
importLostAccounts ({ lostAccounts }) { |
|
|
|
|
const privKeys = lostAccounts.map(acct => acct.privateKey) |
|
|
|
|
return this.keyringController.restoreKeyring({ |
|
|
|
|
type: 'Simple Key Pair', |
|
|
|
|
data: privKeys, |
|
|
|
|
this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { |
|
|
|
|
if (err) { |
|
|
|
|
this.state.network = 'loading' |
|
|
|
|
return this.sendUpdate() |
|
|
|
|
} |
|
|
|
|
if (global.METAMASK_DEBUG) { |
|
|
|
|
console.log('web3.getNetwork returned ' + network) |
|
|
|
|
} |
|
|
|
|
this.state.network = network |
|
|
|
|
this.sendUpdate() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|